commit cd3b53759e866da476505f599d3224d69a271e68 Author: 被淹死的鱼 <13423737683@163.com> Date: Wed Mar 11 18:26:29 2026 +0800 第一次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a56a8aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.iml +/local.properties +.idea +.DS_Store +build +/captures +.externalNativeBuild +.gradle/ + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/agconnect-services.json b/app/agconnect-services.json new file mode 100644 index 0000000..e3b74a8 --- /dev/null +++ b/app/agconnect-services.json @@ -0,0 +1,96 @@ +{ + "agcgw":{ + "backurl":"connect-drcn.hispace.hicloud.com", + "url":"connect-drcn.dbankcloud.cn", + "websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com", + "websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn" + }, + "agcgw_all":{ + "CN":"connect-drcn.dbankcloud.cn", + "CN_back":"connect-drcn.hispace.hicloud.com", + "DE":"connect-dre.dbankcloud.cn", + "DE_back":"connect-dre.hispace.hicloud.com", + "RU":"connect-drru.hispace.dbankcloud.ru", + "RU_back":"connect-drru.hispace.dbankcloud.cn", + "SG":"connect-dra.dbankcloud.cn", + "SG_back":"connect-dra.hispace.hicloud.com" + }, + "websocketgw_all":{ + "CN":"connect-ws-drcn.hispace.dbankcloud.cn", + "CN_back":"connect-ws-drcn.hispace.dbankcloud.com", + "DE":"connect-ws-dre.hispace.dbankcloud.cn", + "DE_back":"connect-ws-dre.hispace.dbankcloud.com", + "RU":"connect-ws-drru.hispace.dbankcloud.ru", + "RU_back":"connect-ws-drru.hispace.dbankcloud.cn", + "SG":"connect-ws-dra.hispace.dbankcloud.cn", + "SG_back":"connect-ws-dra.hispace.dbankcloud.com" + }, + "client":{ + "cp_id":"30086000686564064", + "product_id":"388421841221488221", + "client_id":"1162386077042888192", + "client_secret":"F0EC8EDDA52B38AE144E494CB505C344801B5DE325B08BDA0D7649B1983DA93F", + "project_id":"388421841221488221", + "app_id":"108318391", + "api_key":"DAEDACb//MwJd8VoONZ8qwwwfyYb5+/Oeh0YImMODrMKXBRAkqUXPO+jp44QOcybtAsiOgIaYZ2Wgor4WLQTbhJYtLxHmmFE9Dy/xw==", + "package_name":"com.fengliyan.tianlesue" + }, + "oauth_client":{ + "client_id":"108318391", + "client_type":1 + }, + "app_info":{ + "app_id":"108318391", + "package_name":"com.fengliyan.tianlesue" + }, + "service":{ + "analytics":{ + "collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", + "collector_url_ru":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com", + "collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn", + "collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn", + "collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", + "resource_id":"p1", + "channel_id":"" + }, + "edukit":{ + "edu_url":"edukit.edu.cloud.huawei.com.cn", + "dh_url":"edukit.edu.cloud.huawei.com.cn" + }, + "search":{ + "url":"https://search-drcn.cloud.huawei.com" + }, + "cloudstorage":{ + "storage_url_sg_back":"https://agc-storage-dra.cloud.huawei.asia", + "storage_url_ru_back":"https://agc-storage-drru.cloud.huawei.ru", + "storage_url_ru":"https://agc-storage-drru.cloud.huawei.ru", + "storage_url_de_back":"https://agc-storage-dre.cloud.huawei.eu", + "storage_url_de":"https://ops-dre.agcstorage.link", + "storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn", + "storage_url_sg":"https://ops-dra.agcstorage.link", + "storage_url_cn_back":"https://agc-storage-drcn.cloud.huawei.com.cn", + "storage_url_cn":"https://agc-storage-drcn.platform.dbankcloud.cn" + }, + "ml":{ + "mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn" + } + }, + "region":"CN", + "configuration_version":"3.0", + "appInfos":[ + { + "package_name":"com.fengliyan.tianlesue", + "client":{ + "app_id":"108318391" + }, + "app_info":{ + "package_name":"com.fengliyan.tianlesue", + "app_id":"108318391" + }, + "oauth_client":{ + "client_type":1, + "client_id":"108318391" + } + } + ] +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..66e89fc --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,402 @@ +apply plugin: 'com.android.application' +apply plugin: 'com.huawei.agconnect' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'com.hihonor.mcs.asplugin' + +//apply plugin: 'android-junk-code' +//androidJunkCode { +// def config = { +// //变体名称,如果没有设置productFlavors就是buildType名称,如果有设置productFlavors就是flavor+buildType,例如(freeRelease、proRelease) +// packageBase = "com.live.siyu" //生成java类根包名 +// packageCount = 60 //生成包数量 +// activityCountPerPackage = 6 //每个包下生成Activity类数量 +// excludeActivityJavaFile = false +// //是否排除生成Activity的Java文件,默认false(layout和写入AndroidManifest.xml还会执行),主要用于处理类似神策全埋点编译过慢问题 +// otherCountPerPackage = 60 //每个包下生成其它类的数量 +// methodCountPerClass = 60 //每个类下生成方法数量 +// resPrefix = "sy_" //生成的layout、drawable、string等资源名前缀 +// drawableCount = 300 //生成drawable资源数量 +// stringCount = 300 //生成string数量 +// } +// variantConfig { +// devDebug config +// ossRelease config +// } +//} + +android { + aaptOptions.cruncherEnabled = false + aaptOptions.useNewCruncher = false + compileSdkVersion 31 + buildToolsVersion "30.0.3" + viewBinding { + enabled = true + } + useLibrary 'org.apache.http.legacy' + defaultConfig { + applicationId "com.fengliyan.tianlesue" + minSdkVersion 24 + targetSdkVersion 30 + versionCode 38 + versionName "2.5.1" + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' + flavorDimensions "versionCode" + buildConfigField "String", "AUTH_SECRET", '"tX1pY3+d9GOsDdek6c8EkqlBagajAzzq4Yl8xWzKxE66qzaa51BRukuNO66MPcv92lK5tTifKP6md8Jn/vIcgQCLpJWhr4vKvcGeOmBFIPmdo/++elnHTJdJ10RSRN8fDaQVUhX7Ap3KoPQ4n/oSUNSpa/HKZihCLQK31vyNCL/GZ4bGijb2e63JDN4GbUOP1d7yw4vbaNEA883Da+CQ+CyYW4aXWuLca/1ngoszOw3wRFhe/ZMVDhDRRMc7Bpp/+judD4ehwydRzLprBpVSQufZV6XAUpec3V7eJRH3FHGXE4fwtZK4BA=="' + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a" + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + configurations.all { + resolutionStrategy { + force 'androidx.core:core:1.7.0' + } + } + packagingOptions { + pickFirst 'lib/arm64-v8a/libc++_shared.so' + pickFirst 'lib/armeabi-v7a/libc++_shared.so' + } + + signingConfigs { + release { + // default keystore file, PLZ config file path in local.properties + //Properties properties = new Properties() + //加载本地local.properties文件 + /*if(rootProject.file("local.properties").exists()) { + properties.load(rootProject.file("local.properties").newDataInputStream()) + } + storeFile file(properties.get("storeFile") ?: System.getenv("FLOW_CERTIFICATE_FILE")) + storePassword properties.get("storePassword") ?: System.getenv("FLOW_KEYSTORE_PASS") + keyAlias properties.get("keyAlias") ?: System.getenv("FLOW_ALIAS_NAME") + keyPassword properties.get("keyPassword") ?: System.getenv("FLOW_ALIAS_PASS")*/ + + storeFile file("xiayue.jks") + storePassword 'Chenqihong3' + keyAlias 'chenqihong3' + keyPassword 'Chenqihong3' + v1SigningEnabled true + v2SigningEnabled true + } + } + + + //更改打包名字 + applicationVariants.all { variant -> + variant.outputs.all { + //qingyu_v1.4.5_oppo_id1389900 +// def code = getBuildConfigFieldValue(variant, "InviteCode") +// def codeReplace = code.replace("\"", "").replace("\"", "") +// def fileName = "qingyu_v${versionName}_${variant.productFlavors[0].name}_id${codeReplace}_${buildType.name}.apk" + def fileName = "siyu_v${versionName}_${variant.productFlavors[0].name}_${buildType.name}.apk" + outputFileName = fileName + } + variant.mergeAssetsProvider.configure { + doLast { + delete(fileTree(dir: outputDir, + includes: ['model/ai_bgseg_green.bundle', + 'model/ai_face_processor_lite.bundle', + 'model/ai_hairseg.bundle', + 'model/ai_hand_processor.bundle', + 'model/ai_human_processor_mb_fast.bundle', + 'graphics/face_makeup.bundle', + 'graphics/body_slim.bundle', + 'graphics/controller_cpp.bundle', + 'graphics/fuzzytoonfilter.bundle', + 'graphics/tongue.bundle', + 'graphics/fxaa.bundle'])) + } + } + } + + buildTypes { + release { + minifyEnabled false +// shrinkResources true +// useProguard true +// zipAlignEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + } + + debug { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + } + } + + repositories { + flatDir { + dirs 'libs' + } + } + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + + main.assets.srcDirs += ['src/main/assets'] + main.res.srcDirs += ['src/mian/res', 'src/main/filters/res'] + } + + lintOptions { + checkReleaseBuilds false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError false + } + + productFlavors { +// dev { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "true" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "oss", +// APP_NAME : "私语" +// ] +// } + oss { + applicationId "com.fengliyan.tianlesue" + buildConfigField "boolean", "IS_DEV", "false" + buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' + buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' + buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' + manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", + MARKET_VALUE : "oss", + APP_NAME : "私语" + ] + } + +// vivo { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "vivo", +// APP_NAME : "私语" +// ] +// } +// oppo { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "oppo", +// APP_NAME : "私语", +// ] +// } +// xiaomi { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "xiaomi", +// APP_NAME : "私语" +// ] +// } +// yingyongbao { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "yingyongbao", +// APP_NAME : "私语" +// ] +// } +// huawei { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuSocialPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuSocialAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuSocialVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "huawei", +// APP_NAME : "私语交友" +// ] +// } +// honor { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "honor", +// APP_NAME : "私语" +// ] +// } +// meizu { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "meizu", +// APP_NAME : "私语" +// ] +// } +// baiduss { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "baiduss", +// APP_NAME : "私语" +// ] +// } +// baiduxxl { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "baiduxxl", +// APP_NAME : "私语" +// ] +// } +// threesixzero { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "\"360\"", +// APP_NAME : "私语" +// ] +// } +// ali { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "ali", +// APP_NAME : "私语" +// ] +// } +// kuaishou { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "kuaishou", +// APP_NAME : "私语" +// ] +// } +// douyin { +// applicationId "com.fengliyan.tianlesue" +// buildConfigField "boolean", "IS_DEV", "false" +// buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' +// buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' +// buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' +// manifestPlaceholders = [APPLICATION_ID: "com.fengliyan.tianlesue", +// MARKET_VALUE : "douyin", +// APP_NAME : "私语" +// ] +// } + } + + dependencies { + //noinspection GradleCompatible + implementation 'com.github.gzu-liyujiang:Android_CN_OAID:4.2.4' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04' + implementation 'androidx.constraintlayout:constraintlayout:1.1.2' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.androidx.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' + implementation 'com.facebook.fresco:fresco:1.8.1' + implementation 'com.contrarywind:Android-PickerView:4.0.1' + implementation 'com.google.code.gson:gson:2.8.2' + implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' + implementation 'io.reactivex.rxjava2:rxjava:2.1.12' + implementation 'in.srain.cube:ultra-ptr:1.0.11' + implementation 'commons-io:commons-io:2.6' + implementation 'me.relex:photodraweeview:1.1.3' + implementation 'me.himanshusoni.quantityview:quantity-view:1.2.0' + implementation project(path: ':uikit') + implementation project(path: ':location') + implementation project(path: ':http') + implementation project(path: ':share') + implementation project(path: ':device') + implementation project(path: ':messaging') + implementation project(path: ':storage') + implementation project(path: ':yunxinkit') + implementation project(':faceunity') + //EventBus + implementation 'de.greenrobot:eventbus:2.4.0' + implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:6.8.0' + //魅族推送 + implementation 'com.meizu.flyme.internet:push-internal:3.6.3@aar' + implementation 'de.hdodenhof:circleimageview:2.2.0' + implementation 'org.adw.library:discrete-seekbar:1.0.1' + //设置状态栏颜色 + implementation 'com.githang:status-bar-compat:0.7' + //banner + implementation 'com.youth.banner:banner:1.4.10' + //最新版本 + //仿微信图片预览 + implementation 'com.google.android.material:material:1.4.0' + + implementation fileTree(include: ['*.aar', '*.jar'], exclude: [], dir: 'libs') + + implementation 'com.huawei.hms:push:6.12.0.300' //华为 + implementation 'com.hihonor.mcs:push:7.0.61.303' + implementation 'com.github.yyued:SVGAPlayer-Android:2.5.12'//svga + + implementation 'com.tencent.bugly:crashreport:4.0.4' + implementation 'com.github.getActivity:XXPermissions:13.6' + + + implementation 'me.jessyan:autosize:1.2.1' + //圆角控件 + implementation 'com.flyco.roundview:FlycoRoundView_Lib:1.1.4@aar' + implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6' + implementation 'com.github.eralpyucel:CircleProgressView:v1.1' + //implementation 'com.github.CarGuo.GSYVideoPlayer:GSYVideoPlayer:v8.1.0' + implementation 'com.shuyu:GSYVideoPlayer:8.1.0' + + implementation 'com.googlecode.mp4parser:isoparser:1.1.21' + + implementation "io.agora.rtc:full-rtc-basic:3.6.2" +// implementation 'commons-codec:commons-codec:1.6' + implementation 'io.github.happylishang:antifake:1.7.0' + implementation 'com.blankj:utilcodex:1.31.1' + implementation 'com.airbnb.android:lottie:5.2.0' +// implementation 'com.mcxiaoke.packer-ng:helper:2.0.1' +// implementation(name: 'alipaySdk-15.8.03.210428205839', ext: 'aar') + // 商业化转化组件(必须) + implementation 'com.bytedance.ads:AppConvert:2.0.0' + implementation 'com.ryan.github:menupopupview:1.0.0' + implementation 'io.github.scwang90:refresh-layout-kernel:3.0.0-alpha' + implementation 'io.github.scwang90:refresh-footer-classics:3.0.0-alpha' + implementation 'com.devzld:expandlayout:1.0.0' + implementation 'io.github.lucksiege:pictureselector:v3.11.2' + implementation 'com.github.Dimezis:BlurView:version-3.1.0' + } +} \ No newline at end of file diff --git a/app/libs/APSecuritySDK-deepSec-7.0.1.20240528.jiagu.aar b/app/libs/APSecuritySDK-deepSec-7.0.1.20240528.jiagu.aar new file mode 100644 index 0000000..7f6b077 Binary files /dev/null and b/app/libs/APSecuritySDK-deepSec-7.0.1.20240528.jiagu.aar differ diff --git a/app/libs/Android-AliyunFaceGuard-10052.2.aar b/app/libs/Android-AliyunFaceGuard-10052.2.aar new file mode 100644 index 0000000..6a71ec4 Binary files /dev/null and b/app/libs/Android-AliyunFaceGuard-10052.2.aar differ diff --git a/app/libs/HTProtectLib-5.5.9.1.aar b/app/libs/HTProtectLib-5.5.9.1.aar new file mode 100644 index 0000000..f5b93bd Binary files /dev/null and b/app/libs/HTProtectLib-5.5.9.1.aar differ diff --git a/app/libs/MiPush_SDK_Client_6_0_1-C_3rd.aar b/app/libs/MiPush_SDK_Client_6_0_1-C_3rd.aar new file mode 100644 index 0000000..256da02 Binary files /dev/null and b/app/libs/MiPush_SDK_Client_6_0_1-C_3rd.aar differ diff --git a/app/libs/alipaysdk-15.8.03.210428205839.aar b/app/libs/alipaysdk-15.8.03.210428205839.aar new file mode 100644 index 0000000..b2cf3f4 Binary files /dev/null and b/app/libs/alipaysdk-15.8.03.210428205839.aar differ diff --git a/app/libs/aliyun-base-2.3.32.1.250219103019.aar b/app/libs/aliyun-base-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..99c51ec Binary files /dev/null and b/app/libs/aliyun-base-2.3.32.1.250219103019.aar differ diff --git a/app/libs/aliyun-facade-2.3.32.1.250219103019.aar b/app/libs/aliyun-facade-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..0a6ad0c Binary files /dev/null and b/app/libs/aliyun-facade-2.3.32.1.250219103019.aar differ diff --git a/app/libs/aliyun-face-2.3.32.1.250219103019.aar b/app/libs/aliyun-face-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..09a6179 Binary files /dev/null and b/app/libs/aliyun-face-2.3.32.1.250219103019.aar differ diff --git a/app/libs/aliyun-faceaudio-2.3.32.1.250219103019.aar b/app/libs/aliyun-faceaudio-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..40c7d07 Binary files /dev/null and b/app/libs/aliyun-faceaudio-2.3.32.1.250219103019.aar differ diff --git a/app/libs/aliyun-facelanguage-2.3.32.1.250219103019.aar b/app/libs/aliyun-facelanguage-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..601eb24 Binary files /dev/null and b/app/libs/aliyun-facelanguage-2.3.32.1.250219103019.aar differ diff --git a/app/libs/aliyun-facequality-2.3.32.1.250219103019.aar b/app/libs/aliyun-facequality-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..8ff0254 Binary files /dev/null and b/app/libs/aliyun-facequality-2.3.32.1.250219103019.aar differ diff --git a/app/libs/aliyun-photinus-2.3.32.1.250219103019.aar b/app/libs/aliyun-photinus-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..3662a99 Binary files /dev/null and b/app/libs/aliyun-photinus-2.3.32.1.250219103019.aar differ diff --git a/app/libs/aliyun-wishverify-2.3.32.1.250219103019.aar b/app/libs/aliyun-wishverify-2.3.32.1.250219103019.aar new file mode 100644 index 0000000..9b059ae Binary files /dev/null and b/app/libs/aliyun-wishverify-2.3.32.1.250219103019.aar differ diff --git a/app/libs/arm64-v8a/libNetHTProtect.so b/app/libs/arm64-v8a/libNetHTProtect.so new file mode 100644 index 0000000..c430e42 Binary files /dev/null and b/app/libs/arm64-v8a/libNetHTProtect.so differ diff --git a/app/libs/arm64-v8a/libhtpcrash.so b/app/libs/arm64-v8a/libhtpcrash.so new file mode 100644 index 0000000..a296522 Binary files /dev/null and b/app/libs/arm64-v8a/libhtpcrash.so differ diff --git a/app/libs/arm64-v8a/libhtpcrash_dumper.so b/app/libs/arm64-v8a/libhtpcrash_dumper.so new file mode 100644 index 0000000..3b5f5ee Binary files /dev/null and b/app/libs/arm64-v8a/libhtpcrash_dumper.so differ diff --git a/app/libs/arm64-v8a/libmsaoaidauth.so b/app/libs/arm64-v8a/libmsaoaidauth.so new file mode 100644 index 0000000..b46d213 Binary files /dev/null and b/app/libs/arm64-v8a/libmsaoaidauth.so differ diff --git a/app/libs/arm64-v8a/libnllvm1632808251147706677.so b/app/libs/arm64-v8a/libnllvm1632808251147706677.so new file mode 100644 index 0000000..85de766 Binary files /dev/null and b/app/libs/arm64-v8a/libnllvm1632808251147706677.so differ diff --git a/app/libs/armeabi-v7a/libNetHTProtect.so b/app/libs/armeabi-v7a/libNetHTProtect.so new file mode 100644 index 0000000..60e23d1 Binary files /dev/null and b/app/libs/armeabi-v7a/libNetHTProtect.so differ diff --git a/app/libs/armeabi-v7a/libhtpcrash.so b/app/libs/armeabi-v7a/libhtpcrash.so new file mode 100644 index 0000000..d0560f5 Binary files /dev/null and b/app/libs/armeabi-v7a/libhtpcrash.so differ diff --git a/app/libs/armeabi-v7a/libhtpcrash_dumper.so b/app/libs/armeabi-v7a/libhtpcrash_dumper.so new file mode 100644 index 0000000..03dff6d Binary files /dev/null and b/app/libs/armeabi-v7a/libhtpcrash_dumper.so differ diff --git a/app/libs/armeabi-v7a/libmsaoaidauth.so b/app/libs/armeabi-v7a/libmsaoaidauth.so new file mode 100644 index 0000000..a75c629 Binary files /dev/null and b/app/libs/armeabi-v7a/libmsaoaidauth.so differ diff --git a/app/libs/armeabi-v7a/libnllvm1632808251147706677.so b/app/libs/armeabi-v7a/libnllvm1632808251147706677.so new file mode 100644 index 0000000..affc1b1 Binary files /dev/null and b/app/libs/armeabi-v7a/libnllvm1632808251147706677.so differ diff --git a/app/libs/auth_number_product-2.13.2.1-log-online-standard-cuum-release.aar b/app/libs/auth_number_product-2.13.2.1-log-online-standard-cuum-release.aar new file mode 100644 index 0000000..f52d8d5 Binary files /dev/null and b/app/libs/auth_number_product-2.13.2.1-log-online-standard-cuum-release.aar differ diff --git a/app/libs/com.heytap.msp.aar b/app/libs/com.heytap.msp.aar new file mode 100644 index 0000000..608aced Binary files /dev/null and b/app/libs/com.heytap.msp.aar differ diff --git a/app/libs/crashshield-2.1.4-release.aar b/app/libs/crashshield-2.1.4-release.aar new file mode 100644 index 0000000..e9b88cd Binary files /dev/null and b/app/libs/crashshield-2.1.4-release.aar differ diff --git a/app/libs/logger-2.2.1-release.aar b/app/libs/logger-2.2.1-release.aar new file mode 100644 index 0000000..b4c5ad2 Binary files /dev/null and b/app/libs/logger-2.2.1-release.aar differ diff --git a/app/libs/main-2.2.1-release.aar b/app/libs/main-2.2.1-release.aar new file mode 100644 index 0000000..2fe9a70 Binary files /dev/null and b/app/libs/main-2.2.1-release.aar differ diff --git a/app/libs/oaid.jar b/app/libs/oaid.jar new file mode 100644 index 0000000..b981df1 Binary files /dev/null and b/app/libs/oaid.jar differ diff --git a/app/libs/sand-paytypesdk-1.0.0.aar b/app/libs/sand-paytypesdk-1.0.0.aar new file mode 100644 index 0000000..92c24d6 Binary files /dev/null and b/app/libs/sand-paytypesdk-1.0.0.aar differ diff --git a/app/libs/video-capture.aar b/app/libs/video-capture.aar new file mode 100644 index 0000000..9df7fe0 Binary files /dev/null and b/app/libs/video-capture.aar differ diff --git a/app/libs/vivo_pushSDK_v3.0.0.4_484.aar b/app/libs/vivo_pushSDK_v3.0.0.4_484.aar new file mode 100644 index 0000000..f278999 Binary files /dev/null and b/app/libs/vivo_pushSDK_v3.0.0.4_484.aar differ diff --git a/app/libs/x86/libNetHTProtect.so b/app/libs/x86/libNetHTProtect.so new file mode 100644 index 0000000..8df72bc Binary files /dev/null and b/app/libs/x86/libNetHTProtect.so differ diff --git a/app/libs/x86/libhtpcrash.so b/app/libs/x86/libhtpcrash.so new file mode 100644 index 0000000..9a5ac9f Binary files /dev/null and b/app/libs/x86/libhtpcrash.so differ diff --git a/app/libs/x86/libhtpcrash_dumper.so b/app/libs/x86/libhtpcrash_dumper.so new file mode 100644 index 0000000..f31f06c Binary files /dev/null and b/app/libs/x86/libhtpcrash_dumper.so differ diff --git a/app/libs/x86/libmsaoaidauth.so b/app/libs/x86/libmsaoaidauth.so new file mode 100644 index 0000000..b46d213 Binary files /dev/null and b/app/libs/x86/libmsaoaidauth.so differ diff --git a/app/libs/x86/libnllvm1632808251147706677.so b/app/libs/x86/libnllvm1632808251147706677.so new file mode 100644 index 0000000..85de766 Binary files /dev/null and b/app/libs/x86/libnllvm1632808251147706677.so differ diff --git a/app/libs/x86_64/libNetHTProtect.so b/app/libs/x86_64/libNetHTProtect.so new file mode 100644 index 0000000..cd9a5ca Binary files /dev/null and b/app/libs/x86_64/libNetHTProtect.so differ diff --git a/app/libs/x86_64/libhtpcrash.so b/app/libs/x86_64/libhtpcrash.so new file mode 100644 index 0000000..38f3350 Binary files /dev/null and b/app/libs/x86_64/libhtpcrash.so differ diff --git a/app/libs/x86_64/libhtpcrash_dumper.so b/app/libs/x86_64/libhtpcrash_dumper.so new file mode 100644 index 0000000..6a1a866 Binary files /dev/null and b/app/libs/x86_64/libhtpcrash_dumper.so differ diff --git a/app/libs/x86_64/libmsaoaidauth.so b/app/libs/x86_64/libmsaoaidauth.so new file mode 100644 index 0000000..b46d213 Binary files /dev/null and b/app/libs/x86_64/libmsaoaidauth.so differ diff --git a/app/libs/x86_64/libnllvm1632808251147706677.so b/app/libs/x86_64/libnllvm1632808251147706677.so new file mode 100644 index 0000000..85de766 Binary files /dev/null and b/app/libs/x86_64/libnllvm1632808251147706677.so differ diff --git a/app/mcs-services.json b/app/mcs-services.json new file mode 100644 index 0000000..cd7a555 --- /dev/null +++ b/app/mcs-services.json @@ -0,0 +1,6 @@ +{ + "developer_id":"109999896480", + "app_id":"104457750", + "package_name":"com.fengliyan.tianlesue", + "version":"1.0" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..d581465 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,276 @@ +# 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 + +# +#-------------------------------------------基本不用动区域---------------------------------------------- +# +# +# -----------------------------基本 ----------------------------- +# + +# 指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。) +-optimizationpasses 5 +# 混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名) +-dontusemixedcaseclassnames +# 指定不去忽略非公共的库类(不跳过library中的非public的类) +-dontskipnonpubliclibraryclasses +# 指定不去忽略包可见的库类的成员 +-dontskipnonpubliclibraryclassmembers +#不进行优化,建议使用此选项, +-dontoptimize + # 不进行预校验,Android不需要,可加快混淆速度。 +-dontpreverify +# 屏蔽警告 +-ignorewarnings +# 指定混淆是采用的算法,后面的参数是一个过滤器 +# 这个过滤器是谷歌推荐的算法,一般不做更改 +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* +# 保护代码中的Annotation不被混淆 +-keepattributes *Annotation* +# 避免混淆泛型, 这在JSON实体映射时非常重要 +-keepattributes Signature +# 抛出异常时保留代码行号 +-keepattributes SourceFile,LineNumberTable + #优化时允许访问并修改有修饰符的类和类的成员,这可以提高优化步骤的结果。 +# 比如,当内联一个公共的getter方法时,这也可能需要外地公共访问。 +# 虽然java二进制规范不需要这个,要不然有的虚拟机处理这些代码会有问题。当有优化和使用-repackageclasses时才适用。 +#指示语:不能用这个指令处理库中的代码,因为有的类和类成员没有设计成public ,而在api中可能变成public +-allowaccessmodification +#当有优化和使用-repackageclasses时才适用。 +-repackageclasses '' + # 混淆时记录日志(打印混淆的详细信息) + # 这句话能够使我们的项目混淆后产生映射文件 + # 包含有类名->混淆后类名的映射关系 +-verbose + +# +# ----------------------------- 默认保留 ----------------------------- +# +#---------------------------------------------------- +# 保持哪些类不被混淆 +#继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆 +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.support.multidex.MultiDexApplication +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class * extends android.view.View +-keep class android.support.** {*;}## 保留support下的所有类及其内部类 + +-keep public class com.google.vending.licensing.ILicensingService +-keep public class com.android.vending.licensing.ILicensingService +#表示不混淆上面声明的类,最后这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。 +#---------------------------------------------------- + +# 保留继承的 +-keep public class * extends android.support.v4.** +-keep public class * extends android.support.v7.** +-keep public class * extends android.support.annotation.** + + +#表示不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致 +-keepclasseswithmembernames class * { + native ; +} + + +#这个主要是在layout 中写的onclick方法android:onclick="onClick",不进行混淆 +#表示不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性, +#当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了 +-keepclassmembers class * extends android.app.Activity{ + public void *(android.view.View); +} + +#表示不混淆枚举中的values()和valueOf()方法,枚举我用的非常少,这个就不评论了 +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +#表示不混淆任何一个View中的setXxx()和getXxx()方法, +#因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了。 +-keep public class * extends android.view.View{ + *** get*(); + void set*(***); + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); +} +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); +} + +#表示不混淆Parcelable实现类中的CREATOR字段, +#毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。 +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} +# 这指定了继承Serizalizable的类的如下成员不被移除混淆 +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} +# 保留R下面的资源 +#-keep class **.R$* { +# *; +#} +#不混淆资源类下static的 +-keepclassmembers class **.R$* { + public static ; +} + +# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆 +-keepclassmembers class * { + void *(**On*Event); + void *(**On*Listener); +} + +# 保留我们自定义控件(继承自View)不被混淆 +-keep public class * extends android.view.View{ + *** get*(); + void set*(***); + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); +} + +# +#----------------------------- WebView(项目中没有可以忽略) ----------------------------- +# +#webView需要进行特殊处理 +-keepclassmembers class fqcn.of.javascript.interface.for.Webview { + public *; +} +-keepclassmembers class * extends android.webkit.WebViewClient { + public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); + public boolean *(android.webkit.WebView, java.lang.String); +} +-keepclassmembers class * extends android.webkit.WebViewClient { + public void *(android.webkit.WebView, jav.lang.String); +} +#在app中与HTML5的JavaScript的交互进行特殊处理 +#我们需要确保这些js要调用的原生方法不能够被混淆,于是我们需要做如下处理: +-keepclassmembers class com.ljd.example.JSInterface { + ; +} + +# +#---------------------------------实体类--------------------------------- +#--------(实体Model不能混淆,否则找不到对应的属性获取不到值)----- +# +-dontwarn com.suchengkeji.android.confusiondemo.md.** +#对含有反射类的处理 +-keep class com.suchengkeji.android.confusiondemo.md.** { *; } +# +# ----------------------------- 其他的 ----------------------------- +# +# 删除代码中Log相关的代码 +-assumenosideeffects class android.util.Log { + public static boolean isLoggable(java.lang.String, int); + public static int v(...); + public static int i(...); + public static int w(...); + public static int d(...); + public static int e(...); +} + +# 保持测试相关的代码 +-dontnote junit.framework.** +-dontnote junit.runner.** +-dontwarn android.test.** +-dontwarn android.support.test.** +-dontwarn org.junit.** + +#华为推送 +-ignorewarnings +-keepattributes *Annotation* +-keepattributes Exceptions +-keepattributes InnerClasses +-keepattributes Signature +-keepattributes SourceFile,LineNumberTable +-keep class com.hianalytics.android.**{*;} +-keep class com.huawei.updatesdk.**{*;} +-keep class com.huawei.hms.**{*;} + + +#小米推送 +-dontwarn com.xiaomi.push.** +-keep class com.xiaomi.** {*;} + +#oppo推送 +-keep public class * extends android.app.Service + +# OAID +# sdk +-keep class com.bun.miitmdid.** { *; } +-keep interface com.bun.supplier.** { *; } +# asus +-keep class com.asus.msa.SupplementaryDID.** { *; } +-keep class com.asus.msa.sdid.** { *; } +# freeme +-keep class com.android.creator.** { *; } +-keep class com.android.msasdk.** { *; } +# huawei +-keep class com.huawei.hms.ads.** { *; } +-keep interface com.huawei.hms.ads.** {*; } +# lenovo +-keep class com.zui.deviceidservice.** { *; } +-keep class com.zui.opendeviceidlibrary.** { *; } +# meizu +-keep class com.meizu.flyme.openidsdk.** { *; } +# nubia +-keep class com.bun.miitmdid.provider.nubia.NubiaIdentityImpl +{ *; } +# oppo +-keep class com.heytap.openid.** { *; } +# samsung +-keep class com.samsung.android.deviceidservice.** { *; } +# vivo +-keep class com.vivo.identifier.** { *; } +# xiaomi +-keep class com.bun.miitmdid.provider.xiaomi.IdentifierManager +{ *; } +# zte +-keep class com.bun.lib.** { *; } +# coolpad +-keep class com.coolpad.deviceidsupport.** { *; } + + +-dontwarn com.tencent.bugly.** +-keep public class com.tencent.bugly.**{*;} + +-keep class com.tencent.mm.opensdk.** {*;} + +-keep class com.tencent.mm.sdk.** {*;} + +-keep class com.tencent.wxop.** {*;} + +-dontwarn com.unionpay.** +-keep class com.unionpay.** {*;} \ No newline at end of file diff --git a/app/src/androidTest/java/com/fengliyan/tianlesue/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/fengliyan/tianlesue/ExampleInstrumentedTest.java new file mode 100644 index 0000000..8a6e69c --- /dev/null +++ b/app/src/androidTest/java/com/fengliyan/tianlesue/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue; + +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 Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.fengliyan.tianlesue", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..aa8f00c --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,1025 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/aidl/com/fengliyan/tianlesue/aidl/IMyAidlInterface.aidl b/app/src/main/aidl/com/fengliyan/tianlesue/aidl/IMyAidlInterface.aidl new file mode 100644 index 0000000..e313ef0 --- /dev/null +++ b/app/src/main/aidl/com/fengliyan/tianlesue/aidl/IMyAidlInterface.aidl @@ -0,0 +1,12 @@ +// IMyAidlInterface.aidl +package com.fengliyan.tianlesue.aidl; + +// Declare any non-default types here with import statements + +interface IMyAidlInterface { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + String getServiceName(); +} diff --git a/app/src/main/assets/china_cities_v3.db b/app/src/main/assets/china_cities_v3.db new file mode 100644 index 0000000..c019b75 Binary files /dev/null and b/app/src/main/assets/china_cities_v3.db differ diff --git a/app/src/main/assets/com.live.xiayueonline.cert.pem b/app/src/main/assets/com.live.xiayueonline.cert.pem new file mode 100644 index 0000000..8562252 --- /dev/null +++ b/app/src/main/assets/com.live.xiayueonline.cert.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFoDCCA4igAwIBAgICJuwwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAkNO +MRAwDgYDVQQIDAdCZWlqaW5nMQwwCgYDVQQKDANNU0ExETAPBgNVBAsMCE9BSURf +U0RLMR4wHAYDVQQDDBVjb20uYnVuLm1paXRtZGlkLnNpZ24xHjAcBgkqhkiG9w0B +CQEWD21zYUBjYWljdC5hYy5jbjAeFw0yMjA2MjcxNTAzNTFaFw0yMzA2MjgxNTAz +NTFaMIGSMQswCQYDVQQGEwJDTjEQMA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwH +QmVpamluZzETMBEGA1UECgwKcWluZ3l1MjAyMjEeMBwGA1UEAwwVY29tLmxpdmUu +eGlheXVlb25saW5lMSowKAYJKoZIhvcNAQkBFhtqdUBzenNoZmtqeXhnczM4Lndl +Y29tLndvcmswggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCyGC9T3GW4 +BSsvnVNqb8+HlnjJAQvTPd7H13m1f945uUsUYYMaaZuICYjb4qefZUyQgyxBUTYf +BOTpE7ccdcNoZgCp05RTng30zvkc4pjawJIkNeIC2NGlN7RquO4Ka/06LSuq5N+b +fL78E0MwZAinoxSswf/yNY5R1LJ2b3I7BnW7rVSb7KbB0Q4z5KmuJ04hPVl7BtSd +fVnvnRVTBDRm/cMgyupEl+CCGW8HUejzPHdHeHRK1rx7fuwQI+5jgMmDYRNXZD4A +mJ0vClurQR5avN2xOuxB8HbtB+lQitsNnQCvYY1Xp4s7FtfmT6JzDNQ//vRgXxYr +OaVFfoY/ugrO+SfZtqej+mdKR3KgOaAA75t8zcJfM6WGrbPJl3xHc2bhD4kGwRkT +AcHJ7WQOIrWz85CPCfIoYh8nZlBlsCNamJJh6Pl2nAtmnfMtDuYZJo/2QK6J/KFt +ywsYIekU6fiRsJaaunBf5sD9IxbvJcRRB+HRCsySKYEg8z7Xlh90fHimfUgT0Gt4 +4/o+nzPh7Cq9Ay6dWtMxYFx78Z1epapOJdUNpZWIET8wQHriJmbJ18TlidGRAW85 +kW2ka2cr4u6Ed68JQa+nN+kbS0dDeuvOBGOsiqqCy5aeA0oz88HRWWIga02PLTZb +Es4PdYrNzHWCISjnk34KpwwxYJUn6Zpy1wIDAQABoxAwDjAMBgNVHRMBAf8EAjAA +MA0GCSqGSIb3DQEBCwUAA4ICAQCRRKZLtYiCh86150a7thE/YsQxE3PEVHd4/Ufm +UqDRZEbt/ObUNE0Pl0f4ZYu3eSqUeljwTI9E2AHlMznMzVhi0JMQSpLKMdl+5D2L +S7tX3YBtAGhYQ7N66Sa4XDXbVQQdup3RxpQ5vwPGKlkHUUG8z+0wgcWzqRoBe1bG ++BodXmvfFVqpOqH/1w8M9o10KHpc0hfoq4NJhtYLaZ5xAJh488W+fFywSai2ybqx +1xar/q0fiB68J+5/i/6jkBfBS3/MT1hFRu1ieWVEFr71qtN4df+UoiP7DTtmuNzS +Z+NQgVKP33PkGT/UrLq4IT1V5jKJHc1+ihUQi/9TeBIrn5d+XdND1Ci063ezJAok +S42ZmJK3CHza1nu0bUW8eddX6byv/PxSFRCprpkbi0LPMzEiUtwxpVSBc4P322oQ +wRUgL52BXO7zAYrRHWtuBGI1xcJqXiQcBfczEYZrLKx39qZtgBievhppT10HVdLl +5E8aRgVMorx/ZUjgScJQFYDPOaRZBeDSmqSf8DqHGSUXlnUey6AIpqH97gfQBsrK +U1rmJpKbLZkWyC1G9Lhxti8CE2u1oWjORf57gngKpZEYJ8TU9gKsJsmuJFfHLQWq +fPYVB3GlKL/pmNhG0JIzG5fgHd+/bhig7VrUOO+b4IidWeZ5Jqixg7PcVo5wKlGC +vkmAyQ== +-----END CERTIFICATE----- diff --git a/app/src/main/assets/emoji/default/emoji_00.png b/app/src/main/assets/emoji/default/emoji_00.png new file mode 100644 index 0000000..4465411 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_00.png differ diff --git a/app/src/main/assets/emoji/default/emoji_01.png b/app/src/main/assets/emoji/default/emoji_01.png new file mode 100644 index 0000000..54f540e Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_01.png differ diff --git a/app/src/main/assets/emoji/default/emoji_02.png b/app/src/main/assets/emoji/default/emoji_02.png new file mode 100644 index 0000000..a7781b5 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_02.png differ diff --git a/app/src/main/assets/emoji/default/emoji_03.png b/app/src/main/assets/emoji/default/emoji_03.png new file mode 100644 index 0000000..2f4d019 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_03.png differ diff --git a/app/src/main/assets/emoji/default/emoji_04.png b/app/src/main/assets/emoji/default/emoji_04.png new file mode 100644 index 0000000..4025be4 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_04.png differ diff --git a/app/src/main/assets/emoji/default/emoji_05.png b/app/src/main/assets/emoji/default/emoji_05.png new file mode 100644 index 0000000..0073ce8 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_05.png differ diff --git a/app/src/main/assets/emoji/default/emoji_06.png b/app/src/main/assets/emoji/default/emoji_06.png new file mode 100644 index 0000000..02375d5 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_06.png differ diff --git a/app/src/main/assets/emoji/default/emoji_07.png b/app/src/main/assets/emoji/default/emoji_07.png new file mode 100644 index 0000000..cf9460a Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_07.png differ diff --git a/app/src/main/assets/emoji/default/emoji_08.png b/app/src/main/assets/emoji/default/emoji_08.png new file mode 100644 index 0000000..ae73def Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_08.png differ diff --git a/app/src/main/assets/emoji/default/emoji_09.png b/app/src/main/assets/emoji/default/emoji_09.png new file mode 100644 index 0000000..8e0add9 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_09.png differ diff --git a/app/src/main/assets/emoji/default/emoji_10.png b/app/src/main/assets/emoji/default/emoji_10.png new file mode 100644 index 0000000..8c2c093 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_10.png differ diff --git a/app/src/main/assets/emoji/default/emoji_100.png b/app/src/main/assets/emoji/default/emoji_100.png new file mode 100644 index 0000000..09ee79c Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_100.png differ diff --git a/app/src/main/assets/emoji/default/emoji_101.png b/app/src/main/assets/emoji/default/emoji_101.png new file mode 100644 index 0000000..fba99ac Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_101.png differ diff --git a/app/src/main/assets/emoji/default/emoji_102.png b/app/src/main/assets/emoji/default/emoji_102.png new file mode 100644 index 0000000..cfa1a7d Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_102.png differ diff --git a/app/src/main/assets/emoji/default/emoji_103.png b/app/src/main/assets/emoji/default/emoji_103.png new file mode 100644 index 0000000..3b087b6 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_103.png differ diff --git a/app/src/main/assets/emoji/default/emoji_104.png b/app/src/main/assets/emoji/default/emoji_104.png new file mode 100644 index 0000000..e768fac Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_104.png differ diff --git a/app/src/main/assets/emoji/default/emoji_105.png b/app/src/main/assets/emoji/default/emoji_105.png new file mode 100644 index 0000000..cbea142 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_105.png differ diff --git a/app/src/main/assets/emoji/default/emoji_106.png b/app/src/main/assets/emoji/default/emoji_106.png new file mode 100644 index 0000000..57c7a13 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_106.png differ diff --git a/app/src/main/assets/emoji/default/emoji_107.png b/app/src/main/assets/emoji/default/emoji_107.png new file mode 100644 index 0000000..e40eeee Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_107.png differ diff --git a/app/src/main/assets/emoji/default/emoji_108.png b/app/src/main/assets/emoji/default/emoji_108.png new file mode 100644 index 0000000..ce562c6 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_108.png differ diff --git a/app/src/main/assets/emoji/default/emoji_109.png b/app/src/main/assets/emoji/default/emoji_109.png new file mode 100644 index 0000000..0de454e Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_109.png differ diff --git a/app/src/main/assets/emoji/default/emoji_11.png b/app/src/main/assets/emoji/default/emoji_11.png new file mode 100644 index 0000000..24ddd65 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_11.png differ diff --git a/app/src/main/assets/emoji/default/emoji_110.png b/app/src/main/assets/emoji/default/emoji_110.png new file mode 100644 index 0000000..f146a3e Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_110.png differ diff --git a/app/src/main/assets/emoji/default/emoji_111.png b/app/src/main/assets/emoji/default/emoji_111.png new file mode 100644 index 0000000..4e1d2f2 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_111.png differ diff --git a/app/src/main/assets/emoji/default/emoji_112.png b/app/src/main/assets/emoji/default/emoji_112.png new file mode 100644 index 0000000..6799b94 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_112.png differ diff --git a/app/src/main/assets/emoji/default/emoji_113.png b/app/src/main/assets/emoji/default/emoji_113.png new file mode 100644 index 0000000..aeb2588 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_113.png differ diff --git a/app/src/main/assets/emoji/default/emoji_114.png b/app/src/main/assets/emoji/default/emoji_114.png new file mode 100644 index 0000000..76b6900 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_114.png differ diff --git a/app/src/main/assets/emoji/default/emoji_115.png b/app/src/main/assets/emoji/default/emoji_115.png new file mode 100644 index 0000000..8ea9e17 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_115.png differ diff --git a/app/src/main/assets/emoji/default/emoji_12.png b/app/src/main/assets/emoji/default/emoji_12.png new file mode 100644 index 0000000..04ca5ff Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_12.png differ diff --git a/app/src/main/assets/emoji/default/emoji_13.png b/app/src/main/assets/emoji/default/emoji_13.png new file mode 100644 index 0000000..01aeee3 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_13.png differ diff --git a/app/src/main/assets/emoji/default/emoji_14.png b/app/src/main/assets/emoji/default/emoji_14.png new file mode 100644 index 0000000..972caf6 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_14.png differ diff --git a/app/src/main/assets/emoji/default/emoji_145.png b/app/src/main/assets/emoji/default/emoji_145.png new file mode 100644 index 0000000..596dc9d Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_145.png differ diff --git a/app/src/main/assets/emoji/default/emoji_15.png b/app/src/main/assets/emoji/default/emoji_15.png new file mode 100644 index 0000000..d991313 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_15.png differ diff --git a/app/src/main/assets/emoji/default/emoji_16.png b/app/src/main/assets/emoji/default/emoji_16.png new file mode 100644 index 0000000..6ec3148 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_16.png differ diff --git a/app/src/main/assets/emoji/default/emoji_160.png b/app/src/main/assets/emoji/default/emoji_160.png new file mode 100644 index 0000000..82ce23e Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_160.png differ diff --git a/app/src/main/assets/emoji/default/emoji_161.png b/app/src/main/assets/emoji/default/emoji_161.png new file mode 100644 index 0000000..981fb71 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_161.png differ diff --git a/app/src/main/assets/emoji/default/emoji_162.png b/app/src/main/assets/emoji/default/emoji_162.png new file mode 100644 index 0000000..08d638f Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_162.png differ diff --git a/app/src/main/assets/emoji/default/emoji_163.png b/app/src/main/assets/emoji/default/emoji_163.png new file mode 100644 index 0000000..a493dc3 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_163.png differ diff --git a/app/src/main/assets/emoji/default/emoji_164.png b/app/src/main/assets/emoji/default/emoji_164.png new file mode 100644 index 0000000..d61502d Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_164.png differ diff --git a/app/src/main/assets/emoji/default/emoji_165.png b/app/src/main/assets/emoji/default/emoji_165.png new file mode 100644 index 0000000..2642192 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_165.png differ diff --git a/app/src/main/assets/emoji/default/emoji_166.png b/app/src/main/assets/emoji/default/emoji_166.png new file mode 100644 index 0000000..e87ca8b Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_166.png differ diff --git a/app/src/main/assets/emoji/default/emoji_167.png b/app/src/main/assets/emoji/default/emoji_167.png new file mode 100644 index 0000000..8b9f3bb Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_167.png differ diff --git a/app/src/main/assets/emoji/default/emoji_17.png b/app/src/main/assets/emoji/default/emoji_17.png new file mode 100644 index 0000000..5472a0e Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_17.png differ diff --git a/app/src/main/assets/emoji/default/emoji_18.png b/app/src/main/assets/emoji/default/emoji_18.png new file mode 100644 index 0000000..d192152 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_18.png differ diff --git a/app/src/main/assets/emoji/default/emoji_19.png b/app/src/main/assets/emoji/default/emoji_19.png new file mode 100644 index 0000000..36d267d Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_19.png differ diff --git a/app/src/main/assets/emoji/default/emoji_20.png b/app/src/main/assets/emoji/default/emoji_20.png new file mode 100644 index 0000000..0e7d6cb Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_20.png differ diff --git a/app/src/main/assets/emoji/default/emoji_21.png b/app/src/main/assets/emoji/default/emoji_21.png new file mode 100644 index 0000000..7278fa7 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_21.png differ diff --git a/app/src/main/assets/emoji/default/emoji_22.png b/app/src/main/assets/emoji/default/emoji_22.png new file mode 100644 index 0000000..3d63a89 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_22.png differ diff --git a/app/src/main/assets/emoji/default/emoji_23.png b/app/src/main/assets/emoji/default/emoji_23.png new file mode 100644 index 0000000..6f28582 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_23.png differ diff --git a/app/src/main/assets/emoji/default/emoji_24.png b/app/src/main/assets/emoji/default/emoji_24.png new file mode 100644 index 0000000..1f4c004 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_24.png differ diff --git a/app/src/main/assets/emoji/default/emoji_25.png b/app/src/main/assets/emoji/default/emoji_25.png new file mode 100644 index 0000000..80856b1 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_25.png differ diff --git a/app/src/main/assets/emoji/default/emoji_26.png b/app/src/main/assets/emoji/default/emoji_26.png new file mode 100644 index 0000000..d87bdca Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_26.png differ diff --git a/app/src/main/assets/emoji/default/emoji_27.png b/app/src/main/assets/emoji/default/emoji_27.png new file mode 100644 index 0000000..aaba661 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_27.png differ diff --git a/app/src/main/assets/emoji/default/emoji_28.png b/app/src/main/assets/emoji/default/emoji_28.png new file mode 100644 index 0000000..be44083 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_28.png differ diff --git a/app/src/main/assets/emoji/default/emoji_29.png b/app/src/main/assets/emoji/default/emoji_29.png new file mode 100644 index 0000000..ebf7ad7 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_29.png differ diff --git a/app/src/main/assets/emoji/default/emoji_30.png b/app/src/main/assets/emoji/default/emoji_30.png new file mode 100644 index 0000000..1adda7e Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_30.png differ diff --git a/app/src/main/assets/emoji/default/emoji_31.png b/app/src/main/assets/emoji/default/emoji_31.png new file mode 100644 index 0000000..848e39f Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_31.png differ diff --git a/app/src/main/assets/emoji/default/emoji_32.png b/app/src/main/assets/emoji/default/emoji_32.png new file mode 100644 index 0000000..2fd4bd0 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_32.png differ diff --git a/app/src/main/assets/emoji/default/emoji_33.png b/app/src/main/assets/emoji/default/emoji_33.png new file mode 100644 index 0000000..43be47a Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_33.png differ diff --git a/app/src/main/assets/emoji/default/emoji_34.png b/app/src/main/assets/emoji/default/emoji_34.png new file mode 100644 index 0000000..ea3623a Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_34.png differ diff --git a/app/src/main/assets/emoji/default/emoji_35.png b/app/src/main/assets/emoji/default/emoji_35.png new file mode 100644 index 0000000..5f94409 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_35.png differ diff --git a/app/src/main/assets/emoji/default/emoji_36.png b/app/src/main/assets/emoji/default/emoji_36.png new file mode 100644 index 0000000..54187b2 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_36.png differ diff --git a/app/src/main/assets/emoji/default/emoji_37.png b/app/src/main/assets/emoji/default/emoji_37.png new file mode 100644 index 0000000..eb9537a Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_37.png differ diff --git a/app/src/main/assets/emoji/default/emoji_38.png b/app/src/main/assets/emoji/default/emoji_38.png new file mode 100644 index 0000000..7da044a Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_38.png differ diff --git a/app/src/main/assets/emoji/default/emoji_39.png b/app/src/main/assets/emoji/default/emoji_39.png new file mode 100644 index 0000000..ee0c8e2 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_39.png differ diff --git a/app/src/main/assets/emoji/default/emoji_40.png b/app/src/main/assets/emoji/default/emoji_40.png new file mode 100644 index 0000000..06b74cf Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_40.png differ diff --git a/app/src/main/assets/emoji/default/emoji_41.png b/app/src/main/assets/emoji/default/emoji_41.png new file mode 100644 index 0000000..558a743 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_41.png differ diff --git a/app/src/main/assets/emoji/default/emoji_42.png b/app/src/main/assets/emoji/default/emoji_42.png new file mode 100644 index 0000000..d2f4038 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_42.png differ diff --git a/app/src/main/assets/emoji/default/emoji_43.png b/app/src/main/assets/emoji/default/emoji_43.png new file mode 100644 index 0000000..f161702 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_43.png differ diff --git a/app/src/main/assets/emoji/default/emoji_44.png b/app/src/main/assets/emoji/default/emoji_44.png new file mode 100644 index 0000000..cc6fb60 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_44.png differ diff --git a/app/src/main/assets/emoji/default/emoji_45.png b/app/src/main/assets/emoji/default/emoji_45.png new file mode 100644 index 0000000..2d59f76 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_45.png differ diff --git a/app/src/main/assets/emoji/default/emoji_46.png b/app/src/main/assets/emoji/default/emoji_46.png new file mode 100644 index 0000000..f12e9c9 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_46.png differ diff --git a/app/src/main/assets/emoji/default/emoji_47.png b/app/src/main/assets/emoji/default/emoji_47.png new file mode 100644 index 0000000..149ec92 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_47.png differ diff --git a/app/src/main/assets/emoji/default/emoji_48.png b/app/src/main/assets/emoji/default/emoji_48.png new file mode 100644 index 0000000..136ff32 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_48.png differ diff --git a/app/src/main/assets/emoji/default/emoji_49.png b/app/src/main/assets/emoji/default/emoji_49.png new file mode 100644 index 0000000..f54af73 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_49.png differ diff --git a/app/src/main/assets/emoji/default/emoji_50.png b/app/src/main/assets/emoji/default/emoji_50.png new file mode 100644 index 0000000..d5833f3 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_50.png differ diff --git a/app/src/main/assets/emoji/default/emoji_51.png b/app/src/main/assets/emoji/default/emoji_51.png new file mode 100644 index 0000000..6de855c Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_51.png differ diff --git a/app/src/main/assets/emoji/default/emoji_52.png b/app/src/main/assets/emoji/default/emoji_52.png new file mode 100644 index 0000000..f0d401f Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_52.png differ diff --git a/app/src/main/assets/emoji/default/emoji_53.png b/app/src/main/assets/emoji/default/emoji_53.png new file mode 100644 index 0000000..7abdf74 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_53.png differ diff --git a/app/src/main/assets/emoji/default/emoji_54.png b/app/src/main/assets/emoji/default/emoji_54.png new file mode 100644 index 0000000..276df18 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_54.png differ diff --git a/app/src/main/assets/emoji/default/emoji_55.png b/app/src/main/assets/emoji/default/emoji_55.png new file mode 100644 index 0000000..9981e0b Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_55.png differ diff --git a/app/src/main/assets/emoji/default/emoji_56.png b/app/src/main/assets/emoji/default/emoji_56.png new file mode 100644 index 0000000..4b620c6 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_56.png differ diff --git a/app/src/main/assets/emoji/default/emoji_57.png b/app/src/main/assets/emoji/default/emoji_57.png new file mode 100644 index 0000000..0704717 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_57.png differ diff --git a/app/src/main/assets/emoji/default/emoji_58.png b/app/src/main/assets/emoji/default/emoji_58.png new file mode 100644 index 0000000..0b1a1d6 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_58.png differ diff --git a/app/src/main/assets/emoji/default/emoji_59.png b/app/src/main/assets/emoji/default/emoji_59.png new file mode 100644 index 0000000..3129f8d Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_59.png differ diff --git a/app/src/main/assets/emoji/default/emoji_60.png b/app/src/main/assets/emoji/default/emoji_60.png new file mode 100644 index 0000000..7e4921e Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_60.png differ diff --git a/app/src/main/assets/emoji/default/emoji_61.png b/app/src/main/assets/emoji/default/emoji_61.png new file mode 100644 index 0000000..6faf53c Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_61.png differ diff --git a/app/src/main/assets/emoji/default/emoji_62.png b/app/src/main/assets/emoji/default/emoji_62.png new file mode 100644 index 0000000..e91e481 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_62.png differ diff --git a/app/src/main/assets/emoji/default/emoji_63.png b/app/src/main/assets/emoji/default/emoji_63.png new file mode 100644 index 0000000..938c577 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_63.png differ diff --git a/app/src/main/assets/emoji/default/emoji_64.png b/app/src/main/assets/emoji/default/emoji_64.png new file mode 100644 index 0000000..b2c1fda Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_64.png differ diff --git a/app/src/main/assets/emoji/default/emoji_65.png b/app/src/main/assets/emoji/default/emoji_65.png new file mode 100644 index 0000000..189c04f Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_65.png differ diff --git a/app/src/main/assets/emoji/default/emoji_66.png b/app/src/main/assets/emoji/default/emoji_66.png new file mode 100644 index 0000000..ccfc989 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_66.png differ diff --git a/app/src/main/assets/emoji/default/emoji_67.png b/app/src/main/assets/emoji/default/emoji_67.png new file mode 100644 index 0000000..4f058e9 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_67.png differ diff --git a/app/src/main/assets/emoji/default/emoji_68.png b/app/src/main/assets/emoji/default/emoji_68.png new file mode 100644 index 0000000..faa870c Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_68.png differ diff --git a/app/src/main/assets/emoji/default/emoji_69.png b/app/src/main/assets/emoji/default/emoji_69.png new file mode 100644 index 0000000..ca26055 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_69.png differ diff --git a/app/src/main/assets/emoji/default/emoji_70.png b/app/src/main/assets/emoji/default/emoji_70.png new file mode 100644 index 0000000..eccfdc6 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_70.png differ diff --git a/app/src/main/assets/emoji/default/emoji_71.png b/app/src/main/assets/emoji/default/emoji_71.png new file mode 100644 index 0000000..3a3d366 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_71.png differ diff --git a/app/src/main/assets/emoji/default/emoji_72.png b/app/src/main/assets/emoji/default/emoji_72.png new file mode 100644 index 0000000..69726e9 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_72.png differ diff --git a/app/src/main/assets/emoji/default/emoji_73.png b/app/src/main/assets/emoji/default/emoji_73.png new file mode 100644 index 0000000..d2480fa Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_73.png differ diff --git a/app/src/main/assets/emoji/default/emoji_74.png b/app/src/main/assets/emoji/default/emoji_74.png new file mode 100644 index 0000000..0fcc17f Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_74.png differ diff --git a/app/src/main/assets/emoji/default/emoji_75.png b/app/src/main/assets/emoji/default/emoji_75.png new file mode 100644 index 0000000..644d3f3 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_75.png differ diff --git a/app/src/main/assets/emoji/default/emoji_76.png b/app/src/main/assets/emoji/default/emoji_76.png new file mode 100644 index 0000000..a188d02 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_76.png differ diff --git a/app/src/main/assets/emoji/default/emoji_77.png b/app/src/main/assets/emoji/default/emoji_77.png new file mode 100644 index 0000000..89d795f Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_77.png differ diff --git a/app/src/main/assets/emoji/default/emoji_78.png b/app/src/main/assets/emoji/default/emoji_78.png new file mode 100644 index 0000000..0298b21 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_78.png differ diff --git a/app/src/main/assets/emoji/default/emoji_79.png b/app/src/main/assets/emoji/default/emoji_79.png new file mode 100644 index 0000000..4012413 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_79.png differ diff --git a/app/src/main/assets/emoji/default/emoji_80.png b/app/src/main/assets/emoji/default/emoji_80.png new file mode 100644 index 0000000..de40041 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_80.png differ diff --git a/app/src/main/assets/emoji/default/emoji_81.png b/app/src/main/assets/emoji/default/emoji_81.png new file mode 100644 index 0000000..81b496a Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_81.png differ diff --git a/app/src/main/assets/emoji/default/emoji_82.png b/app/src/main/assets/emoji/default/emoji_82.png new file mode 100644 index 0000000..eab0a58 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_82.png differ diff --git a/app/src/main/assets/emoji/default/emoji_83.png b/app/src/main/assets/emoji/default/emoji_83.png new file mode 100644 index 0000000..c6ff3e3 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_83.png differ diff --git a/app/src/main/assets/emoji/default/emoji_84.png b/app/src/main/assets/emoji/default/emoji_84.png new file mode 100644 index 0000000..422bd0d Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_84.png differ diff --git a/app/src/main/assets/emoji/default/emoji_85.png b/app/src/main/assets/emoji/default/emoji_85.png new file mode 100644 index 0000000..baee72f Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_85.png differ diff --git a/app/src/main/assets/emoji/default/emoji_86.png b/app/src/main/assets/emoji/default/emoji_86.png new file mode 100644 index 0000000..46ea92b Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_86.png differ diff --git a/app/src/main/assets/emoji/default/emoji_87.png b/app/src/main/assets/emoji/default/emoji_87.png new file mode 100644 index 0000000..a07dd76 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_87.png differ diff --git a/app/src/main/assets/emoji/default/emoji_88.png b/app/src/main/assets/emoji/default/emoji_88.png new file mode 100644 index 0000000..c7bba8b Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_88.png differ diff --git a/app/src/main/assets/emoji/default/emoji_89.png b/app/src/main/assets/emoji/default/emoji_89.png new file mode 100644 index 0000000..185f474 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_89.png differ diff --git a/app/src/main/assets/emoji/default/emoji_90.png b/app/src/main/assets/emoji/default/emoji_90.png new file mode 100644 index 0000000..d224843 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_90.png differ diff --git a/app/src/main/assets/emoji/default/emoji_91.png b/app/src/main/assets/emoji/default/emoji_91.png new file mode 100644 index 0000000..8d56793 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_91.png differ diff --git a/app/src/main/assets/emoji/default/emoji_92.png b/app/src/main/assets/emoji/default/emoji_92.png new file mode 100644 index 0000000..e7e5044 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_92.png differ diff --git a/app/src/main/assets/emoji/default/emoji_93.png b/app/src/main/assets/emoji/default/emoji_93.png new file mode 100644 index 0000000..1f6c071 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_93.png differ diff --git a/app/src/main/assets/emoji/default/emoji_94.png b/app/src/main/assets/emoji/default/emoji_94.png new file mode 100644 index 0000000..f1ea6e5 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_94.png differ diff --git a/app/src/main/assets/emoji/default/emoji_95.png b/app/src/main/assets/emoji/default/emoji_95.png new file mode 100644 index 0000000..e1b7fc8 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_95.png differ diff --git a/app/src/main/assets/emoji/default/emoji_96.png b/app/src/main/assets/emoji/default/emoji_96.png new file mode 100644 index 0000000..8b5821b Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_96.png differ diff --git a/app/src/main/assets/emoji/default/emoji_97.png b/app/src/main/assets/emoji/default/emoji_97.png new file mode 100644 index 0000000..d694b37 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_97.png differ diff --git a/app/src/main/assets/emoji/default/emoji_98.png b/app/src/main/assets/emoji/default/emoji_98.png new file mode 100644 index 0000000..d19e80d Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_98.png differ diff --git a/app/src/main/assets/emoji/default/emoji_99.png b/app/src/main/assets/emoji/default/emoji_99.png new file mode 100644 index 0000000..42e1fd6 Binary files /dev/null and b/app/src/main/assets/emoji/default/emoji_99.png differ diff --git a/app/src/main/assets/emoji/emoji.xml b/app/src/main/assets/emoji/emoji.xml new file mode 100644 index 0000000..8047167 --- /dev/null +++ b/app/src/main/assets/emoji/emoji.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/assets/images/img_page_call.png b/app/src/main/assets/images/img_page_call.png new file mode 100644 index 0000000..7ebac36 Binary files /dev/null and b/app/src/main/assets/images/img_page_call.png differ diff --git a/app/src/main/assets/images/img_video_call0.png b/app/src/main/assets/images/img_video_call0.png new file mode 100644 index 0000000..128efc8 Binary files /dev/null and b/app/src/main/assets/images/img_video_call0.png differ diff --git a/app/src/main/assets/images/img_video_call1.png b/app/src/main/assets/images/img_video_call1.png new file mode 100644 index 0000000..d4b35f7 Binary files /dev/null and b/app/src/main/assets/images/img_video_call1.png differ diff --git a/app/src/main/assets/motion/libxt3.1_a.so b/app/src/main/assets/motion/libxt3.1_a.so new file mode 100644 index 0000000..f07fc89 Binary files /dev/null and b/app/src/main/assets/motion/libxt3.1_a.so differ diff --git a/app/src/main/assets/motion/libxt3.1_a64.so b/app/src/main/assets/motion/libxt3.1_a64.so new file mode 100644 index 0000000..2a68538 Binary files /dev/null and b/app/src/main/assets/motion/libxt3.1_a64.so differ diff --git a/app/src/main/assets/motion/libxt3.1_x64.so b/app/src/main/assets/motion/libxt3.1_x64.so new file mode 100644 index 0000000..80abd96 Binary files /dev/null and b/app/src/main/assets/motion/libxt3.1_x64.so differ diff --git a/app/src/main/assets/motion/libxt3.1_x86.so b/app/src/main/assets/motion/libxt3.1_x86.so new file mode 100644 index 0000000..5fd47de Binary files /dev/null and b/app/src/main/assets/motion/libxt3.1_x86.so differ diff --git a/app/src/main/assets/page_call_video.json b/app/src/main/assets/page_call_video.json new file mode 100644 index 0000000..50815a7 --- /dev/null +++ b/app/src/main/assets/page_call_video.json @@ -0,0 +1 @@ +{"v":"5.6.10","fr":25,"ip":1,"op":35,"w":428,"h":121,"nm":"合成 2","ddd":0,"assets":[{"id":"image_0","w":648,"h":186,"u":"images/","p":"img_page_call.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"Group 1000005210.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[214,60,0],"ix":2},"a":{"a":0,"k":[324,93,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[59.249,59.249,100],"e":[66.249,66.249,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":17,"s":[66.249,66.249,100],"e":[59.249,59.249,100]},{"t":35}],"ix":6}},"ao":0,"ip":0,"op":100,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/app/src/main/assets/pinyin/index.dat b/app/src/main/assets/pinyin/index.dat new file mode 100644 index 0000000..8a812bb Binary files /dev/null and b/app/src/main/assets/pinyin/index.dat differ diff --git a/app/src/main/assets/supplierconfig.json b/app/src/main/assets/supplierconfig.json new file mode 100644 index 0000000..1a138b4 --- /dev/null +++ b/app/src/main/assets/supplierconfig.json @@ -0,0 +1,10 @@ +{ + "supplier":{ + "vivo":{ + "appid":"105654483" + }, + "oppo":{ + "appid":"31060347" + } + } +} diff --git a/app/src/main/assets/svga/hg1.svga b/app/src/main/assets/svga/hg1.svga new file mode 100644 index 0000000..aba1431 Binary files /dev/null and b/app/src/main/assets/svga/hg1.svga differ diff --git a/app/src/main/assets/svga/hg2.svga b/app/src/main/assets/svga/hg2.svga new file mode 100644 index 0000000..3f81bfc Binary files /dev/null and b/app/src/main/assets/svga/hg2.svga differ diff --git a/app/src/main/assets/svga/hg3.svga b/app/src/main/assets/svga/hg3.svga new file mode 100644 index 0000000..628656d Binary files /dev/null and b/app/src/main/assets/svga/hg3.svga differ diff --git a/app/src/main/assets/svga/speed_video_man.svga b/app/src/main/assets/svga/speed_video_man.svga new file mode 100644 index 0000000..9a03fb1 Binary files /dev/null and b/app/src/main/assets/svga/speed_video_man.svga differ diff --git a/app/src/main/assets/svga/speed_video_women.svga b/app/src/main/assets/svga/speed_video_women.svga new file mode 100644 index 0000000..1a6e00f Binary files /dev/null and b/app/src/main/assets/svga/speed_video_women.svga differ diff --git a/app/src/main/assets/svga/speed_voice_man.svga b/app/src/main/assets/svga/speed_voice_man.svga new file mode 100644 index 0000000..8552527 Binary files /dev/null and b/app/src/main/assets/svga/speed_voice_man.svga differ diff --git a/app/src/main/assets/svga/speed_voice_women.svga b/app/src/main/assets/svga/speed_voice_women.svga new file mode 100644 index 0000000..1d00dfd Binary files /dev/null and b/app/src/main/assets/svga/speed_voice_women.svga differ diff --git a/app/src/main/assets/video_call_btn.json b/app/src/main/assets/video_call_btn.json new file mode 100644 index 0000000..4ee418b --- /dev/null +++ b/app/src/main/assets/video_call_btn.json @@ -0,0 +1 @@ +{"v":"5.6.10","fr":25,"ip":1,"op":78,"w":128,"h":128,"nm":"合成 2","ddd":0,"assets":[{"id":"image_0","w":123,"h":125,"u":"images/","p":"img_video_call0.png","e":0},{"id":"image_1","w":180,"h":180,"u":"images/","p":"img_video_call1.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-203,-484,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[],"ip":0,"op":100,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":2,"nm":"Group 2041@3x.png","cl":"png","parent":3,"refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[-10],"e":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":57,"s":[10],"e":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":64,"s":[-10],"e":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":71,"s":[10],"e":[-10]},{"t":78}],"ix":10},"p":{"a":0,"k":[88.72,92.559,0],"ix":2},"a":{"a":0,"k":[61.5,62.5,0],"ix":1},"s":{"a":0,"k":[101.898,101.898,100],"ix":6}},"ao":0,"ip":0,"op":100,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":2,"nm":"Ellipse 622.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,63.25,0],"ix":2},"a":{"a":0,"k":[90,90,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[58.611,58.611,100],"e":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[50,50,100],"e":[58.611,58.611,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":24,"s":[58.611,58.611,100],"e":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":36,"s":[50,50,100],"e":[58.611,58.611,100]},{"t":48}],"ix":6}},"ao":0,"ip":0,"op":100,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/app/src/main/filters/res/drawable-xhdpi/avatar_bg_white.xml b/app/src/main/filters/res/drawable-xhdpi/avatar_bg_white.xml new file mode 100644 index 0000000..4253c91 --- /dev/null +++ b/app/src/main/filters/res/drawable-xhdpi/avatar_bg_white.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/filters/res/drawable-xhdpi/bg_corner.xml b/app/src/main/filters/res/drawable-xhdpi/bg_corner.xml new file mode 100644 index 0000000..9608025 --- /dev/null +++ b/app/src/main/filters/res/drawable-xhdpi/bg_corner.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/filters/res/drawable-xhdpi/danya.jpg b/app/src/main/filters/res/drawable-xhdpi/danya.jpg new file mode 100644 index 0000000..3232d0d Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/danya.jpg differ diff --git a/app/src/main/filters/res/drawable-xhdpi/fennen.jpg b/app/src/main/filters/res/drawable-xhdpi/fennen.jpg new file mode 100644 index 0000000..d1944df Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/fennen.jpg differ diff --git a/app/src/main/filters/res/drawable-xhdpi/home_buttons_dislike_normal.png b/app/src/main/filters/res/drawable-xhdpi/home_buttons_dislike_normal.png new file mode 100644 index 0000000..84192fc Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/home_buttons_dislike_normal.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/home_buttons_info_normal.png b/app/src/main/filters/res/drawable-xhdpi/home_buttons_info_normal.png new file mode 100644 index 0000000..67896c4 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/home_buttons_info_normal.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/home_buttons_like_normal.png b/app/src/main/filters/res/drawable-xhdpi/home_buttons_like_normal.png new file mode 100644 index 0000000..f0bcc21 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/home_buttons_like_normal.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/home_buttons_like_pressed.png b/app/src/main/filters/res/drawable-xhdpi/home_buttons_like_pressed.png new file mode 100644 index 0000000..50a3872 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/home_buttons_like_pressed.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/hongrun.jpg b/app/src/main/filters/res/drawable-xhdpi/hongrun.jpg new file mode 100644 index 0000000..bc0c8d3 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/hongrun.jpg differ diff --git a/app/src/main/filters/res/drawable-xhdpi/ic_luck_location.png b/app/src/main/filters/res/drawable-xhdpi/ic_luck_location.png new file mode 100644 index 0000000..c00a646 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/ic_luck_location.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/ic_speed_man_bg.png b/app/src/main/filters/res/drawable-xhdpi/ic_speed_man_bg.png new file mode 100644 index 0000000..99798a3 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/ic_speed_man_bg.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/ic_speed_women_bg.png b/app/src/main/filters/res/drawable-xhdpi/ic_speed_women_bg.png new file mode 100644 index 0000000..9236192 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/ic_speed_women_bg.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/icon_msg_customer.png b/app/src/main/filters/res/drawable-xhdpi/icon_msg_customer.png new file mode 100644 index 0000000..1a45572 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/icon_msg_customer.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/icon_msg_notice.png b/app/src/main/filters/res/drawable-xhdpi/icon_msg_notice.png new file mode 100644 index 0000000..96a5c0f Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/icon_msg_notice.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/qinxin.jpg b/app/src/main/filters/res/drawable-xhdpi/qinxin.jpg new file mode 100644 index 0000000..25c93cc Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/qinxin.jpg differ diff --git a/app/src/main/filters/res/drawable-xhdpi/setting_mine_bg3.png b/app/src/main/filters/res/drawable-xhdpi/setting_mine_bg3.png new file mode 100644 index 0000000..7694101 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/setting_mine_bg3.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/setting_mine_bg4.png b/app/src/main/filters/res/drawable-xhdpi/setting_mine_bg4.png new file mode 100644 index 0000000..2f504e7 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/setting_mine_bg4.png differ diff --git a/app/src/main/filters/res/drawable-xhdpi/yuantu.jpg b/app/src/main/filters/res/drawable-xhdpi/yuantu.jpg new file mode 100644 index 0000000..66b5aa6 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/yuantu.jpg differ diff --git a/app/src/main/filters/res/drawable-xhdpi/ziran.jpg b/app/src/main/filters/res/drawable-xhdpi/ziran.jpg new file mode 100644 index 0000000..2832199 Binary files /dev/null and b/app/src/main/filters/res/drawable-xhdpi/ziran.jpg differ diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/EngineConfig.java b/app/src/main/java/com/fengliyan/tianlesue/agora/EngineConfig.java new file mode 100644 index 0000000..f7b5dfb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/EngineConfig.java @@ -0,0 +1,16 @@ +package com.fengliyan.tianlesue.agora; + +public class EngineConfig { + public int mClientRole; + public int mVideoProfile; + public int mUid; + public String mChannel; + + public void reset() { + mChannel = null; + } + + EngineConfig() { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/RtcEngineEventHandler.java b/app/src/main/java/com/fengliyan/tianlesue/agora/RtcEngineEventHandler.java new file mode 100644 index 0000000..86571da --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/RtcEngineEventHandler.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.agora; + +public interface RtcEngineEventHandler { + void onFirstRemoteVideoDecoded(int uid, int width, int height, int elapsed); + + void onJoinChannelSuccess(String channel, int uid, int elapsed); + + void onUserOffline(int uid, int reason); + + void onUserJoined(int uid, int elapsed); + + void onUserMuteVideo(int uid, boolean muted); + + void onConnectionStateChanged(int state, int reason, String channelId); + + void onRemoteVideoStateChanged(int uid, int state, int reason, int elapsed); + + void onNetworkQuality(int uid, int txQuality, int rxQuality); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/RtcEngineEventHandlerProxy.java b/app/src/main/java/com/fengliyan/tianlesue/agora/RtcEngineEventHandlerProxy.java new file mode 100644 index 0000000..0f7c0be --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/RtcEngineEventHandlerProxy.java @@ -0,0 +1,134 @@ +package com.fengliyan.tianlesue.agora; + +import android.util.Log; + +import java.util.ArrayList; + +import io.agora.rtc.IRtcEngineEventHandler; + +public class RtcEngineEventHandlerProxy extends IRtcEngineEventHandler { + private static final String TAG = "RtcEngineEventHandlerPr"; + private ArrayList mEventHandlers = new ArrayList<>(); + + public void addEventHandler(RtcEngineEventHandler handler) { + if (!mEventHandlers.contains(handler)) mEventHandlers.add(handler); + } + + @Override + public void onFirstRemoteVideoDecoded(int uid, int width, int height, int elapsed) { + for (RtcEngineEventHandler handler : mEventHandlers) { + handler.onFirstRemoteVideoDecoded(uid, width, height,elapsed); + } + } + + public void removeEventHandler(RtcEngineEventHandler handler) { + mEventHandlers.remove(handler); + } + + @Override + public void onJoinChannelSuccess(String channel, int uid, int elapsed) { + for (RtcEngineEventHandler handler : mEventHandlers) { + handler.onJoinChannelSuccess(channel, uid, elapsed); + } + } + + @Override + public void onUserJoined(int uid, int elapsed) { + for (RtcEngineEventHandler handler : mEventHandlers) { + handler.onUserJoined(uid, elapsed); + } + } + + @Override + public void onUserOffline(int uid, int reason) { + for (RtcEngineEventHandler handler : mEventHandlers) { + handler.onUserOffline(uid, reason); + } + } + + @Override + public void onUserMuteVideo(int uid, boolean muted) { + for (RtcEngineEventHandler handler : mEventHandlers) { + handler.onUserMuteVideo(uid, muted); + } + } + + @Override + public void onRemoteVideoStateChanged(int uid, int state, int reason, int elapsed) { + for (RtcEngineEventHandler handler : mEventHandlers) { + handler.onRemoteVideoStateChanged(uid, state, reason, elapsed); + } + } + + private int mCallbackCount; + private int mWidth; + private int mHeight; + private int mSumRenderFps; + private int mSumDecoderFps; + private int mSumReceivedBitrate; + + public static class StatsInfo { + public int width; + public int height; + public int renderFps; + public int decoderFps; + + public int receivedBitrate; + } + + public StatsInfo retrieveStatsInfo() { + StatsInfo statsInfo = new StatsInfo(); + synchronized (this) { + statsInfo.width = mWidth; + statsInfo.height = mHeight; + int count = mCallbackCount; + if (count > 0) { + statsInfo.renderFps = mSumRenderFps / count; + statsInfo.decoderFps = mSumDecoderFps / count; + statsInfo.receivedBitrate = mSumReceivedBitrate / count; + } + mCallbackCount = 0; + mSumRenderFps = 0; + mSumDecoderFps = 0; + mSumReceivedBitrate = 0; + } + return statsInfo; + } + + @Override + public void onRemoteVideoStats(RemoteVideoStats remoteVideoStats) { + super.onRemoteVideoStats(remoteVideoStats); + Log.i(TAG,"远端视频状态改变 :"+"receivedBitrate=="+remoteVideoStats.receivedBitrate+" --remoteVideoStats=="+remoteVideoStats.packetLossRate+" --decoderOutputFrameRate=="+remoteVideoStats.decoderOutputFrameRate+" --rendererOutputFrameRate=="+remoteVideoStats.rendererOutputFrameRate+" --totalFrozenTime"+remoteVideoStats.totalFrozenTime+" --frozenRate"+remoteVideoStats.frozenRate); +// Log.d(TAG, String.format("onRemoteVideoStats. width %d, height %d, " + +// "delay %d, receivedBitrate %d, decoderOutputFrameRate %d, rendererOutputFrameRate %d, " + +// "packetLossRate %d, totalFrozenTime %d, totalActiveTime %d, rxStreamType %d", +// remoteVideoStats.width, remoteVideoStats.height, remoteVideoStats.delay, remoteVideoStats.receivedBitrate, +// remoteVideoStats.decoderOutputFrameRate, remoteVideoStats.rendererOutputFrameRate, +// remoteVideoStats.packetLossRate, remoteVideoStats.totalFrozenTime, remoteVideoStats.totalActiveTime, +// remoteVideoStats.rxStreamType)); +// synchronized (this) { +// mWidth = remoteVideoStats.width; +// mHeight = remoteVideoStats.height; +// mSumRenderFps += remoteVideoStats.rendererOutputFrameRate; +// mSumDecoderFps += remoteVideoStats.decoderOutputFrameRate; +// mSumReceivedBitrate += remoteVideoStats.receivedBitrate; +// ++mCallbackCount; +// } + } + + @Override + public void onLocalVideoStats(LocalVideoStats stats) { + super.onLocalVideoStats(stats); + Log.i(TAG,"本地视频状态 :"+"rendererOutputFrameRate=="+stats.rendererOutputFrameRate+" --encoderOutputFrameRate=="+stats.encoderOutputFrameRate+" --targetBitrate=="+stats.targetBitrate+" --targetFrameRate=="+stats.targetFrameRate+" --encodedBitrate"+stats.encodedBitrate+" --sentBitrate"+stats.sentBitrate+" --sentFrameRate=="+stats.sentFrameRate+" --encodedFrameCount=="+stats.encodedFrameCount+" --codecType=="+stats.codecType+"--qualityAdaptIndication=="+stats.qualityAdaptIndication); + + + } + @Override + public void onNetworkQuality(int uid, int txQuality, int rxQuality) { + super.onNetworkQuality(uid, txQuality, rxQuality); + for (RtcEngineEventHandler handler : mEventHandlers) { + handler.onNetworkQuality(uid, txQuality,rxQuality); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/framework/PreprocessorFaceUnity.java b/app/src/main/java/com/fengliyan/tianlesue/agora/framework/PreprocessorFaceUnity.java new file mode 100644 index 0000000..1468163 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/framework/PreprocessorFaceUnity.java @@ -0,0 +1,161 @@ +package com.fengliyan.tianlesue.agora.framework; + +import android.content.Context; +import android.opengl.GLES20; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.model.facebeauty.FaceBeautyBlurTypeEnum; +import com.faceunity.nama.FUConfig; +import com.faceunity.nama.FURenderer; +import com.faceunity.nama.utils.FuDeviceUtils; +import com.fengliyan.tianlesue.agora.profile.CSVUtils; + +import io.agora.capture.framework.modules.channels.VideoChannel; +import io.agora.capture.framework.modules.processors.IPreprocessor; +import io.agora.capture.video.camera.VideoCaptureFrame; + +public class PreprocessorFaceUnity implements IPreprocessor { + private final static String TAG = PreprocessorFaceUnity.class.getSimpleName(); + + private FURenderer mFURenderer = FURenderer.getInstance(); + private boolean renderSwitch; + private int skipFrame = 0; + + private Handler mGLHandler; + + public void setCSVUtils(CSVUtils cSVUtils) { + this.mCSVUtils = cSVUtils; + } + + private CSVUtils mCSVUtils; + + public PreprocessorFaceUnity(Context context) { + } + + @Override + public VideoCaptureFrame onPreProcessFrame(VideoCaptureFrame outFrame, VideoChannel.ChannelContext context) { + if (!renderSwitch) { + return outFrame; + } + if (mGLHandler == null) { + startGLThread(); + } + if (skipFrame > 0) { + skipFrame--; + outFrame.textureId = 0; + return outFrame; + } + mFURenderer.setInputOrientation(outFrame.rotation); + + if (FUConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID)//高性能设备 + cheekFaceNum(); + + long start = System.nanoTime(); + int texId = mFURenderer.onDrawFrameDualInput(outFrame.image, + outFrame.textureId, outFrame.format.getWidth(), + outFrame.format.getHeight()); + + long renderTime = System.nanoTime() - start; + if (mCSVUtils != null) { + mCSVUtils.writeCsv(null, renderTime); + } + + // The texture is transformed to texture2D by beauty module. + if (skipFrame <= 0) { + outFrame.textureId = texId; + outFrame.format.setTexFormat(GLES20.GL_TEXTURE_2D); + } else { + outFrame.textureId = 0; + } + return outFrame; + } + + + @Override + public void initPreprocessor() { + // only call once when app launched + Log.e(TAG, "initPreprocessor: "); + } + + @Override + public void enablePreProcess(boolean enabled) { + Log.e(TAG, "enablePreProcess: "); + } + + @Override + public void releasePreprocessor(VideoChannel.ChannelContext context) { + // not called + Log.d(TAG, "releasePreprocessor: "); + } + + + /* 创建线程 */ + private void startGLThread() { + if (mGLHandler == null) { + mGLHandler = new Handler(Looper.myLooper()); + mGLHandler.post(() -> {if (mSurfaceViewListener !=null ) mSurfaceViewListener.onSurfaceCreated();}); + } + } + + public void doGLAction(Runnable runnable) { + if (mGLHandler != null) { + mGLHandler.post(runnable); + } + } + + public void setRenderEnable(boolean enabled) { + renderSwitch = enabled; + } + + + public void skipFrame() { + skipFrame = 5; + } + + public void releaseFURender() { + renderSwitch = false; + if(mGLHandler!=null){ + mGLHandler.removeCallbacksAndMessages(0); + mGLHandler.post(() -> { + if (mSurfaceViewListener !=null ) mSurfaceViewListener.onSurfaceDestroyed(); + }); + } + + mGLHandler = null; + } + + private SurfaceViewListener mSurfaceViewListener; + + public interface SurfaceViewListener{ + void onSurfaceCreated(); + void onSurfaceDestroyed(); + } + + public void setSurfaceListener(SurfaceViewListener surfaceViewListener) { + this.mSurfaceViewListener = surfaceViewListener; + } + + /** + * 检查当前人脸数量 + */ + private void cheekFaceNum() { + //根据有无人脸 + 设备性能 判断开启的磨皮类型 + float faceProcessorGetConfidenceScore = FUAIKit.getInstance().getFaceProcessorGetConfidenceScore(0); + if (faceProcessorGetConfidenceScore >= 0.95) { + //高端手机并且检测到人脸开启均匀磨皮,人脸点位质 + if (FURenderKit.getInstance() != null && FURenderKit.getInstance().getFaceBeauty() != null && FURenderKit.getInstance().getFaceBeauty().getBlurType() != FaceBeautyBlurTypeEnum.EquallySkin) { + FURenderKit.getInstance().getFaceBeauty().setBlurType(FaceBeautyBlurTypeEnum.EquallySkin); + FURenderKit.getInstance().getFaceBeauty().setEnableBlurUseMask(true); + } + } else { + if (FURenderKit.getInstance() != null && FURenderKit.getInstance().getFaceBeauty() != null && FURenderKit.getInstance().getFaceBeauty().getBlurType() != FaceBeautyBlurTypeEnum.FineSkin) { + FURenderKit.getInstance().getFaceBeauty().setBlurType(FaceBeautyBlurTypeEnum.FineSkin); + FURenderKit.getInstance().getFaceBeauty().setEnableBlurUseMask(false); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/framework/RtcVideoConsumer.java b/app/src/main/java/com/fengliyan/tianlesue/agora/framework/RtcVideoConsumer.java new file mode 100644 index 0000000..32cec4f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/framework/RtcVideoConsumer.java @@ -0,0 +1,138 @@ +package com.fengliyan.tianlesue.agora.framework; + +import android.opengl.GLES20; +import android.util.Log; + +import io.agora.capture.framework.modules.channels.ChannelManager; +import io.agora.capture.framework.modules.channels.VideoChannel; +import io.agora.capture.framework.modules.consumers.IVideoConsumer; +import io.agora.capture.video.camera.VideoCaptureFrame; +import io.agora.capture.video.camera.VideoModule; +import io.agora.rtc.mediaio.IVideoFrameConsumer; +import io.agora.rtc.mediaio.IVideoSource; +import io.agora.rtc.mediaio.MediaIO; +import io.agora.rtc.video.AgoraVideoFrame; + +/** + * The renderer acts as the consumer of the video source + * from current video channel, and also the video source + * of rtc engine. + */ +public class RtcVideoConsumer implements IVideoConsumer, IVideoSource { + private static final String TAG = RtcVideoConsumer.class.getSimpleName(); + + private volatile IVideoFrameConsumer mRtcConsumer; + private volatile boolean mValidInRtc; + + private volatile VideoModule mVideoModule; + private int mChannelId; + + public RtcVideoConsumer() { + this(ChannelManager.ChannelID.CAMERA); + } + + private RtcVideoConsumer(int channelId) { + mVideoModule = VideoModule.instance(); + mChannelId = channelId; + } + + @Override + public void onConsumeFrame(VideoCaptureFrame frame, VideoChannel.ChannelContext context) { + if (mValidInRtc) { + int format = frame.format.getTexFormat() == GLES20.GL_TEXTURE_2D + ? AgoraVideoFrame.FORMAT_TEXTURE_2D + : AgoraVideoFrame.FORMAT_TEXTURE_OES; + if (mRtcConsumer != null) { + mRtcConsumer.consumeTextureFrame(frame.textureId, format, + frame.format.getWidth(), frame.format.getHeight(), + frame.rotation, frame.timestamp, frame.textureTransform); + } + } + } + + @Override + public void connectChannel(int channelId) { + // Rtc transmission is an off-screen rendering procedure. + VideoChannel channel = mVideoModule.connectConsumer( + this, channelId, IVideoConsumer.TYPE_OFF_SCREEN); + } + + @Override + public void disconnectChannel(int channelId) { + mVideoModule.disconnectConsumer(this, channelId); + } + + @Override + public void setMirrorMode(int mode) { + + } + + @Override + public Object getDrawingTarget() { + return null; + } + + @Override + public int onMeasuredWidth() { + return 0; + } + + @Override + public int onMeasuredHeight() { + return 0; + } + + @Override + public void recycle() { + + } + + @Override + public String getId() { + return null; + } + + @Override + public boolean onInitialize(IVideoFrameConsumer consumer) { + Log.i(TAG, "onInitialize"); + mRtcConsumer = consumer; + return true; + } + + @Override + public boolean onStart() { + Log.i(TAG, "onStart"); + connectChannel(mChannelId); + mValidInRtc = true; + return true; + } + + @Override + public void onStop() { + mValidInRtc = false; + mRtcConsumer = null; + } + + @Override + public void onDispose() { + Log.i(TAG , "onDispose"); + mValidInRtc = false; + mRtcConsumer = null; + disconnectChannel(mChannelId); + } + + @Override + public int getBufferType() { + return MediaIO.BufferType.TEXTURE.intValue(); + } + + @Override + public int getCaptureType() { + return 0; + } + + @Override + public int getContentHint() { + return 0; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/profile/CPUInfoUtil.java b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/CPUInfoUtil.java new file mode 100644 index 0000000..cb6b898 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/CPUInfoUtil.java @@ -0,0 +1,172 @@ +package com.fengliyan.tianlesue.agora.profile; + +import android.content.Context; +import android.os.Build; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.RandomAccessFile; + +/** + * cpu使用率获取工具类 + * Created by lirui on 2017/8/2. + */ + +public class CPUInfoUtil { + private long lastTotalCpu = 0; + private long lastProcessCpu = 0; + + private final String PackageName; + + private volatile boolean isRunningCPU = false; + private volatile double cpuRate = 0; + + public CPUInfoUtil(Context context) { + if (Build.VERSION.SDK_INT >= 26) { + final String pn = context.getPackageName(); + if (pn.length() <= 16) { + PackageName = pn; + } else { + PackageName = pn.substring(0, 15) + "+"; + } +// Log.e(TAG, "CSVUtils PackageName " + PackageName); + isRunningCPU = true; + CPUInfoThread cpuinfothread = new CPUInfoThread(); + cpuinfothread.start(); + } else { + PackageName = null; + } + } + + public double getProcessCpuUsed() { + if (Build.VERSION.SDK_INT >= 26) { + return cpuRate; + } else { + double pcpu = 0; + double tmp = 1.0; + long nowTotalCpu = getTotalCpu(); + long nowProcessCpu = getMyProcessCpu(); + if (nowTotalCpu != 0 && (nowTotalCpu - lastTotalCpu) != 0) { +// Log.e(TAG, "cpu used nowProcessCpu " + nowProcessCpu + " lastProcessCpu " + lastProcessCpu + " nowTotalCpu " + nowTotalCpu + " lastTotalCpu " + lastTotalCpu); + pcpu = 100 * (tmp * (nowProcessCpu - lastProcessCpu) / (nowTotalCpu - lastTotalCpu)); + } + lastProcessCpu = nowProcessCpu; + lastTotalCpu = nowTotalCpu; + return pcpu < 0 ? 0 : pcpu; + } + } + + public void close() { + if (Build.VERSION.SDK_INT >= 26) { + isRunningCPU = false; + } + } + + private long getTotalCpu() { + String[] cpuInfos = null; + try { + RandomAccessFile reader = null; + reader = new RandomAccessFile("/proc/stat", "r"); + String load = reader.readLine(); + reader.close(); + cpuInfos = load.split(" "); + } catch (IOException e) { + e.printStackTrace(); + return 0; + } + long totalCpu = 0; + try { + totalCpu = Long.parseLong(cpuInfos[2]) + + Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4]) + + Long.parseLong(cpuInfos[6]) + Long.parseLong(cpuInfos[5]) + + Long.parseLong(cpuInfos[7]) + Long.parseLong(cpuInfos[8]); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + return 0; + } + return totalCpu; + } + + private long getMyProcessCpu() { + String[] cpuInfos = null; + try { + int pid = android.os.Process.myPid(); + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream("/proc/" + pid + "/stat")), 1000); + String load = reader.readLine(); + reader.close(); + cpuInfos = load.split(" "); + } catch (IOException e) { + e.printStackTrace(); + return 0; + } + long appCpuTime = 0; + try { + appCpuTime = Long.parseLong(cpuInfos[13]) + + Long.parseLong(cpuInfos[14]) + Long.parseLong(cpuInfos[15]) + + Long.parseLong(cpuInfos[16]); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + return 0; + } + return appCpuTime; + } + + class CPUInfoThread extends Thread { + + private double allCPU = 0; + + @Override + public void run() { + String line = null; + InputStream is = null; + try { + + Runtime runtime = Runtime.getRuntime(); + Process proc = runtime.exec("top -d 1"); + is = proc.getInputStream(); + + // 换成BufferedReader + BufferedReader buf = new BufferedReader(new InputStreamReader(is)); + do { + line = buf.readLine(); + if (allCPU == 0 && line.contains("user") && line.contains("nice") && line.contains("sys") && line.contains("idle") && line.contains("iow") && line.contains("irq") && line.contains("sirq") && line.contains("host")) { + if (line.indexOf("%cpu ") > 0) + allCPU = Double.parseDouble(line.split("%cpu ")[0]); + if (allCPU == 0) { + String[] s = line.split("%,"); + for (String st : s) { + String[] sts = st.split(" "); + if (sts.length > 0) + allCPU += Double.parseDouble(sts[sts.length - 1]); + } + } + } + // 读取到相应pkgName跳出循环(或者未找到) + if (line == null || line.endsWith(PackageName)) { +// Log.e(TAG, "cpu line : " + line); + String str[] = line.split(" "); + int t = 0; + for (int i = str.length - 1; i > 0; i--) { + if (!str[i].isEmpty() && ++t == 4) { +// Log.e(TAG, "cpu : " + str[i] + " allCPU " + allCPU); + cpuRate = 100 * Double.parseDouble(str[i]) / allCPU; + } + } + continue; + } + } while (isRunningCPU); + + if (is != null) { + buf.close(); + is.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/profile/CSVUtils.java b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/CSVUtils.java new file mode 100644 index 0000000..8437515 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/CSVUtils.java @@ -0,0 +1,188 @@ +package com.fengliyan.tianlesue.agora.profile; + +import android.app.ActivityManager; +import android.content.Context; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; +import android.util.Log; + +import com.fengliyan.tianlesue.agora.RtcEngineEventHandlerProxy; +import com.fengliyan.tianlesue.agora.utils.FPSUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + + +/** + * Created by tujh on 2017/11/2. + */ +public class CSVUtils { + public static final String TAG = CSVUtils.class.getSimpleName(); + /* 每 100 帧统计一次 */ + public static final int FRAME_STEP = 100; + + public static final String COMMA = ","; + + private OutputStreamWriter mStreamWriter; + + private ActivityManager mActivityManager; + + private Handler mHandler; + + private CPUInfoUtil mCPUInfoUtil; + + private int mFrameRate; + private volatile double mCpuUsed; + private volatile double mAverageFps; + private volatile double mAverageRenderTime; + private volatile double mMemory; + private long mSumRenderTimeInNano; + private volatile long mTimestamp; + + //private RtcEngineEventHandlerProxy mRtcEngineEventHandler; + + public void setRtcEngineEventHandler(RtcEngineEventHandlerProxy rtcEngineEventHandlerProxy) { + //mRtcEngineEventHandler = rtcEngineEventHandlerProxy; + } + + public CSVUtils(Context context) { + mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + mCPUInfoUtil = new CPUInfoUtil(context); + + HandlerThread handlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + mHandler = new Handler(handlerThread.getLooper()); + } + + public void initHeader(String folderName, StringBuilder headerInfo) { + Log.d(TAG, "initHeader() called with: folderName = [" + folderName + "], headerInfo = [" + headerInfo + "]"); + StringBuilder stringBuilder = new StringBuilder().append("时间").append(COMMA) + .append("帧率").append(COMMA) + .append("渲染耗时").append(COMMA) + .append("CPU").append(COMMA) + .append("内存").append(COMMA) + .append("远端分辨率").append(COMMA) + .append("远端渲染帧率").append(COMMA) + .append("远端解码帧率").append(COMMA) + .append("远端接收码率").append(COMMA); + if (headerInfo != null) { + stringBuilder.append(headerInfo); + } + stringBuilder.append("\n"); + + File file = new File(folderName); + File parentFile = file.getParentFile(); + if (!parentFile.exists()) { + parentFile.mkdirs(); + } + try { + if (!file.exists()) { + file.createNewFile(); + } + mStreamWriter = new OutputStreamWriter(new FileOutputStream(file, false), "GBK"); + } catch (IOException e) { + Log.e(TAG, "CSVUtils: ", e); + } + flush(stringBuilder); + mTimestamp = System.currentTimeMillis(); + } + + public void writeCsv(final StringBuilder extraInfo, long renderTimeInNano) { + if (mStreamWriter == null) { + return; + } + + mSumRenderTimeInNano += renderTimeInNano; + if (mFrameRate % FRAME_STEP == FRAME_STEP - 1) { + mTimestamp = System.currentTimeMillis(); + mAverageFps = FPSUtil.fpsAVG(FRAME_STEP); + mAverageRenderTime = (double) mSumRenderTimeInNano / FRAME_STEP / 1_000_000; + mSumRenderTimeInNano = 0; + mHandler.post(new Runnable() { + @Override + public void run() { + mCpuUsed = mCPUInfoUtil.getProcessCpuUsed(); + mMemory = MemoryInfoUtil.getMemory(mActivityManager.getProcessMemoryInfo(new int[]{Process.myPid()})); + String strCPU = String.format(Locale.getDefault(), "%.2f", mCpuUsed); + String strMemory = String.format(Locale.getDefault(), "%.2f", mMemory); + + StringBuilder stringBuilder = new StringBuilder(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS", Locale.getDefault()); + //RtcEngineEventHandlerProxy.StatsInfo statsInfo = mRtcEngineEventHandler.retrieveStatsInfo(); + stringBuilder.append(dateFormat.format(new Date(mTimestamp))).append(COMMA) + .append(String.format(Locale.getDefault(), "%.2f", mAverageFps)).append(COMMA) + .append(String.format(Locale.getDefault(), "%.2f", mAverageRenderTime)).append(COMMA) + .append(strCPU).append(COMMA) + .append(strMemory).append(COMMA) + /*.append(statsInfo.width).append("x") + .append(statsInfo.height).append(COMMA) + .append(statsInfo.renderFps).append(COMMA) + .append(statsInfo.decoderFps).append(COMMA) + .append(statsInfo.receivedBitrate).append(COMMA)*/; + Log.d(TAG, "Fps:" + String.format(Locale.getDefault(), "%.2f", mAverageFps) + + " Render Time:" + String.format(Locale.getDefault(), "%.2f", mAverageRenderTime)); + if (extraInfo != null) { + stringBuilder.append(extraInfo); + } + stringBuilder.append("\n"); + flush(stringBuilder); + } + }); + } + mFrameRate++; + } + + private void flush(StringBuilder stringBuilder) { + if (mStreamWriter == null) { + return; + } + try { + mStreamWriter.write(stringBuilder.toString()); + mStreamWriter.flush(); + } catch (IOException e) { + Log.e(TAG, "flush: ", e); + } + } + + public void close() { + Log.d(TAG, "close: "); + mHandler.post(new Runnable() { + @Override + public void run() { + if (mStreamWriter != null) { + try { + mStreamWriter.close(); + mStreamWriter = null; + } catch (IOException e) { + Log.e(TAG, "close: ", e); + } + } + } + }); + mHandler.getLooper().quitSafely(); + mHandler = null; + mCPUInfoUtil.close(); + } + + public double getCpuUsed() { + return mCpuUsed; + } + + public double getMemory() { + return mMemory; + } + + public double getAverageRenderTime() { + return mAverageRenderTime; + } + + public double getAverageFps() { + return mAverageFps; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/profile/Constant.java b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/Constant.java new file mode 100644 index 0000000..ecb8831 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/Constant.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.agora.profile; + +import android.os.Build; +import android.os.Environment; + +import java.io.File; +import java.util.regex.Pattern; + +/** + * Created by tujh on 2018/2/7. + */ + +public class Constant { + public static final String APP_NAME = "AgoraVideo"; + public static final String filePath = Environment.getExternalStoragePublicDirectory("") + + File.separator + "FaceUnity" + File.separator + APP_NAME + File.separator; + + public static final String DICMFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath(); + public static final String photoFilePath; + public static final String cameraFilePath; + + static { + if (Build.FINGERPRINT.contains("Flyme") + || Pattern.compile("Flyme", Pattern.CASE_INSENSITIVE).matcher(Build.DISPLAY).find() + || Build.MANUFACTURER.contains("Meizu") + || Build.MANUFACTURER.contains("MeiZu")) { + photoFilePath = DICMFilePath + File.separator + "Camera" + File.separator; + cameraFilePath = DICMFilePath + File.separator + "Video" + File.separator; + } else if (Build.FINGERPRINT.contains("vivo") + || Pattern.compile("vivo", Pattern.CASE_INSENSITIVE).matcher(Build.DISPLAY).find() + || Build.MANUFACTURER.contains("vivo") + || Build.MANUFACTURER.contains("vivo")) { + photoFilePath = cameraFilePath = Environment.getExternalStoragePublicDirectory("") + File.separator + "相机" + File.separator; + } else { + cameraFilePath = photoFilePath = DICMFilePath + File.separator + "Camera" + File.separator; + } + createFile(filePath); + createFile(cameraFilePath); + createFile(photoFilePath); + } + + public static void createFile(String path) { + File dir = new File(path); + if (!dir.exists()) { + dir.mkdirs(); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/profile/MemoryInfoUtil.java b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/MemoryInfoUtil.java new file mode 100644 index 0000000..74be587 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/profile/MemoryInfoUtil.java @@ -0,0 +1,90 @@ +package com.fengliyan.tianlesue.agora.profile; + +import android.os.Build; +import android.os.Debug; + +import androidx.annotation.RequiresApi; + +import java.lang.reflect.Field; + +/** + * 内存使用率获取工具类 + * Created by tujh on 2018/5/24. + */ +public abstract class MemoryInfoUtil { + + @RequiresApi(api = Build.VERSION_CODES.M) + public static double getMemory(Debug.MemoryInfo[] memoryInfos) { + try { + if (Build.VERSION.SDK_INT >= 27) { + return compute(memoryInfos); + } + + Field otherStats_Field = memoryInfos[0].getClass().getDeclaredField("otherStats"); + otherStats_Field.setAccessible(true); + int[] otherStats = (int[]) otherStats_Field.get(memoryInfos[0]); + + Field NUM_CATEGORIES_Field = memoryInfos[0].getClass().getDeclaredField("NUM_CATEGORIES"); + Field offsetPrivateClean_Field = memoryInfos[0].getClass().getDeclaredField("offsetPrivateClean"); + Field offsetPrivateDirty_Field = memoryInfos[0].getClass().getDeclaredField("offsetPrivateDirty"); + final int NUM_CATEGORIES = (int) NUM_CATEGORIES_Field.get(memoryInfos[0]); + final int offsetPrivateClean = (int) offsetPrivateClean_Field.get(memoryInfos[0]); + final int offsetPrivateDirty = (int) offsetPrivateDirty_Field.get(memoryInfos[0]); + + int javaHeap = memoryInfos[0].dalvikPrivateDirty + + otherStats[12 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[12 * NUM_CATEGORIES + offsetPrivateDirty]; + int nativeHeap = memoryInfos[0].nativePrivateDirty; + int code = otherStats[6 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[6 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[7 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[7 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[8 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[8 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[9 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[9 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[10 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[10 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[11 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[11 * NUM_CATEGORIES + offsetPrivateDirty]; + int stack = otherStats[NUM_CATEGORIES + offsetPrivateDirty]; + int graphics = otherStats[4 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[4 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[14 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[14 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[15 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[15 * NUM_CATEGORIES + offsetPrivateDirty]; + int other = otherStats[0 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[0 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[2 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[2 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[3 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[3 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[5 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[5 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[13 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[13 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[16 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[16 * NUM_CATEGORIES + offsetPrivateDirty]; + int all = javaHeap + nativeHeap + code + stack + graphics + other; +// Log.d("MemoryAll", "javaHeap=" + javaHeap +// + "\nnativeHeap=" + nativeHeap + "\ncode=" + code + "\nstack=" + stack +// + "\ngraphics=" + graphics + "\nother=" + other); +// Log.e(TAG, "memory " + memoryStr +// + " java-heap " + String.format("%.2f", ((double) javaHeap) / 1024) +// + " native-heap " + String.format("%.2f", ((double) nativeHeap) / 1024) +// + " code " + String.format("%.2f", ((double) code) / 1024) +// + " stack " + String.format("%.2f", ((double) stack) / 1024) +// + " graphics " + String.format("%.2f", ((double) graphics) / 1024) +// + " other " + String.format("%.2f", ((double) other) / 1024) +// + " pps " + String.format("%.2f", ((double) memoryInfos[0].getTotalPss()) / 1024) +// ); + return ((double) all) / 1024; + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + + @RequiresApi(api = Build.VERSION_CODES.M) + private static double compute(Debug.MemoryInfo[] memInfo) { + String java_mem = memInfo[0].getMemoryStat("summary.java-heap"); + String native_mem = memInfo[0].getMemoryStat("summary.native-heap"); + String graphics_mem = memInfo[0].getMemoryStat("summary.graphics"); + String stack_mem = memInfo[0].getMemoryStat("summary.stack"); + String code_mem = memInfo[0].getMemoryStat("summary.code"); + String others_mem = memInfo[0].getMemoryStat("summary.system"); + int all = Integer.parseInt(java_mem) + + Integer.parseInt(native_mem) + + Integer.parseInt(graphics_mem) + + Integer.parseInt(stack_mem) + + Integer.parseInt(code_mem) + + Integer.parseInt(others_mem); + return ((double) all) / 1024; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/DiscreteSeekBar.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/DiscreteSeekBar.java new file mode 100644 index 0000000..5f2b056 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/DiscreteSeekBar.java @@ -0,0 +1,1065 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewParent; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.DrawableCompat; +import androidx.core.view.ViewCompat; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.PopupIndicator; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.compat.AnimatorCompat; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.compat.SeekBarCompat; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.MarkerDrawable; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.ThumbDrawable; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.TrackRectDrawable; + +import java.util.Formatter; +import java.util.Locale; + + +public class DiscreteSeekBar extends View { + private static final String TAG = DiscreteSeekBar.class.getSimpleName(); + + /** + * Interface to propagate seekbar change getEventHandler + */ + public interface OnProgressChangeListener { + /** + * When the {@link DiscreteSeekBar} value changes + * + * @param seekBar The DiscreteSeekBar + * @param value the new value + * @param fromUser if the change was made from the user or not (i.e. the developer calling {@link #setProgress(int)} + */ + public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser); + + public void onStartTrackingTouch(DiscreteSeekBar seekBar); + + public void onStopTrackingTouch(DiscreteSeekBar seekBar); + } + + /** + * Interface to transform the current internal value of this DiscreteSeekBar to anther one for the visualization. + *

+ * This will be used on the floating bubble to display a different value if needed. + *

+ * Using this in conjunction with {@link #setIndicatorFormatter(String)} you will be able to manipulate the + * value seen by the user + * + * @see #setIndicatorFormatter(String) + * @see #setNumericTransformer(DiscreteSeekBar.NumericTransformer) + */ + public static abstract class NumericTransformer { + /** + * Return the desired value to be shown to the user. + * This value will be formatted using the format specified by {@link #setIndicatorFormatter} before displaying it + * + * @param value The value to be transformed + * @return The transformed int + */ + public abstract int transform(int value); + + /** + * Return the desired value to be shown to the user. + * This value will be displayed 'as is' without further formatting. + * + * @param value The value to be transformed + * @return A formatted string + */ + public String transformToString(int value) { + return String.valueOf(value); + } + + /** + * Used to indicate which transform will be used. If this method returns true, + * {@link #transformToString(int)} will be used, otherwise {@link #transform(int)} + * will be used + */ + public boolean useStringTransform() { + return false; + } + } + + + private static class DefaultNumericTransformer extends NumericTransformer { + + @Override + public int transform(int value) { + return value; + } + } + + + private static final boolean isLollipopOrGreater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; + //We want to always use a formatter so the indicator numbers are "translated" to specific locales. + private static final String DEFAULT_FORMATTER = "%d"; + + private static final int PRESSED_STATE = android.R.attr.state_pressed; + private static final int FOCUSED_STATE = android.R.attr.state_focused; + private static final int PROGRESS_ANIMATION_DURATION = 250; + private static final int INDICATOR_DELAY_FOR_TAPS = 150; + private static final int DEFAULT_THUMB_COLOR = 0xff009688; + private static final int SEPARATION_DP = 5; + private ThumbDrawable mThumb; + private TrackRectDrawable mTrack; + private TrackRectDrawable mTrackBase; + private TrackRectDrawable mScrubber; + private Drawable mRipple; + + private int mTrackHeight; + private int mTrackBaseHeight; + private int mScrubberHeight; + private final int mAddedTouchBounds; + + private int mMax; + private int mMin; + private int mValue; + private int mKeyProgressIncrement = 1; + private boolean mMirrorForRtl = false; + private boolean mAllowTrackClick = true; + private boolean mIndicatorPopupEnabled = true; + //We use our own Formatter to avoid creating new instances on every progress change + Formatter mFormatter; + private String mIndicatorFormatter; + private NumericTransformer mNumericTransformer; + private StringBuilder mFormatBuilder; + private OnProgressChangeListener mPublicChangeListener; + private boolean mIsDragging; + private int mDragOffset; + + private Rect mInvalidateRect = new Rect(); + private Rect mTempRect = new Rect(); + private PopupIndicator mIndicator; + private AnimatorCompat mPositionAnimator; + private float mAnimationPosition; + private int mAnimationTarget; + private float mDownX; + private float mTouchSlop; + + private int mValueBase; + + public DiscreteSeekBar(Context context) { + this(context, null); + } + + public DiscreteSeekBar(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.discreteSeekBarStyle); + } + + public DiscreteSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setFocusable(true); + setWillNotDraw(false); + + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + float density = context.getResources().getDisplayMetrics().density; + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DiscreteSeekBar, + defStyleAttr, R.style.Widget_DiscreteSeekBar); + + int max = 100; + int min = 0; + mMirrorForRtl = a.getBoolean(R.styleable.DiscreteSeekBar_dsb_mirrorForRtl, mMirrorForRtl); + mAllowTrackClick = a.getBoolean(R.styleable.DiscreteSeekBar_dsb_allowTrackClickToDrag, mAllowTrackClick); + mIndicatorPopupEnabled = a.getBoolean(R.styleable.DiscreteSeekBar_dsb_indicatorPopupEnabled, mIndicatorPopupEnabled); + mTrackHeight = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_trackHeight, (int) (1 * density)); + mTrackBaseHeight = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_trackBaseHeight, (int) (1 * density)); + mScrubberHeight = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_scrubberHeight, (int) (4 * density)); + int thumbSize = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_thumbSize, (int) (density * ThumbDrawable.DEFAULT_SIZE_DP)); + int separation = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_indicatorSeparation, + (int) (SEPARATION_DP * density)); + + //Extra pixels for a minimum touch area of 32dp + int touchBounds = (int) (density * 32); + mAddedTouchBounds = Math.max(0, (touchBounds - thumbSize) / 2); + + int indexMax = R.styleable.DiscreteSeekBar_dsb_max; + int indexMin = R.styleable.DiscreteSeekBar_dsb_min; + int indexValue = R.styleable.DiscreteSeekBar_dsb_value; + final TypedValue out = new TypedValue(); + //Not sure why, but we wanted to be able to use dimensions here... + if (a.getValue(indexMax, out)) { + if (out.type == TypedValue.TYPE_DIMENSION) { + max = a.getDimensionPixelSize(indexMax, max); + } else { + max = a.getInteger(indexMax, max); + } + } + if (a.getValue(indexMin, out)) { + if (out.type == TypedValue.TYPE_DIMENSION) { + min = a.getDimensionPixelSize(indexMin, min); + } else { + min = a.getInteger(indexMin, min); + } + } + if (a.getValue(indexValue, out)) { + if (out.type == TypedValue.TYPE_DIMENSION) { + mValueBase = a.getDimensionPixelSize(indexValue, mValueBase); + } else { + mValueBase = a.getInteger(indexValue, mValueBase); + } + } + + mMin = min; + mMax = Math.max(min + 1, max); + mValue = Math.max(min, Math.min(max, mValueBase)); + updateKeyboardRange(); + + mIndicatorFormatter = a.getString(R.styleable.DiscreteSeekBar_dsb_indicatorFormatter); + + ColorStateList trackColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_trackColor); + ColorStateList progressColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_progressColor); + ColorStateList rippleColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_rippleColor); + boolean editMode = isInEditMode(); + if (editMode || rippleColor == null) { + rippleColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.DKGRAY}); + } + if (editMode || trackColor == null) { + trackColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.GRAY}); + } + if (editMode || progressColor == null) { + progressColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{DEFAULT_THUMB_COLOR}); + } + + mRipple = SeekBarCompat.getRipple(rippleColor); + if (isLollipopOrGreater) { + SeekBarCompat.setBackground(this, mRipple); + } else { + mRipple.setCallback(this); + } + + TrackRectDrawable shapeDrawable = new TrackRectDrawable(trackColor); + mTrack = shapeDrawable; + mTrack.setCallback(this); + + mTrackBase = new TrackRectDrawable(trackColor); + mTrackBase.setCallback(this); + + shapeDrawable = new TrackRectDrawable(progressColor); + mScrubber = shapeDrawable; + mScrubber.setCallback(this); + + mThumb = new ThumbDrawable(progressColor, thumbSize); + mThumb.setCallback(this); + mThumb.setBounds(0, 0, mThumb.getIntrinsicWidth(), mThumb.getIntrinsicHeight()); + + + if (!editMode) { + mIndicator = new PopupIndicator(context, attrs, defStyleAttr, convertValueToMessage(mMax), + thumbSize, thumbSize + mAddedTouchBounds + separation); + mIndicator.setListener(mFloaterListener); + } + a.recycle(); + + setNumericTransformer(new DefaultNumericTransformer()); + + } + + /** + * Sets the current Indicator formatter string + * + * @param formatter + * @see String#format(String, Object...) + * @see #setNumericTransformer(DiscreteSeekBar.NumericTransformer) + */ + public void setIndicatorFormatter(@Nullable String formatter) { + mIndicatorFormatter = formatter; + updateProgressMessage(mValue); + } + + /** + * Sets the current {@link DiscreteSeekBar.NumericTransformer} + * + * @param transformer + * @see #getNumericTransformer() + */ + public void setNumericTransformer(@Nullable NumericTransformer transformer) { + mNumericTransformer = transformer != null ? transformer : new DefaultNumericTransformer(); + //We need to refresh the PopupIndicator view + updateIndicatorSizes(); + updateProgressMessage(mValue); + } + + /** + * Retrieves the current {@link DiscreteSeekBar.NumericTransformer} + * + * @return NumericTransformer + * @see #setNumericTransformer + */ + public NumericTransformer getNumericTransformer() { + return mNumericTransformer; + } + + /** + * Sets the maximum value for this DiscreteSeekBar + * if the supplied argument is smaller than the Current MIN value, + * the MIN value will be set to MAX-1 + *

+ *

+ * Also if the current progress is out of the new range, it will be set to MIN + *

+ * + * @param max + * @see #setMin(int) + * @see #setProgress(int) + */ + public void setMax(int max) { + if (mMax == max) return; + mMax = max; + if (mMax < mMin) { + setMin(mMax - 1); + } + updateKeyboardRange(); + + //We need to refresh the PopupIndicator view + updateIndicatorSizes(); + } + + public int getMax() { + return mMax; + } + + /** + * Sets the minimum value for this DiscreteSeekBar + * if the supplied argument is bigger than the Current MAX value, + * the MAX value will be set to MIN+1 + *

+ * Also if the current progress is out of the new range, it will be set to MIN + *

+ * + * @param min + * @see #setMax(int) + * @see #setProgress(int) + */ + public void setMin(int min) { + if (mMin == min) return; + mMin = min; + if (mMin > mMax) { + setMax(mMin + 1); + } + updateKeyboardRange(); + } + + public int getMin() { + return mMin; + } + + /** + * Sets the current progress for this DiscreteSeekBar + * The supplied argument will be capped to the current MIN-MAX range + * + * @param progress + * @see #setMax(int) + * @see #setMin(int) + */ + public void setProgress(int progress) { + setProgress(progress, false); + } + + private void setProgress(int value, boolean fromUser) { + value = Math.max(mMin, Math.min(mMax, value)); + if (isAnimationRunning()) { + mPositionAnimator.cancel(); + } + + mValue = value; + notifyProgress(value, fromUser); + updateProgressMessage(value); + updateThumbPosFromCurrentProgress(); + } + + /** + * Get the current progress + * + * @return the current progress :-P + */ + public int getProgress() { + return mValue; + } + + /** + * Sets a listener to receive notifications of changes to the DiscreteSeekBar's progress level. Also + * provides notifications of when the DiscreteSeekBar shows/hides the bubble indicator. + * + * @param listener The seek bar notification listener + * @see DiscreteSeekBar.OnProgressChangeListener + */ + public void setOnProgressChangeListener(@Nullable OnProgressChangeListener listener) { + mPublicChangeListener = listener; + } + + /** + * Sets the color of the seek thumb, as well as the color of the popup indicator. + * + * @param thumbColor The color the seek thumb will be changed to + * @param indicatorColor The color the popup indicator will be changed to + * The indicator will animate from thumbColor to indicatorColor + * when opening + */ + public void setThumbColor(int thumbColor, int indicatorColor) { + mThumb.setColorStateList(ColorStateList.valueOf(thumbColor)); + mIndicator.setColors(indicatorColor, thumbColor); + } + + /** + * Sets the color of the seek thumb, as well as the color of the popup indicator. + * + * @param thumbColorStateList The ColorStateList the seek thumb will be changed to + * @param indicatorColor The color the popup indicator will be changed to + * The indicator will animate from thumbColorStateList(pressed state) to indicatorColor + * when opening + */ + public void setThumbColor(@NonNull ColorStateList thumbColorStateList, int indicatorColor) { + mThumb.setColorStateList(thumbColorStateList); + //we use the "pressed" color to morph the indicator from it to its own color + int thumbColor = thumbColorStateList.getColorForState(new int[]{PRESSED_STATE}, thumbColorStateList.getDefaultColor()); + mIndicator.setColors(indicatorColor, thumbColor); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param color The color the track scrubber will be changed to + */ + public void setScrubberColor(int color) { + mScrubber.setColorStateList(ColorStateList.valueOf(color)); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param colorStateList The ColorStateList the track scrubber will be changed to + */ + public void setScrubberColor(@NonNull ColorStateList colorStateList) { + mScrubber.setColorStateList(colorStateList); + } + + /** + * Sets the color of the seekbar ripple + * + * @param color The color the track ripple will be changed to + */ + public void setRippleColor(int color) { + setRippleColor(new ColorStateList(new int[][]{new int[]{}}, new int[]{color})); + } + + /** + * Sets the color of the seekbar ripple + * + * @param colorStateList The ColorStateList the track ripple will be changed to + */ + public void setRippleColor(@NonNull ColorStateList colorStateList) { + SeekBarCompat.setRippleColor(mRipple, colorStateList); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param color The color the track will be changed to + */ + public void setTrackColor(int color) { + mTrack.setColorStateList(ColorStateList.valueOf(color)); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param colorStateList The ColorStateList the track will be changed to + */ + public void setTrackColor(@NonNull ColorStateList colorStateList) { + mTrack.setColorStateList(colorStateList); + } + + /** + * If {@code enabled} is false the indicator won't appear. By default popup indicator is + * enabled. + */ + public void setIndicatorPopupEnabled(boolean enabled) { + this.mIndicatorPopupEnabled = enabled; + } + + private void updateIndicatorSizes() { + if (!isInEditMode()) { + if (mNumericTransformer.useStringTransform()) { + mIndicator.updateSizes(mNumericTransformer.transformToString(mMax)); + } else { + mIndicator.updateSizes(convertValueToMessage(mNumericTransformer.transform(mMax))); + } + } + + } + + private void notifyProgress(int value, boolean fromUser) { + if (mPublicChangeListener != null) { + mPublicChangeListener.onProgressChanged(DiscreteSeekBar.this, value, fromUser); + } + onValueChanged(value); + } + + private void notifyBubble(boolean open) { + if (open) { + onShowBubble(); + } else { + onHideBubble(); + } + } + + /** + * When the {@link DiscreteSeekBar} enters pressed or focused state + * the bubble with the value will be shown, and this method called + *

+ * Subclasses may override this to add functionality around this getEventHandler + *

+ */ + protected void onShowBubble() { + } + + /** + * When the {@link DiscreteSeekBar} exits pressed or focused state + * the bubble with the value will be hidden, and this method called + *

+ * Subclasses may override this to add functionality around this getEventHandler + *

+ */ + protected void onHideBubble() { + } + + /** + * When the {@link DiscreteSeekBar} value changes this method is called + *

+ * Subclasses may override this to add functionality around this getEventHandler + * without having to specify a {@link DiscreteSeekBar.OnProgressChangeListener} + *

+ */ + protected void onValueChanged(int value) { + } + + private void updateKeyboardRange() { + int range = mMax - mMin; + if ((mKeyProgressIncrement == 0) || (range / mKeyProgressIncrement > 20)) { + // It will take the user too long to change this via keys, change it + // to something more reasonable + mKeyProgressIncrement = Math.max(1, Math.round((float) range / 20)); + } + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int height = mThumb.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom(); + height += (mAddedTouchBounds * 2); + setMeasuredDimension(widthSize, height); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (changed) { + removeCallbacks(mShowIndicatorRunnable); + if (!isInEditMode()) { + mIndicator.dismissComplete(); + } + updateFromDrawableState(); + } + } + + @Override + public void scheduleDrawable(Drawable who, Runnable what, long when) { + super.scheduleDrawable(who, what, when); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + int thumbWidth = mThumb.getIntrinsicWidth(); + int thumbHeight = mThumb.getIntrinsicHeight(); + int addedThumb = mAddedTouchBounds; + int halfThumb = thumbWidth / 2; + int paddingLeft = getPaddingLeft() + addedThumb; + int paddingRight = getPaddingRight(); + int bottom = getHeight() - getPaddingBottom() - addedThumb; + mThumb.setBounds(paddingLeft, bottom - thumbHeight, paddingLeft + thumbWidth, bottom); + int trackHeight = Math.max(mTrackHeight / 2, 1); + mTrack.setBounds(paddingLeft + halfThumb, bottom - halfThumb - trackHeight, + getWidth() - halfThumb - paddingRight - addedThumb, bottom - halfThumb + trackHeight); + int available = getWidth() - paddingRight - addedThumb - paddingLeft - thumbWidth; + float scaleDrawBase = (mValueBase - mMin) / (float) (mMax - mMin); + final int thumbPosBase = (int) (scaleDrawBase * available + 0.5f); + mTrackBase.setBounds(paddingLeft + halfThumb + thumbPosBase - mTrackBaseHeight / 8, bottom - halfThumb - mTrackBaseHeight / 2, + paddingLeft + halfThumb + thumbPosBase + mTrackBaseHeight / 8, bottom - halfThumb + mTrackBaseHeight / 2); + int scrubberHeight = Math.max(mScrubberHeight / 2, 2); + mScrubber.setBounds(paddingLeft + halfThumb, bottom - halfThumb - scrubberHeight, + paddingLeft + halfThumb, bottom - halfThumb + scrubberHeight); + + //Update the thumb position after size changed + updateThumbPosFromCurrentProgress(); + } + + @Override + protected synchronized void onDraw(Canvas canvas) { + if (!isLollipopOrGreater) { + mRipple.draw(canvas); + } + super.onDraw(canvas); + mTrack.draw(canvas); + mScrubber.draw(canvas); + if (mMin != mValueBase && mMax != mValueBase) { + mTrackBase.draw(canvas); + } + mThumb.draw(canvas); + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + updateFromDrawableState(); + } + + private void updateFromDrawableState() { + int[] state = getDrawableState(); + boolean focused = false; + boolean pressed = false; + for (int i : state) { + if (i == FOCUSED_STATE) { + focused = true; + } else if (i == PRESSED_STATE) { + pressed = true; + } + } + if (isEnabled() && (focused || pressed) && mIndicatorPopupEnabled) { + //We want to add a small delay here to avoid + //poping in/out on simple taps + removeCallbacks(mShowIndicatorRunnable); + postDelayed(mShowIndicatorRunnable, INDICATOR_DELAY_FOR_TAPS); + } else { + hideFloater(); + } + mThumb.setState(state); + mTrack.setState(state); + mScrubber.setState(state); + mRipple.setState(state); + } + + private void updateProgressMessage(int value) { + if (!isInEditMode()) { + if (mNumericTransformer.useStringTransform()) { + mIndicator.setValue(mNumericTransformer.transformToString(value)); + } else { + mIndicator.setValue(convertValueToMessage(mNumericTransformer.transform(value))); + } + } + } + + private String convertValueToMessage(int value) { + String format = mIndicatorFormatter != null ? mIndicatorFormatter : DEFAULT_FORMATTER; + //We're trying to re-use the Formatter here to avoid too much memory allocations + //But I'm not completey sure if it's doing anything good... :( + //Previously, this condition was wrong so the Formatter was always re-created + //But as I fixed the condition, the formatter started outputting trash characters from previous + //calls, so I mark the StringBuilder as empty before calling format again. + + //Anyways, I see the memory usage still go up on every call to this method + //and I have no clue on how to fix that... damn Strings... + if (mFormatter == null || !mFormatter.locale().equals(Locale.getDefault())) { + int bufferSize = format.length() + String.valueOf(mMax).length(); + if (mFormatBuilder == null) { + mFormatBuilder = new StringBuilder(bufferSize); + } else { + mFormatBuilder.ensureCapacity(bufferSize); + } + mFormatter = new Formatter(mFormatBuilder, Locale.getDefault()); + } else { + mFormatBuilder.setLength(0); + } + return mFormatter.format(format, value).toString(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; + } + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + mDownX = event.getX(); + startDragging(event, isInScrollingContainer()); + break; + case MotionEvent.ACTION_MOVE: + if (isDragging()) { + updateDragging(event); + } else { + final float x = event.getX(); + if (Math.abs(x - mDownX) > mTouchSlop) { + startDragging(event, false); + } + } + break; + case MotionEvent.ACTION_UP: + if (!isDragging() && mAllowTrackClick) { + startDragging(event, false); + updateDragging(event); + } + stopDragging(); + break; + case MotionEvent.ACTION_CANCEL: + stopDragging(); + break; + } + return true; + } + + private boolean isInScrollingContainer() { + return SeekBarCompat.isInScrollingContainer(getParent()); + } + + private boolean startDragging(MotionEvent ev, boolean ignoreTrackIfInScrollContainer) { + final Rect bounds = mTempRect; + mThumb.copyBounds(bounds); + //Grow the current thumb rect for a bigger touch area + bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); + mIsDragging = (bounds.contains((int) ev.getX(), (int) ev.getY())); + if (!mIsDragging && mAllowTrackClick && !ignoreTrackIfInScrollContainer) { + //If the user clicked outside the thumb, we compute the current position + //and force an immediate drag to it. + mIsDragging = true; + mDragOffset = (bounds.width() / 2) - mAddedTouchBounds; + updateDragging(ev); + //As the thumb may have moved, get the bounds again + mThumb.copyBounds(bounds); + bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); + } + if (mIsDragging) { + setPressed(true); + attemptClaimDrag(); + setHotspot(ev.getX(), ev.getY()); + mDragOffset = (int) (ev.getX() - bounds.left - mAddedTouchBounds); + if (mPublicChangeListener != null) { + mPublicChangeListener.onStartTrackingTouch(this); + } + } + return mIsDragging; + } + + private boolean isDragging() { + return mIsDragging; + } + + private void stopDragging() { + if (mPublicChangeListener != null) { + mPublicChangeListener.onStopTrackingTouch(this); + } + mIsDragging = false; + setPressed(false); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + boolean handled = false; + if (isEnabled()) { + int progress = getAnimatedProgress(); + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = true; + if (progress <= mMin) break; + animateSetProgress(progress - mKeyProgressIncrement); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = true; + if (progress >= mMax) break; + animateSetProgress(progress + mKeyProgressIncrement); + break; + } + } + + return handled || super.onKeyDown(keyCode, event); + } + + private int getAnimatedProgress() { + return isAnimationRunning() ? getAnimationTarget() : mValue; + } + + + boolean isAnimationRunning() { + return mPositionAnimator != null && mPositionAnimator.isRunning(); + } + + void animateSetProgress(int progress) { + final float curProgress = isAnimationRunning() ? getAnimationPosition() : getProgress(); + + if (progress < mMin) { + progress = mMin; + } else if (progress > mMax) { + progress = mMax; + } + //setProgressValueOnly(progress); + + if (mPositionAnimator != null) { + mPositionAnimator.cancel(); + } + + mAnimationTarget = progress; + mPositionAnimator = AnimatorCompat.create(curProgress, + progress, new AnimatorCompat.AnimationFrameUpdateListener() { + @Override + public void onAnimationFrame(float currentValue) { + setAnimationPosition(currentValue); + } + }); + mPositionAnimator.setDuration(PROGRESS_ANIMATION_DURATION); + mPositionAnimator.start(); + } + + private int getAnimationTarget() { + return mAnimationTarget; + } + + void setAnimationPosition(float position) { + mAnimationPosition = position; + float currentScale = (position - mMin) / (float) (mMax - mMin); + updateProgressFromAnimation(currentScale); + } + + float getAnimationPosition() { + return mAnimationPosition; + } + + + private void updateDragging(MotionEvent ev) { + setHotspot(ev.getX(), ev.getY()); + int x = (int) ev.getX(); + Rect oldBounds = mThumb.getBounds(); + int halfThumb = oldBounds.width() / 2; + int addedThumb = mAddedTouchBounds; + int newX = x - mDragOffset + halfThumb; + int left = getPaddingLeft() + halfThumb + addedThumb; + int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb); + if (newX < left) { + newX = left; + } else if (newX > right) { + newX = right; + } + + int available = right - left; + float scale = (float) (newX - left) / (float) available; + if (isRtl()) { + scale = 1f - scale; + } + int progress = Math.round((scale * (mMax - mMin)) + mMin); + setProgress(progress, true); + } + + private void updateProgressFromAnimation(float scale) { + Rect bounds = mThumb.getBounds(); + int halfThumb = bounds.width() / 2; + int addedThumb = mAddedTouchBounds; + int left = getPaddingLeft() + halfThumb + addedThumb; + int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb); + int available = right - left; + int progress = Math.round((scale * (mMax - mMin)) + mMin); + //we don't want to just call setProgress here to avoid the animation being cancelled, + //and this position is not bound to a real progress value but interpolated + if (progress != getProgress()) { + mValue = progress; + notifyProgress(mValue, true); + updateProgressMessage(progress); + } + final int thumbPos = (int) (scale * available + 0.5f); + + float scaleDrawBase = (mValueBase - mMin) / (float) (mMax - mMin); + final int thumbPosBase = (int) (scaleDrawBase * available + 0.5f); + + updateThumbPos(thumbPosBase, thumbPos); + } + + private void updateThumbPosFromCurrentProgress() { + int thumbWidth = mThumb.getIntrinsicWidth(); + int addedThumb = mAddedTouchBounds; + int halfThumb = thumbWidth / 2; + + //This doesn't matter if RTL, as we just need the "avaiable" area + int left = getPaddingLeft() + halfThumb + addedThumb; + int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb); + int available = right - left; + + float scaleDraw = (mValue - mMin) / (float) (mMax - mMin); + float scaleDrawBase = (mValueBase - mMin) / (float) (mMax - mMin); + + final int thumbPos = (int) (scaleDraw * available + 0.5f); + final int thumbPosBase = (int) (scaleDrawBase * available + 0.5f); + updateThumbPos(thumbPosBase, thumbPos); + } + + private void updateThumbPos(int base, int value) { + base += getPaddingLeft() + mAddedTouchBounds; + value += getPaddingLeft() + mAddedTouchBounds; + int start = Math.min(base, value); + int end = Math.max(base, value); + + int thumbWidth = mThumb.getIntrinsicWidth(); + int halfThumb = thumbWidth / 2; + mThumb.copyBounds(mInvalidateRect); + mThumb.setBounds(value, mInvalidateRect.top, value + thumbWidth, mInvalidateRect.bottom); + mScrubber.getBounds().left = start + halfThumb; + mScrubber.getBounds().right = end + halfThumb; + final Rect finalBounds = mTempRect; + mThumb.copyBounds(finalBounds); + if (!isInEditMode()) { + mIndicator.move(finalBounds.centerX()); + } + mTrackBase.getBounds().left = base + halfThumb - mTrackBaseHeight / 8; + mTrackBase.getBounds().right = base + halfThumb + mTrackBaseHeight / 8; + mInvalidateRect.inset(-mAddedTouchBounds, -mAddedTouchBounds); + finalBounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); + mInvalidateRect.union(finalBounds); + SeekBarCompat.setHotspotBounds(mRipple, finalBounds.left, finalBounds.top, finalBounds.right, finalBounds.bottom); + invalidate(mInvalidateRect); + } + + + private void setHotspot(float x, float y) { + DrawableCompat.setHotspot(mRipple, x, y); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mThumb || who == mTrack || who == mScrubber || who == mRipple || super.verifyDrawable(who); + } + + private void attemptClaimDrag() { + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } + + private Runnable mShowIndicatorRunnable = new Runnable() { + @Override + public void run() { + showFloater(); + } + }; + + private void showFloater() { + if (!isInEditMode()) { + mThumb.animateToPressed(); + mIndicator.showIndicator(this, mThumb.getBounds()); + notifyBubble(true); + } + } + + private void hideFloater() { + removeCallbacks(mShowIndicatorRunnable); + if (!isInEditMode()) { + mIndicator.dismiss(); + notifyBubble(false); + } + } + + private MarkerDrawable.MarkerAnimationListener mFloaterListener = new MarkerDrawable.MarkerAnimationListener() { + @Override + public void onClosingComplete() { + mThumb.animateToNormal(); + } + + @Override + public void onOpeningComplete() { + + } + + }; + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + removeCallbacks(mShowIndicatorRunnable); + if (!isInEditMode()) { + mIndicator.dismissComplete(); + } + } + + public boolean isRtl() { + return (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) && mMirrorForRtl; + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + CustomState state = new CustomState(superState); + state.progress = getProgress(); + state.max = mMax; + state.min = mMin; + return state; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state == null || !state.getClass().equals(CustomState.class)) { + super.onRestoreInstanceState(state); + return; + } + + CustomState customState = (CustomState) state; + setMin(customState.min); + setMax(customState.max); + setProgress(customState.progress, false); + super.onRestoreInstanceState(customState.getSuperState()); + } + + static class CustomState extends BaseSavedState { + private int progress; + private int max; + private int min; + + public CustomState(Parcel source) { + super(source); + progress = source.readInt(); + max = source.readInt(); + min = source.readInt(); + } + + public CustomState(Parcelable superState) { + super(superState); + } + + @Override + public void writeToParcel(Parcel outcoming, int flags) { + super.writeToParcel(outcoming, flags); + outcoming.writeInt(progress); + outcoming.writeInt(max); + outcoming.writeInt(min); + } + + public static final Creator CREATOR = + new Creator() { + + @Override + public CustomState[] newArray(int size) { + return new CustomState[size]; + } + + @Override + public CustomState createFromParcel(Parcel incoming) { + return new CustomState(incoming); + } + }; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/Marker.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/Marker.java new file mode 100644 index 0000000..776f8f9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/Marker.java @@ -0,0 +1,196 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.core.view.ViewCompat; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.compat.SeekBarCompat; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.MarkerDrawable; + + +/** + * {@link ViewGroup} to be used as the real indicator. + *

+ * I've used this to be able to accommodate the TextView + * and the {@link MarkerDrawable} + * with the required positions and offsets + *

+ * + * @hide + */ +public class Marker extends ViewGroup implements MarkerDrawable.MarkerAnimationListener { + private static final int PADDING_DP = 4; + private static final int ELEVATION_DP = 8; + //The TextView to show the info + private TextView mNumber; + //The max width of this View + private int mWidth; + //some distance between the thumb and our bubble marker. + //This will be added to our measured height + private int mSeparation; + MarkerDrawable mMarkerDrawable; + + public Marker(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) { + super(context, attrs, defStyleAttr); + //as we're reading the parent DiscreteSeekBar attributes, it may wrongly set this view's visibility. + setVisibility(View.VISIBLE); + + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DiscreteSeekBar, + R.attr.discreteSeekBarStyle, R.style.Widget_DiscreteSeekBar); + + int padding = (int) (PADDING_DP * displayMetrics.density) * 2; + int textAppearanceId = a.getResourceId(R.styleable.DiscreteSeekBar_dsb_indicatorTextAppearance, + R.style.Widget_DiscreteIndicatorTextAppearance); + mNumber = new TextView(context); + //Add some padding to this textView so the bubble has some space to breath + mNumber.setPadding(padding, 0, padding, 0); + mNumber.setTextAppearance(context, textAppearanceId); + mNumber.setGravity(Gravity.CENTER); + mNumber.setText(maxValue); + mNumber.setMaxLines(1); + mNumber.setSingleLine(true); + SeekBarCompat.setTextDirection(mNumber, TEXT_DIRECTION_LOCALE); + mNumber.setVisibility(View.INVISIBLE); + + //add some padding for the elevation shadow not to be clipped + //I'm sure there are better ways of doing this... + setPadding(padding, padding, padding, padding); + + resetSizes(maxValue); + + mSeparation = separation; + ColorStateList color = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_indicatorColor); + mMarkerDrawable = new MarkerDrawable(color, thumbSize); + mMarkerDrawable.setCallback(this); + mMarkerDrawable.setMarkerListener(this); + mMarkerDrawable.setExternalOffset(padding); + + //Elevation for anroid 5+ + float elevation = a.getDimension(R.styleable.DiscreteSeekBar_dsb_indicatorElevation, ELEVATION_DP * displayMetrics.density); + ViewCompat.setElevation(this, elevation); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + SeekBarCompat.setOutlineProvider(this, mMarkerDrawable); + } + a.recycle(); + } + + public void resetSizes(String maxValue) { + DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); + //Account for negative numbers... is there any proper way of getting the biggest string between our range???? + mNumber.setText("-" + maxValue); + //Do a first forced measure call for the TextView (with the biggest text content), + //to calculate the max width and use always the same. + //this avoids the TextView from shrinking and growing when the text content changes + int wSpec = MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, MeasureSpec.AT_MOST); + int hSpec = MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels, MeasureSpec.AT_MOST); + mNumber.measure(wSpec, hSpec); + mWidth = Math.max(mNumber.getMeasuredWidth(), mNumber.getMeasuredHeight()); + removeView(mNumber); + addView(mNumber, new FrameLayout.LayoutParams(mWidth, mWidth, Gravity.LEFT | Gravity.TOP)); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + mMarkerDrawable.draw(canvas); + super.dispatchDraw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureChildren(widthMeasureSpec, heightMeasureSpec); + int widthSize = mWidth + getPaddingLeft() + getPaddingRight(); + int heightSize = mWidth + getPaddingTop() + getPaddingBottom(); + //This diff is the basic calculation of the difference between + //a square side size and its diagonal + //this helps us account for the visual offset created by MarkerDrawable + //when leaving one of the corners un-rounded + int diff = (int) ((1.41f * mWidth) - mWidth) / 2; + setMeasuredDimension(widthSize, heightSize + diff + mSeparation); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int left = getPaddingLeft(); + int top = getPaddingTop(); + int right = getWidth() - getPaddingRight(); + int bottom = getHeight() - getPaddingBottom(); + //the TetView is always layout at the top + mNumber.layout(left, top, left + mWidth, top + mWidth); + //the MarkerDrawable uses the whole view, it will adapt itself... + // or it seems so... + mMarkerDrawable.setBounds(left, top, right, bottom); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mMarkerDrawable || super.verifyDrawable(who); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + //HACK: Sometimes, the animateOpen() call is made before the View is attached + //so the drawable cannot schedule itself to run the animation + //I think we can call it here safely. + //I've seen it happen in android 2.3.7 + animateOpen(); + } + + public void setValue(CharSequence value) { + mNumber.setText(value); + } + + public CharSequence getValue() { + return mNumber.getText(); + } + + public void animateOpen() { + mMarkerDrawable.stop(); + mMarkerDrawable.animateToPressed(); + } + + public void animateClose() { + mMarkerDrawable.stop(); + mNumber.setVisibility(View.INVISIBLE); + mMarkerDrawable.animateToNormal(); + } + + @Override + public void onOpeningComplete() { + mNumber.setVisibility(View.VISIBLE); + if (getParent() instanceof MarkerDrawable.MarkerAnimationListener) { + ((MarkerDrawable.MarkerAnimationListener) getParent()).onOpeningComplete(); + } + } + + @Override + public void onClosingComplete() { + if (getParent() instanceof MarkerDrawable.MarkerAnimationListener) { + ((MarkerDrawable.MarkerAnimationListener) getParent()).onClosingComplete(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mMarkerDrawable.stop(); + } + + public void setColors(int startColor, int endColor) { + mMarkerDrawable.setColors(startColor, endColor); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/PopupIndicator.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/PopupIndicator.java new file mode 100644 index 0000000..13a27b7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/PopupIndicator.java @@ -0,0 +1,255 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.IBinder; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import androidx.core.view.GravityCompat; + +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.compat.SeekBarCompat; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.MarkerDrawable; + + +/** + * Class to manage the floating bubble thing, similar (but quite worse tested than {@link android.widget.PopupWindow} + *

+ *

+ * This will attach a View to the Window (full-width, measured-height, positioned just under the thumb) + *

+ * + * @hide + * @see #showIndicator(View, Rect) + * @see #dismiss() + * @see #dismissComplete() + * @see PopupIndicator.Floater + */ +public class PopupIndicator { + + private final WindowManager mWindowManager; + private boolean mShowing; + private Floater mPopupView; + //Outside listener for the DiscreteSeekBar to get MarkerDrawable animation events. + //The whole chain of events goes this way: + //MarkerDrawable->Marker->Floater->mListener->DiscreteSeekBar.... + //... phew! + private MarkerDrawable.MarkerAnimationListener mListener; + private int[] mDrawingLocation = new int[2]; + Point screenSize = new Point(); + + public PopupIndicator(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) { + mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + mPopupView = new Floater(context, attrs, defStyleAttr, maxValue, thumbSize, separation); + } + + public void updateSizes(String maxValue) { + dismissComplete(); + if (mPopupView != null) { + mPopupView.mMarker.resetSizes(maxValue); + } + } + + public void setListener(MarkerDrawable.MarkerAnimationListener listener) { + mListener = listener; + } + + /** + * We want the Floater to be full-width because the contents will be moved from side to side. + * We may/should change this in the future to use just the PARENT View width and/or pass it in the constructor + */ + private void measureFloater() { + int specWidth = View.MeasureSpec.makeMeasureSpec(screenSize.x, View.MeasureSpec.EXACTLY); + int specHeight = View.MeasureSpec.makeMeasureSpec(screenSize.y, View.MeasureSpec.AT_MOST); + mPopupView.measure(specWidth, specHeight); + } + + public void setValue(CharSequence value) { + mPopupView.mMarker.setValue(value); + } + + public boolean isShowing() { + return mShowing; + } + + public void showIndicator(View parent, Rect touchBounds) { + if (isShowing()) { + mPopupView.mMarker.animateOpen(); + return; + } + + IBinder windowToken = parent.getWindowToken(); + if (windowToken != null) { + WindowManager.LayoutParams p = createPopupLayout(windowToken); + + p.gravity = Gravity.TOP | GravityCompat.START; + updateLayoutParamsForPosiion(parent, p, touchBounds.bottom); + mShowing = true; + + translateViewIntoPosition(touchBounds.centerX()); + invokePopup(p); + } + } + + public void move(int x) { + if (!isShowing()) { + return; + } + translateViewIntoPosition(x); + } + + public void setColors(int startColor, int endColor) { + mPopupView.setColors(startColor, endColor); + } + + /** + * This will start the closing animation of the Marker and call onClosingComplete when finished + */ + public void dismiss() { + mPopupView.mMarker.animateClose(); + } + + /** + * FORCE the popup window to be removed. + * You typically calls this when the parent view is being removed from the window to avoid a Window Leak + */ + public void dismissComplete() { + if (isShowing()) { + mShowing = false; + try { + mWindowManager.removeViewImmediate(mPopupView); + } finally { + } + } + } + + private void updateLayoutParamsForPosiion(View anchor, WindowManager.LayoutParams p, int yOffset) { + DisplayMetrics displayMetrics = anchor.getResources().getDisplayMetrics(); + screenSize.set(displayMetrics.widthPixels, displayMetrics.heightPixels); + + measureFloater(); + int measuredHeight = mPopupView.getMeasuredHeight(); + int paddingBottom = mPopupView.mMarker.getPaddingBottom(); + anchor.getLocationInWindow(mDrawingLocation); + p.x = 0; + p.y = mDrawingLocation[1] - measuredHeight + yOffset + paddingBottom; + p.width = screenSize.x; + p.height = measuredHeight; + } + + private void translateViewIntoPosition(final int x) { + mPopupView.setFloatOffset(x + mDrawingLocation[0]); + } + + private void invokePopup(WindowManager.LayoutParams p) { + mWindowManager.addView(mPopupView, p); + mPopupView.mMarker.animateOpen(); + } + + private WindowManager.LayoutParams createPopupLayout(IBinder token) { + WindowManager.LayoutParams p = new WindowManager.LayoutParams(); + p.gravity = Gravity.START | Gravity.TOP; + p.width = ViewGroup.LayoutParams.MATCH_PARENT; + p.height = ViewGroup.LayoutParams.MATCH_PARENT; + p.format = PixelFormat.TRANSLUCENT; + p.flags = computeFlags(p.flags); + p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; + p.token = token; + p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN; + p.setTitle("DiscreteSeekBar Indicator:" + Integer.toHexString(hashCode())); + + return p; + } + + /** + * I'm NOT completely sure how all this bitwise things work... + * + * @param curFlags + * @return + */ + private int computeFlags(int curFlags) { + curFlags &= ~( + WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES | + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | + WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | + WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES; + curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; + return curFlags; + } + + /** + * Small FrameLayout class to hold and move the bubble around when requested + * I wanted to use the {@link Marker} directly + * but doing so would make some things harder to implement + * (like moving the marker around, having the Marker's outline to work, etc) + */ + private class Floater extends FrameLayout implements MarkerDrawable.MarkerAnimationListener { + private Marker mMarker; + private int mOffset; + + public Floater(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) { + super(context); + mMarker = new Marker(context, attrs, defStyleAttr, maxValue, thumbSize, separation); + addView(mMarker, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureChildren(widthMeasureSpec, heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSie = mMarker.getMeasuredHeight(); + setMeasuredDimension(widthSize, heightSie); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int centerDiffX = mMarker.getMeasuredWidth() / 2; + int offset = (mOffset - centerDiffX); + mMarker.layout(offset, 0, offset + mMarker.getMeasuredWidth(), mMarker.getMeasuredHeight()); + } + + public void setFloatOffset(int x) { + mOffset = x; + int centerDiffX = mMarker.getMeasuredWidth() / 2; + int offset = (x - centerDiffX); + mMarker.offsetLeftAndRight(offset - mMarker.getLeft()); + //Without hardware acceleration (or API levels<11), offsetting a view seems to NOT invalidate the proper area. + //We should calc the proper invalidate Rect but this will be for now... + if (!SeekBarCompat.isHardwareAccelerated(this)) { + invalidate(); + } + } + + @Override + public void onClosingComplete() { + if (mListener != null) { + mListener.onClosingComplete(); + } + dismissComplete(); + } + + @Override + public void onOpeningComplete() { + if (mListener != null) { + mListener.onOpeningComplete(); + } + } + + public void setColors(int startColor, int endColor) { + mMarker.setColors(startColor, endColor); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/AnimatorCompat.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/AnimatorCompat.java new file mode 100644 index 0000000..77119dd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/AnimatorCompat.java @@ -0,0 +1,73 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.compat; + + +import com.fengliyan.tianlesue.agora.ui.seekbar.DiscreteSeekBar; + +/** + * Currently, there's no {@link android.animation.ValueAnimator} compatibility version + * and as we didn't want to throw in external dependencies, we made this small class. + *

+ *

+ * This will work like {@link androidx.core.view.ViewPropertyAnimatorCompat}, that is, + * not doing anything on API<11 and using the default {@link android.animation.ValueAnimator} + * on API>=11 + *

+ *

+ * This class is used to provide animation to the {@link DiscreteSeekBar} + * when navigating with the Keypad + *

+ * + * @hide + */ +public abstract class AnimatorCompat { + public interface AnimationFrameUpdateListener { + public void onAnimationFrame(float currentValue); + } + + AnimatorCompat() { + + } + + public abstract void cancel(); + + public abstract boolean isRunning(); + + public abstract void setDuration(int progressAnimationDuration); + + public abstract void start(); + + public static AnimatorCompat create(float start, float end, AnimationFrameUpdateListener listener) { + return new AnimatorCompatBase(start, end, listener); + } + + private static class AnimatorCompatBase extends AnimatorCompat { + + private final AnimationFrameUpdateListener mListener; + private final float mEndValue; + + public AnimatorCompatBase(float start, float end, AnimationFrameUpdateListener listener) { + mListener = listener; + mEndValue = end; + } + + @Override + public void cancel() { + + } + + @Override + public boolean isRunning() { + return false; + } + + @Override + public void setDuration(int progressAnimationDuration) { + + } + + @Override + public void start() { + mListener.onAnimationFrame(mEndValue); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/SeekBarCompat.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/SeekBarCompat.java new file mode 100644 index 0000000..17b9486 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/SeekBarCompat.java @@ -0,0 +1,129 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.compat; + +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.os.Build; +import android.view.View; +import android.view.ViewParent; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.DrawableCompat; + +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.AlmostRippleDrawable; +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.MarkerDrawable; + + +/** + * Wrapper compatibility class to call some API-Specific methods + * And offer alternate procedures when possible + * + * @hide + */ +public class SeekBarCompat { + + /** + * Sets the custom Outline provider on API>=21. + * Does nothing on API<21 + * + * @param view + * @param markerDrawable + */ + public static void setOutlineProvider(View view, final MarkerDrawable markerDrawable) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + SeekBarCompatDontCrash.setOutlineProvider(view, markerDrawable); + } + } + + /** + * Our DiscreteSeekBar implementation uses a circular drawable on API < 21 + * because we don't set it as Background, but draw it ourselves + * + * @param colorStateList + * @return + */ + public static Drawable getRipple(ColorStateList colorStateList) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + return SeekBarCompatDontCrash.getRipple(colorStateList); + } else { + return new AlmostRippleDrawable(colorStateList); + } + } + + /** + * Sets the color of the seekbar ripple + * @param drawable + * @param colorStateList The ColorStateList the track ripple will be changed to + */ + public static void setRippleColor(@NonNull Drawable drawable, ColorStateList colorStateList) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ((RippleDrawable) drawable).setColor(colorStateList); + } else { + ((AlmostRippleDrawable) drawable).setColor(colorStateList); + } + } + + /** + * As our DiscreteSeekBar implementation uses a circular drawable on API < 21 + * we want to use the same method to set its bounds as the Ripple's hotspot bounds. + * + * @param drawable + * @param left + * @param top + * @param right + * @param bottom + */ + public static void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + //We don't want the full size rect, Lollipop ripple would be too big + int size = (right - left) / 8; + DrawableCompat.setHotspotBounds(drawable, left + size, top + size, right - size, bottom - size); + } else { + drawable.setBounds(left, top, right, bottom); + } + } + + /** + * android.support.v4.view.ViewCompat SHOULD include this once and for all!! + * But it doesn't... + * + * @param view + * @param background + */ + @SuppressWarnings("deprecation") + public static void setBackground(View view, Drawable background) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + SeekBarCompatDontCrash.setBackground(view, background); + } else { + view.setBackgroundDrawable(background); + } + } + + /** + * Sets the TextView text direction attribute when possible + * + * @param textView + * @param textDirection + * @see TextView#setTextDirection(int) + */ + public static void setTextDirection(TextView textView, int textDirection) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + SeekBarCompatDontCrash.setTextDirection(textView, textDirection); + } + } + + public static boolean isInScrollingContainer(ViewParent p) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return SeekBarCompatDontCrash.isInScrollingContainer(p); + } + return false; + } + + public static boolean isHardwareAccelerated(View view) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + return SeekBarCompatDontCrash.isHardwareAccelerated(view); + } + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/SeekBarCompatDontCrash.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/SeekBarCompatDontCrash.java new file mode 100644 index 0000000..0413bb9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/compat/SeekBarCompatDontCrash.java @@ -0,0 +1,59 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.compat; + +import android.annotation.TargetApi; +import android.content.res.ColorStateList; +import android.graphics.Outline; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.view.ViewParent; +import android.widget.TextView; + +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable.MarkerDrawable; + + +/** + * Wrapper compatibility class to call some API-Specific methods + * And offer alternate procedures when possible + * + * @hide + */ +@TargetApi(21) +class SeekBarCompatDontCrash { + public static void setOutlineProvider(View marker, final MarkerDrawable markerDrawable) { + marker.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setConvexPath(markerDrawable.getPath()); + } + }); + } + + public static Drawable getRipple(ColorStateList colorStateList) { + return new RippleDrawable(colorStateList, null, null); + } + + public static void setBackground(View view, Drawable background) { + view.setBackground(background); + } + + public static void setTextDirection(TextView number, int textDirection) { + number.setTextDirection(textDirection); + } + + public static boolean isInScrollingContainer(ViewParent p) { + while (p != null && p instanceof ViewGroup) { + if (((ViewGroup) p).shouldDelayChildPressedState()) { + return true; + } + p = p.getParent(); + } + return false; + } + + public static boolean isHardwareAccelerated(View view) { + return view.isHardwareAccelerated(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/AlmostRippleDrawable.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/AlmostRippleDrawable.java new file mode 100644 index 0000000..1b2d454 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/AlmostRippleDrawable.java @@ -0,0 +1,205 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Animatable; +import android.os.SystemClock; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +import androidx.annotation.NonNull; + +public class AlmostRippleDrawable extends StateDrawable implements Animatable { + private static final long FRAME_DURATION = 1000 / 60; + private static final int ANIMATION_DURATION = 250; + + private static final float INACTIVE_SCALE = 0f; + private static final float ACTIVE_SCALE = 1f; + private float mCurrentScale = INACTIVE_SCALE; + private Interpolator mInterpolator; + private long mStartTime; + private boolean mReverse = false; + private boolean mRunning = false; + private int mDuration = ANIMATION_DURATION; + private float mAnimationInitialValue; + //We don't use colors just with our drawable state because of animations + private int mPressedColor; + private int mFocusedColor; + private int mDisabledColor; + private int mRippleColor; + private int mRippleBgColor; + + public AlmostRippleDrawable(@NonNull ColorStateList tintStateList) { + super(tintStateList); + mInterpolator = new AccelerateDecelerateInterpolator(); + setColor(tintStateList); + } + + public void setColor(@NonNull ColorStateList tintStateList) { + int defaultColor = tintStateList.getDefaultColor(); + mFocusedColor = tintStateList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, defaultColor); + mPressedColor = tintStateList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, defaultColor); + mDisabledColor = tintStateList.getColorForState(new int[]{-android.R.attr.state_enabled}, defaultColor); + + //The ripple should be partially transparent + mFocusedColor = getModulatedAlphaColor(130, mFocusedColor); + mPressedColor = getModulatedAlphaColor(130, mPressedColor); + mDisabledColor = getModulatedAlphaColor(130, mDisabledColor); + } + + private static int getModulatedAlphaColor(int alphaValue, int originalColor) { + int alpha = Color.alpha(originalColor); + int scale = alphaValue + (alphaValue >> 7); + alpha = alpha * scale >> 8; + return Color.argb(alpha, Color.red(originalColor), Color.green(originalColor), Color.blue(originalColor)); + } + + @Override + public void doDraw(Canvas canvas, Paint paint) { + Rect bounds = getBounds(); + int size = Math.min(bounds.width(), bounds.height()); + float scale = mCurrentScale; + int rippleColor = mRippleColor; + int bgColor = mRippleBgColor; + float radius = (size / 2); + float radiusAnimated = radius * scale; + if (scale > INACTIVE_SCALE) { + if (bgColor != 0) { + paint.setColor(bgColor); + paint.setAlpha(decreasedAlpha(Color.alpha(bgColor))); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), radius, paint); + } + if (rippleColor != 0) { + paint.setColor(rippleColor); + paint.setAlpha(modulateAlpha(Color.alpha(rippleColor))); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), radiusAnimated, paint); + } + } + } + + private int decreasedAlpha(int alpha) { + int scale = 100 + (100 >> 7); + return alpha * scale >> 8; + } + + @Override + public boolean setState(int[] stateSet) { + int[] oldState = getState(); + boolean oldPressed = false; + for (int i : oldState) { + if (i == android.R.attr.state_pressed) { + oldPressed = true; + } + } + super.setState(stateSet); + boolean focused = false; + boolean pressed = false; + boolean disabled = true; + for (int i : stateSet) { + if (i == android.R.attr.state_focused) { + focused = true; + } else if (i == android.R.attr.state_pressed) { + pressed = true; + } else if (i == android.R.attr.state_enabled) { + disabled = false; + } + } + + if (disabled) { + unscheduleSelf(mUpdater); + mRippleColor = mDisabledColor; + mRippleBgColor = 0; + mCurrentScale = ACTIVE_SCALE / 2; + invalidateSelf(); + } else { + if (pressed) { + animateToPressed(); + mRippleColor = mRippleBgColor = mPressedColor; + } else if (oldPressed) { + mRippleColor = mRippleBgColor = mPressedColor; + animateToNormal(); + } else if (focused) { + mRippleColor = mFocusedColor; + mRippleBgColor = 0; + mCurrentScale = ACTIVE_SCALE; + invalidateSelf(); + } else { + mRippleColor = 0; + mRippleBgColor = 0; + mCurrentScale = INACTIVE_SCALE; + invalidateSelf(); + } + } + return true; + } + + public void animateToPressed() { + unscheduleSelf(mUpdater); + if (mCurrentScale < ACTIVE_SCALE) { + mReverse = false; + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - ((mAnimationInitialValue - INACTIVE_SCALE) / (ACTIVE_SCALE - INACTIVE_SCALE)); + mDuration = (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } + } + + public void animateToNormal() { + unscheduleSelf(mUpdater); + if (mCurrentScale > INACTIVE_SCALE) { + mReverse = true; + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - ((mAnimationInitialValue - ACTIVE_SCALE) / (INACTIVE_SCALE - ACTIVE_SCALE)); + mDuration = (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } + } + + private void updateAnimation(float factor) { + float initial = mAnimationInitialValue; + float destination = mReverse ? INACTIVE_SCALE : ACTIVE_SCALE; + mCurrentScale = initial + (destination - initial) * factor; + invalidateSelf(); + } + + private final Runnable mUpdater = new Runnable() { + + @Override + public void run() { + + long currentTime = SystemClock.uptimeMillis(); + long diff = currentTime - mStartTime; + if (diff < mDuration) { + float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration); + scheduleSelf(mUpdater, currentTime + FRAME_DURATION); + updateAnimation(interpolation); + } else { + unscheduleSelf(mUpdater); + mRunning = false; + updateAnimation(1f); + } + } + }; + + @Override + public void start() { + //No-Op. We control our own animation + } + + @Override + public void stop() { + //No-Op. We control our own animation + } + + @Override + public boolean isRunning() { + return mRunning; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/MarkerDrawable.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/MarkerDrawable.java new file mode 100644 index 0000000..b1ecfe8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/MarkerDrawable.java @@ -0,0 +1,234 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Animatable; +import android.os.SystemClock; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +import androidx.annotation.NonNull; + +/** + * Implementation of {@link StateDrawable} to draw a morphing marker symbol. + *

+ * It's basically an implementation of an {@link Animatable} Drawable with the following details: + *

+ *
    + *
  • Animates from a circle shape to a "marker" shape just using a RoundRect
  • + *
  • Animates color change from the normal state color to the pressed state color
  • + *
  • Uses a {@link Path} to also serve as Outline for API>=21
  • + *
+ * + * @hide + */ +public class MarkerDrawable extends StateDrawable implements Animatable { + private static final long FRAME_DURATION = 1000 / 60; + private static final int ANIMATION_DURATION = 250; + + private float mCurrentScale = 0f; + private Interpolator mInterpolator; + private long mStartTime; + private boolean mReverse = false; + private boolean mRunning = false; + private int mDuration = ANIMATION_DURATION; + //size of the actual thumb drawable to use as circle state size + private float mClosedStateSize; + //value to store que current scale when starting an animation and interpolate from it + private float mAnimationInitialValue; + //extra offset directed from the View to account + //for its internal padding between circle state and marker state + private int mExternalOffset; + //colors for interpolation + private int mStartColor;//Color when the Marker is OPEN + private int mEndColor;//Color when the arker is CLOSED + + Path mPath = new Path(); + RectF mRect = new RectF(); + Matrix mMatrix = new Matrix(); + private MarkerAnimationListener mMarkerListener; + + public MarkerDrawable(@NonNull ColorStateList tintList, int closedSize) { + super(tintList); + mInterpolator = new AccelerateDecelerateInterpolator(); + mClosedStateSize = closedSize; + mStartColor = tintList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, tintList.getDefaultColor()); + mEndColor = tintList.getDefaultColor(); + + } + + public void setExternalOffset(int offset) { + mExternalOffset = offset; + } + + /** + * The two colors that will be used for the seek thumb. + * + * @param startColor Color used for the seek thumb + * @param endColor Color used for popup indicator + */ + public void setColors(int startColor, int endColor) { + mStartColor = startColor; + mEndColor = endColor; + } + + @Override + void doDraw(Canvas canvas, Paint paint) { + if (!mPath.isEmpty()) { + paint.setStyle(Paint.Style.FILL); + int color = blendColors(mStartColor, mEndColor, mCurrentScale); + paint.setColor(color); + canvas.drawPath(mPath, paint); + } + } + + public Path getPath() { + return mPath; + } + + @Override + protected void onBoundsChange(Rect bounds) { + super.onBoundsChange(bounds); + computePath(bounds); + } + + private void computePath(Rect bounds) { + final float currentScale = mCurrentScale; + final Path path = mPath; + final RectF rect = mRect; + final Matrix matrix = mMatrix; + + path.reset(); + int totalSize = Math.min(bounds.width(), bounds.height()); + + float initial = mClosedStateSize; + float destination = totalSize; + float currentSize = initial + (destination - initial) * currentScale; + + float halfSize = currentSize / 2f; + float inverseScale = 1f - currentScale; + float cornerSize = halfSize * inverseScale; + float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize}; + rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize); + path.addRoundRect(rect, corners, Path.Direction.CCW); + matrix.reset(); + matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize); + matrix.postTranslate((bounds.width() - currentSize) / 2, 0); + float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale; + matrix.postTranslate(0, hDiff); + path.transform(matrix); + } + + private void updateAnimation(float factor) { + float initial = mAnimationInitialValue; + float destination = mReverse ? 0f : 1f; + mCurrentScale = initial + (destination - initial) * factor; + computePath(getBounds()); + invalidateSelf(); + } + + public void animateToPressed() { + unscheduleSelf(mUpdater); + mReverse = false; + if (mCurrentScale < 1) { + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - mCurrentScale; + mDuration = (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } else { + notifyFinishedToListener(); + } + } + + public void animateToNormal() { + mReverse = true; + unscheduleSelf(mUpdater); + if (mCurrentScale > 0) { + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - mCurrentScale; + mDuration = ANIMATION_DURATION - (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } else { + notifyFinishedToListener(); + } + } + + private final Runnable mUpdater = new Runnable() { + + @Override + public void run() { + + long currentTime = SystemClock.uptimeMillis(); + long diff = currentTime - mStartTime; + if (diff < mDuration) { + float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration); + scheduleSelf(mUpdater, currentTime + FRAME_DURATION); + updateAnimation(interpolation); + } else { + unscheduleSelf(mUpdater); + mRunning = false; + updateAnimation(1f); + notifyFinishedToListener(); + } + } + }; + + public void setMarkerListener(MarkerAnimationListener listener) { + mMarkerListener = listener; + } + + private void notifyFinishedToListener() { + if (mMarkerListener != null) { + if (mReverse) { + mMarkerListener.onClosingComplete(); + } else { + mMarkerListener.onOpeningComplete(); + } + } + } + + @Override + public void start() { + //No-Op. We control our own animation + } + + @Override + public void stop() { + unscheduleSelf(mUpdater); + } + + @Override + public boolean isRunning() { + return mRunning; + } + + private static int blendColors(int color1, int color2, float factor) { + final float inverseFactor = 1f - factor; + float a = (Color.alpha(color1) * factor) + (Color.alpha(color2) * inverseFactor); + float r = (Color.red(color1) * factor) + (Color.red(color2) * inverseFactor); + float g = (Color.green(color1) * factor) + (Color.green(color2) * inverseFactor); + float b = (Color.blue(color1) * factor) + (Color.blue(color2) * inverseFactor); + return Color.argb((int) a, (int) r, (int) g, (int) b); + } + + + /** + * A listener interface to porpagate animation events + * This is the "poor's man" AnimatorListener for this Drawable + */ + public interface MarkerAnimationListener { + public void onClosingComplete(); + + public void onOpeningComplete(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/StateDrawable.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/StateDrawable.java new file mode 100644 index 0000000..2b021dd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/StateDrawable.java @@ -0,0 +1,103 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; +import androidx.annotation.NonNull; + +/** + * A drawable that changes it's Paint color depending on the Drawable State + *

+ * Subclasses should implement {@link #doDraw(Canvas, Paint)} + *

+ * + * @hide + */ +public abstract class StateDrawable extends Drawable { + private ColorStateList mTintStateList; + private final Paint mPaint; + private int mCurrentColor; + private int mAlpha = 255; + + public StateDrawable(@NonNull ColorStateList tintStateList) { + super(); + setColorStateList(tintStateList); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + + @Override + public boolean isStateful() { + return (mTintStateList.isStateful()) || super.isStateful(); + } + + @Override + public boolean setState(int[] stateSet) { + boolean handled = super.setState(stateSet); + handled = updateTint(stateSet) || handled; + return handled; + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + private boolean updateTint(int[] state) { + final int color = mTintStateList.getColorForState(state, mCurrentColor); + if (color != mCurrentColor) { + mCurrentColor = color; + //We've changed states + invalidateSelf(); + return true; + } + return false; + } + + @Override + public void draw(Canvas canvas) { + mPaint.setColor(mCurrentColor); + int alpha = modulateAlpha(Color.alpha(mCurrentColor)); + mPaint.setAlpha(alpha); + doDraw(canvas, mPaint); + } + + public void setColorStateList(@NonNull ColorStateList tintStateList) { + mTintStateList = tintStateList; + mCurrentColor = tintStateList.getDefaultColor(); + } + + /** + * Subclasses should implement this method to do the actual drawing + * + * @param canvas The current {@link Canvas} to draw into + * @param paint The {@link Paint} preconfigurred with the current + * {@link ColorStateList} color + */ + abstract void doDraw(Canvas canvas, Paint paint); + + @Override + public void setAlpha(int alpha) { + mAlpha = alpha; + invalidateSelf(); + } + + int modulateAlpha(int alpha) { + int scale = mAlpha + (mAlpha >> 7); + return alpha * scale >> 8; + } + + @Override + public int getAlpha() { + return mAlpha; + } + + @Override + public void setColorFilter(ColorFilter cf) { + mPaint.setColorFilter(cf); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/ThumbDrawable.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/ThumbDrawable.java new file mode 100644 index 0000000..648c9c1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/ThumbDrawable.java @@ -0,0 +1,95 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Animatable; +import android.os.SystemClock; +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.agora.ui.seekbar.internal.Marker; + + +/** + *

HACK

+ *

+ * Special {@link StateDrawable} implementation + * to draw the Thumb circle. + *

+ *

+ * It's special because it will stop drawing once the state is pressed/focused BUT only after a small delay. + *

+ *

+ * This special delay is meant to help avoiding frame glitches while the {@link Marker} is added to the Window + *

+ * + * @hide + */ +public class ThumbDrawable extends StateDrawable implements Animatable { + //The current size for this drawable. Must be converted to real DPs + public static final int DEFAULT_SIZE_DP = 12; + private final int mSize; + private boolean mOpen; + private boolean mRunning; + + public ThumbDrawable(@NonNull ColorStateList tintStateList, int size) { + super(tintStateList); + mSize = size; + } + + @Override + public int getIntrinsicWidth() { + return mSize; + } + + @Override + public int getIntrinsicHeight() { + return mSize; + } + + @Override + public void doDraw(Canvas canvas, Paint paint) { + if (!mOpen) { + Rect bounds = getBounds(); + float radius = (mSize / 2); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), radius, paint); + } + } + + public void animateToPressed() { + scheduleSelf(opener, SystemClock.uptimeMillis() + 100); + mRunning = true; + } + + public void animateToNormal() { + mOpen = false; + mRunning = false; + unscheduleSelf(opener); + invalidateSelf(); + } + + private Runnable opener = new Runnable() { + @Override + public void run() { + mOpen = true; + invalidateSelf(); + mRunning = false; + } + }; + + @Override + public void start() { + //NOOP + } + + @Override + public void stop() { + animateToNormal(); + } + + @Override + public boolean isRunning() { + return mRunning; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/TrackOvalDrawable.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/TrackOvalDrawable.java new file mode 100644 index 0000000..af15af9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/TrackOvalDrawable.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import androidx.annotation.NonNull; + +/** + * Simple {@link StateDrawable} implementation + * to draw circles/ovals + * + * @hide + */ +public class TrackOvalDrawable extends StateDrawable { + private RectF mRectF = new RectF(); + + public TrackOvalDrawable(@NonNull ColorStateList tintStateList) { + super(tintStateList); + } + + @Override + void doDraw(Canvas canvas, Paint paint) { + mRectF.set(getBounds()); + canvas.drawOval(mRectF, paint); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/TrackRectDrawable.java b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/TrackRectDrawable.java new file mode 100644 index 0000000..09171bd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/ui/seekbar/internal/drawable/TrackRectDrawable.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.agora.ui.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Paint; +import androidx.annotation.NonNull; + +/** + * Simple {@link StateDrawable} implementation + * to draw rectangles + * + * @hide + */ +public class TrackRectDrawable extends StateDrawable { + public TrackRectDrawable(@NonNull ColorStateList tintStateList) { + super(tintStateList); + } + + @Override + void doDraw(Canvas canvas, Paint paint) { + canvas.drawRect(getBounds(), paint); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/utils/CameraUtils.java b/app/src/main/java/com/fengliyan/tianlesue/agora/utils/CameraUtils.java new file mode 100644 index 0000000..7bdbdf3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/utils/CameraUtils.java @@ -0,0 +1,135 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.fengliyan.tianlesue.agora.utils; + +import android.app.Activity; +import android.hardware.Camera; +import android.util.Log; +import android.view.Surface; + +import java.util.List; + +/** + * Camera-related utility functions. + */ +public class CameraUtils { + private static final String TAG = CameraUtils.class.getSimpleName(); + private static final boolean DEBUG = false; + + public static int getCameraOrientation(int cameraId) { + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(cameraId, info); + return info.orientation; + } + + public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) { + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(cameraId, info); + int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); + int degrees = 0; + switch (rotation) { + case Surface.ROTATION_0: + degrees = 0; + break; + case Surface.ROTATION_90: + degrees = 90; + break; + case Surface.ROTATION_180: + degrees = 180; + break; + case Surface.ROTATION_270: + degrees = 270; + break; + } + + int result; + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + result = (info.orientation + degrees) % 360; + result = (360 - result) % 360; // compensate the mirror + } else { // back-facing + result = (info.orientation - degrees + 360) % 360; + } + camera.setDisplayOrientation(result); + } + + /** + * 设置对焦,会影响camera吞吐速率 + */ + public static void setFocusModes(Camera.Parameters parameters) { + List focusModes = parameters.getSupportedFocusModes(); + if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + + /** + * 设置fps + */ + public static void chooseFramerate(Camera.Parameters parameters, float frameRate) { + int framerate = (int) (frameRate * 1000); + List rates = parameters.getSupportedPreviewFpsRange(); + int[] bestFramerate = rates.get(0); + for (int i = 0; i < rates.size(); i++) { + int[] rate = rates.get(i); + if (DEBUG) + Log.e(TAG, "supported preview pfs min " + rate[0] + " max " + rate[1]); + int curDelta = Math.abs(rate[1] - framerate); + int bestDelta = Math.abs(bestFramerate[1] - framerate); + if (curDelta < bestDelta) { + bestFramerate = rate; + } else if (curDelta == bestDelta) { + bestFramerate = bestFramerate[0] < rate[0] ? rate : bestFramerate; + } + } + if (DEBUG) + Log.e(TAG, "closet framerate min " + bestFramerate[0] + " max " + bestFramerate[1]); + parameters.setPreviewFpsRange(bestFramerate[0], bestFramerate[1]); + } + + /** + * Attempts to find a preview size that matches the provided width and height (which + * specify the dimensions of the encoded video). If it fails to find a match it just + * uses the default preview size for video. + *

+ * https://github.com/commonsguy/cwac-camera/blob/master/camera/src/com/commonsware/cwac/camera/CameraUtils.java + */ + public static int[] choosePreviewSize(Camera.Parameters parms, int width, int height) { + // We should make sure that the requested MPEG size is less than the preferred + // size, and has the same aspect ratio. + Camera.Size ppsfv = parms.getPreferredPreviewSizeForVideo(); + + if (DEBUG) { + for (Camera.Size size : parms.getSupportedPreviewSizes()) { + Log.e(TAG, "supported: " + size.width + "x" + size.height); + } + } + + for (Camera.Size size : parms.getSupportedPreviewSizes()) { + if (size.width == width && size.height == height) { + parms.setPreviewSize(width, height); + return new int[]{width, height}; + } + } + + Log.e(TAG, "Unable to set preview size to " + width + "x" + height); + if (ppsfv != null) { + parms.setPreviewSize(ppsfv.width, ppsfv.height); + return new int[]{ppsfv.width, ppsfv.height}; + } + // else use whatever the default size is + return new int[]{0, 0}; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/utils/FPSUtil.java b/app/src/main/java/com/fengliyan/tianlesue/agora/utils/FPSUtil.java new file mode 100644 index 0000000..a76a6c8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/utils/FPSUtil.java @@ -0,0 +1,82 @@ +package com.fengliyan.tianlesue.agora.utils; + +import android.util.Log; + +/** + * FPS工具类 + * Created by tujh on 2018/5/24. + */ +public class FPSUtil { + private static final String TAG = FPSUtil.class.getSimpleName(); + private static final int NANO_IN_ONE_MILLI_SECOND = 1000000; + + private static long mLastFrameTimeStamp = 0; + + /** + * 每帧都计算 + * + * @return + */ + public static double fps() { + double fps = 0; + long tmp = System.nanoTime(); + fps = 1000.0f * NANO_IN_ONE_MILLI_SECOND / (tmp - mLastFrameTimeStamp); + mLastFrameTimeStamp = tmp; + Log.e(TAG, "FPS : " + fps); + return fps; + } + + private static long mStartTime = 0; + private static int mFPSFrameRate = 0; + + /** + * 平均值 + * + * @return + */ + public static double fpsAVG(int time) { + if (mStartTime == 0) { + mFPSFrameRate = 0; + mStartTime = System.nanoTime(); + return 0; + } + mFPSFrameRate += time; + double fps = 0; + fps = 1000.0f * NANO_IN_ONE_MILLI_SECOND * mFPSFrameRate / (System.nanoTime() - mStartTime); +// Log.e(TAG, "FPS : " + fps); + return fps; + } + + public static void resetAVG() { + mFPSFrameRate = 0; + mStartTime = 0; + } + + private long mLimitMinTime = 33333333; + private long mLimitStartTime; + private int mLimitFrameRate; + + public void setLimitMinTime(long limitMinTime) { + mLimitMinTime = limitMinTime; + } + + public void limit() { + try { + if (mLimitFrameRate == 0 || mLimitFrameRate > 600000) { + mLimitStartTime = System.nanoTime(); + mLimitFrameRate = 0; + } + long sleepTime = mLimitMinTime * mLimitFrameRate++ - (System.nanoTime() - mLimitStartTime); + if (sleepTime > 0) { + Thread.sleep(sleepTime / NANO_IN_ONE_MILLI_SECOND, (int) (sleepTime % NANO_IN_ONE_MILLI_SECOND)); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void resetLimit() { + mLimitStartTime = 0; + mLimitFrameRate = 0; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/agora/utils/ToastUtil.java b/app/src/main/java/com/fengliyan/tianlesue/agora/utils/ToastUtil.java new file mode 100644 index 0000000..33e64d8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/agora/utils/ToastUtil.java @@ -0,0 +1,23 @@ +package com.fengliyan.tianlesue.agora.utils; + +import android.content.Context; +import android.view.Gravity; +import android.widget.Toast; + +/** + * Created by tujh on 2018/6/28. + */ +public abstract class ToastUtil { + + public static void showToast(Context context, String str) { + Toast toast = Toast.makeText(context, str, Toast.LENGTH_SHORT); + toast.setGravity(Gravity.CENTER, 0, 0); + toast.show(); + } + + public static void showToast(Context context, int str) { + Toast toast = Toast.makeText(context, str, Toast.LENGTH_SHORT); + toast.setGravity(Gravity.CENTER, 0, 0); + toast.show(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/base/RecyclerLoadAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/base/RecyclerLoadAdapter.java new file mode 100644 index 0000000..7a183ea --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/base/RecyclerLoadAdapter.java @@ -0,0 +1,44 @@ +package com.fengliyan.tianlesue.controller.base; + + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * ying 2020/10/14 + * Describe :下拉加载 + */ + +public abstract class RecyclerLoadAdapter extends RecyclerView.Adapter { + private static final String TAG = "RecyclerLoadAdapter"; + private LinearLayoutManager mLayoutManager; + private boolean loading = true; + private int page=1; + private int mItemCount; + + + public RecyclerLoadAdapter(RecyclerView recyclerView) { + mLayoutManager = new LinearLayoutManager(recyclerView.getContext()); + recyclerView.setLayoutManager(mLayoutManager); + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + int itemCount = mLayoutManager.getItemCount(); + // Log.i(TAG, "onScrolled: " + itemCount + " --- " + mItemCount+ " --- "+loading); + if (!loading && itemCount > mItemCount) { + loading = true; + } + if (itemCount - mLayoutManager.findLastVisibleItemPosition() < 5 && loading) { + loading = false; + mItemCount = itemCount; + getloadData(++page); + } + + } + }); + } + + protected abstract void getloadData(int page); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/constant/ConsUser.java b/app/src/main/java/com/fengliyan/tianlesue/controller/constant/ConsUser.java new file mode 100644 index 0000000..e18992c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/constant/ConsUser.java @@ -0,0 +1,87 @@ +package com.fengliyan.tianlesue.controller.constant; + +/** + * Created by zhangbin on 2018/12/4. + */ + +public class ConsUser { + + /** + * "usercode":"101223", + * "nickname":"111111", + * "type":0, + * "mobile":"130****1017", + * "avatar":"uploads/album/201809/02/b38a3845d6291fbe869d63b42134e642.jpg", + * "gender":2, + * "age":6, + * "birthday":"2012-01-01", + * "city":"北京", + * "finish_status":1, + * "im_token":"8144d5aa-389d-48d2-acda-b2cf8a27115d", + * "is_anchor":0, + * "invite_code":"105647", + * "token":"94ea021c-6e4c-4863-827b-2487156517b6", + * "user_id":241, + * "createtime":1543907842, + * "expiretime":1546499842, + * "expires_in":2592000 + */ + + public final static String USERCODE = "zb_usercode"; + public final static String NICKNAME = "zb_nickname"; + public final static String TYPE = "zb_type"; + public final static String MOBILE = "zb_mobile"; + public final static String AVATAR = "zb_avatar"; + public final static String GENDER = "zb_gender"; + public final static String AGE = "zb_age"; + public final static String BIRTHDAY = "zb_birthday"; + public final static String CITY = "zb_city"; + public final static String FINISH_STATUS = "zb_finish_status"; + public final static String IM_TOKEN = "zb_im_token"; + public final static String IS_ANCHOR = "zb_is_anchor"; + public final static String IS_FACE_STATUS = "IS_FACE_STATUS"; + public final static String INVITE_CODE = "zb_invite_code"; + public final static String TOKEN = "zb_token"; + public final static String USER_ID = "zb_user_id"; + public final static String USER_VIP = "user_vip"; + public final static String HIDE_READ_MSG = "HIDE_READ_MSG"; + public final static String CREATETIME = "zb_createtime"; + public final static String EXPIRETIME = "zb_expiretime"; + + public final static String IS_LOGIN = "is_login"; + + public final static String SYSID = "sys_id"; + public final static String SERVID = "serv_id"; + public final static String SERVIDS = "serv_ids"; + public final static String SEND_USER_TOTAL = "send_user_total"; + public final static String GREET_DAY_TOTAL = "greet_day_total"; + public final static String GREET_GAP_HOUR = "greet_gap_hour"; + public final static String RESOURCE_VERSION = "resource_version"; + public final static String WECHAT_STATUS = "WECHAT_STATUS"; + public final static String SEND_VIDEO_MAX_NUM = "SEND_VIDEO_MAX_NUM"; + public final static String SEND_VIDEO_INTERVAL = "SEND_VIDEO_INTERVAL"; + public final static String CHAT_REAL_NAME_SWITCH = "CHAT_REAL_NAME_SWITCH"; + public final static String DYNAMIC_REAL_NAME_SWITCH = "DYNAMIC_REAL_NAME_SWITCH"; + public final static String RISK_FACE_STATUS = "RISK_FACE_STATUS"; + public final static String TURNTABLE_COUPON_SWITCH = "TURNTABLE_COUPON_SWITCH"; + public final static String AGORA_APP_ID = "AGORA_APP_ID"; + public final static String PROFILE = "PROFILE"; + + public final static String PICKER_CITY = "picker_city"; + public final static String PICKER_CITY_ID = "picker_city_id"; + + public final static String GENDER_CITY = "gender_city"; + public final static String GENDER_CITY_ID = "gender_city_id"; + + public final static String SKILL_CITY = "skill_city"; + public final static String SKILL_CITY_ID = "skill_city_id"; + + public final static String DYNAMIC_CITY = "dynamic_city"; + public final static String DYNAMIC_CITY_ID = "dynamic_city_id"; + + public final static String IS_LOGIN_AGREEMENT_CHECK = "is_login_agreement_check"; + + public final static String MY_AVATAR_FRAME = "MY_AVATAR_FRAME"; + public final static String USER_AVATAR_FRAME = "USER_AVATAR_FRAME"; + public final static String DYNAMICS_TYPE = "dynamicsType"; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/constant/ConstUrl.java b/app/src/main/java/com/fengliyan/tianlesue/controller/constant/ConstUrl.java new file mode 100644 index 0000000..c36ade0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/constant/ConstUrl.java @@ -0,0 +1,249 @@ +package com.fengliyan.tianlesue.controller.constant; + + +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.view.base.BaseApplication; + +/** + * Created by abby on 2018/4/6. + */ +public class ConstUrl { + // public final static boolean DEBUG = true; +// public final static boolean LOGDEBUG = false; + public final static String DEFAULT_PATH = BaseApplication.getInstance().getExternalFilesDir("").getAbsolutePath(); + public final static boolean DEBUG = BuildConfig.IS_DEV; + public static boolean DEBUG1 = NoClearSPUtils.getBoolean(BaseApplication.getInstance(), Constans.ENVIRONMENT_TYPE, true); + public final static boolean LOGDEBUG = BuildConfig.IS_DEV; + public final static String BASE_ROOT = DEBUG ? (DEBUG1 ? "https://pre.xq.whnuanbeinikj.cn/" : "https://xq.whnuanbeinikj.cn/") : + "https://xq.whnuanbeinikj.cn/"; + //public static final String WEBSOCKTURL = "saws://192.168.32.106:11119/acc1"; + public static final String WEBSOCKTURL = "ws://red.nndongqing.cn/acc1"; + public static final String SOCKET_USERSTATIS_DEBUG = "wss://pre.ws.ncaicai.tech?user_id="; + public static final String SOCKET_USERSTATIS = "wss://ws.whnuanbeinikj.cn?user_id="; + public static final String SOCKET_SPEED_DATE = DEBUG ? (DEBUG1 ? "wss://pre.ws.whnuanbeinikj.cn/speed?token=" : "wss://ws.whnuanbeinikj.cn/speed?token=") : + "wss://ws.whnuanbeinikj.cn/speed?token="; + public final static String IMAGE_URL = "http://xqasset.whnuanbeinikj.cn/"; + public final static String BASE_URL = BASE_ROOT + "api/"; + public final static String APP_FIELD = "app/"; + public final static String AUTH_FIELD = "passport/"; + public final static String CODE_FIELD = "authcode/"; + public final static String USER_FIELD = "user/"; + public final static String ZONE_FIELD = "dynamic/"; + public final static String FOLLOW_FIELD = "follows/"; + public final static String TOOL_FIELD = "tools/"; + public final static String COMMON_FIELD = "common/"; + public final static String MAIN_FIELD = "index/"; + public final static String CHANNEL_FIELD = "skill/"; + public final static String ANCHOR_FIELD = "anchor/"; + public final static String TASK_FIELD = "task/"; + public final static String RANK_FIELD = "rank/"; + public final static String CHAT_FIELD = "chat/"; + public final static String UPLOAD_FIELD = "upload/"; + public final static String UPLOAD_FIELD1 = "upload/"; + public final static String INDEX_FIELD = "index/"; + public final static String WALLET_FIELD = "wallet/"; + public final static String GREET_FIELD = "greet/"; + public final static String GUARD = "guard/"; + public final static String ACTIVITY = "Activity/"; + public final static String APIGREET = "greet/"; + public final static String UPDATEREALCITY = getUrl(BASE_URL, "Restapi/", "updateLngLat"); + public final static String QUERY_CITIES = getUrl(BASE_URL, APP_FIELD, "citys"); + public final static String REMARK = getUrl(BASE_URL, USER_FIELD, "remark");//获取备注 + public final static String CALL_DELETE = getUrl(BASE_URL, USER_FIELD, "call_delete");//删除通话记录 + public final static String GET_REMARK = getUrl(BASE_URL, USER_FIELD, "get_remark");//获取备注 + public final static String QUERY_GIFTS = getUrl(BASE_URL, APP_FIELD, "gifts"); + public final static String SEND_CODE = getUrl(BASE_URL, AUTH_FIELD, "send_code"); + public final static String BEFORE_CHANGE_MOBILE = getUrl(BASE_URL, "", "UserAccount/beforeChangeMobile"); + public final static String SUBMIT_CHANGE_MOBILE = getUrl(BASE_URL, "", "UserAccount/submitChangeMobile"); + public final static String EDIT_USER_PWD = getUrl(BASE_URL, "", "UserAccount/editUserPwd"); + public final static String SEND_PIC_CODE = getUrl(BASE_URL, CODE_FIELD, "sendcode"); + public final static String REGISTER = getUrl(BASE_URL, AUTH_FIELD, "register"); + public final static String LOGIN = getUrl(BASE_URL, AUTH_FIELD, "login"); + public final static String FORGET = getUrl(BASE_URL, AUTH_FIELD, "resetpwd"); + public final static String THIRD = getUrl(BASE_URL, AUTH_FIELD, "third"); + public final static String SET_USER_INFO = getUrl(BASE_URL, USER_FIELD, "saveinfo"); + public final static String GET_USER_INFO = getUrl(BASE_URL, USER_FIELD, "home"); + public final static String GET_USER_MY_DYNAMIC = getUrl(BASE_URL, USER_FIELD, "my_dynamic_list"); + public final static String GET_USER_IS_VIP = getUrl(BASE_URL, USER_FIELD, "ifVip"); + public final static String GET_DYNAMIC_LIST = getUrl(BASE_URL, ZONE_FIELD, "lists"); + public final static String THUMB_UP = getUrl(BASE_URL, ZONE_FIELD, "like"); + public final static String FOLLOW = getUrl(BASE_URL, USER_FIELD, "follow"); + public final static String DELETE_DYNAMICS = getUrl(BASE_URL, ZONE_FIELD, "delete"); //删除动态 + public final static String POST_DYNAMICS = getUrl(BASE_URL, ZONE_FIELD, "publish"); + public final static String UPLOAD_PHOTO = getUrl(BASE_URL, ZONE_FIELD, "publish_image"); + public final static String UPLOADIMAGE = getUrl(BASE_URL, UPLOAD_FIELD, "images"); + public final static String UPLOADIMAGE1 = getUrl(BASE_URL, UPLOAD_FIELD1, "file"); + + public final static String COMPLETE_PROFILE = getUrl(BASE_URL, USER_FIELD, "profile"); + public final static String MAIN_BANNER_FIELD = getUrl(BASE_URL, MAIN_FIELD, "index"); + public final static String FREEANCHOR = getUrl(BASE_URL, MAIN_FIELD, "freeAnchor"); + public final static String CHANNEL_DATA = getUrl(BASE_URL, CHANNEL_FIELD, "anchors"); + public final static String MAIN_PAGE_DATA = getUrl(BASE_URL, USER_FIELD, "info"); + public final static String GET_ALL_CHANNELS = getUrl(BASE_URL, CHANNEL_FIELD, "lists"); + public final static String BE_ANCHOR_STATUS = getUrl(BASE_URL, ANCHOR_FIELD, "join"); + public final static String GET_SELFIE_EXAMPLE = getUrl(BASE_URL, ANCHOR_FIELD, "camera_audit"); + public final static String GET_FACE_CERTIFY_ID = getUrl(BASE_URL, "", "face/get_aly_certify_id"); + public final static String FACE_CERTIFY_STATUS = getUrl(BASE_URL, "", "face/certify_status"); + public final static String ANCHOR_APPLY = getUrl(BASE_URL, ANCHOR_FIELD, "apply"); + public final static String AGREE_ANCHOR_CONTRACT = getUrl(BASE_URL, ANCHOR_FIELD, "agree_protocol"); + public final static String MISSION_LIST = getUrl(BASE_URL, TASK_FIELD, "lists"); + public final static String MISSION_SHARE = getUrl(BASE_URL, TASK_FIELD, "share"); + public final static String MISSION_SIGN = getUrl(BASE_URL, TASK_FIELD, "sign"); + public final static String SIGN_DATA = getUrl(BASE_URL, "", "v/rechargeSign/index"); + public final static String SIGN_IN = getUrl(BASE_URL, "", "v/rechargeSign/sign"); + public final static String RANK_GIFT = getUrl(BASE_URL, RANK_FIELD, "gift"); + public final static String RANK_INVITE = getUrl(BASE_URL, RANK_FIELD, "invite"); + public final static String RANK_LOVE = getUrl(BASE_URL, RANK_FIELD, "love"); + public final static String RANK_WEALTH = getUrl(BASE_URL, RANK_FIELD, "wealth"); + public final static String RANK_RICH = getUrl(BASE_URL, RANK_FIELD, "rich"); + public final static String GET_GUARD_LIST = getUrl(BASE_URL, GUARD, "get_guard_list"); + public final static String GET_INVITATION_DATA = getUrl(BASE_URL, USER_FIELD, "invite"); + public final static String GET_INVITATION_RECHARGE_LIST = getUrl(BASE_URL, USER_FIELD, "getInviteRechargeList"); + public final static String CONTRACT_URL = getUrl(BASE_ROOT, "", "/index/about/service.html"); + public final static String HELP_URL_BOY = getUrl(BASE_ROOT, "", "/index/about/help_boy.html"); + public final static String HELP_URL_GIRL = getUrl(BASE_ROOT, "", "/index/about/siyuHelpGirl.html"); + public final static String HELP_URL_SPECIAL = getUrl(BASE_ROOT, "", "/index/about/help_audit.html"); + public final static String AGREEMENT_URL = getUrl(BASE_ROOT, "", BuildConfig.AGREEMENT); + public final static String VIP_AGREEMENT_URL = getUrl(BASE_ROOT, "", BuildConfig.VIP_AGREEMENT); + public final static String RULE_URL = getUrl(BASE_ROOT, "", "/index/about/invite_help.html"); //规则详情 + //应用宝 yybprivacy + public final static String USER_PRIVACY_URL = getUrl(BASE_ROOT, "", BuildConfig.PRIVACY); //用户隐私协议 + public final static String CANCALLATION_URL = getUrl(BASE_ROOT, "", "/index/logout/siyuIndex"); + + public final static String TRACER_LIST = getUrl(BASE_URL, USER_FIELD, "viewer_list"); + public final static String VISITOR_LIST = getUrl(BASE_URL, USER_FIELD, "visitor_list"); + public final static String GETADVERT = getUrl(BASE_URL, USER_FIELD, "getAdvert"); //广告 + public final static String FOCUS_LIST = getUrl(BASE_URL, USER_FIELD, "follow_list"); + public final static String FANS_LIST = getUrl(BASE_URL, USER_FIELD, "fans_list"); + public final static String RECEIVED_GIFT_LIST = getUrl(BASE_URL, USER_FIELD, "gift_list"); + public final static String GET_CHAT_INFO = getUrl(BASE_URL, CHAT_FIELD, "call"); + public final static String SEND_GIFT = getUrl(BASE_URL, CHAT_FIELD, "send_gift"); + public final static String GET_GIFT_DATA = getUrl(BASE_URL, APP_FIELD, "gifts"); + public final static String DYNAMIC_SEND_GIFT = getUrl(BASE_URL, ZONE_FIELD, "send_gift"); + public final static String SEND_IM_COST = getUrl(BASE_URL, CHAT_FIELD, "send_im"); + public final static String CHECK_SELFIE = getUrl(BASE_URL, ANCHOR_FIELD, "upload_camera_audit"); + public final static String GET_SKILL_INFO = getUrl(BASE_URL, ANCHOR_FIELD, "skill_setting"); + public final static String SET_SKILL_PRICE = getUrl(BASE_URL, ANCHOR_FIELD, "set_price"); + public final static String SET_SKILL_PRICE1 = getUrl(BASE_URL, ANCHOR_FIELD, "setPriceAndStatus"); + public final static String GET_MY_SKILL = getUrl(BASE_URL, ANCHOR_FIELD, "my_skill"); + public final static String ADD_SKILLS = getUrl(BASE_URL, ANCHOR_FIELD, "add_skill"); + public final static String PRIVILEGE_INFO = getUrl(BASE_URL, ANCHOR_FIELD, "privilege_vip_info"); + public final static String PRIVILEGE_SETTING = getUrl(BASE_URL, ANCHOR_FIELD, "privilege_setting"); + public final static String GET_BIND_INFO = getUrl(BASE_URL, USER_FIELD, "account_binds"); + public final static String BIND_PHONE = getUrl(BASE_URL, USER_FIELD, "bind_mobile"); + public final static String REAL_NAME_ATTEST = getUrl(BASE_URL, "", "attest/realNameAttest"); + public final static String BIND_PLATFORM = getUrl(BASE_URL, USER_FIELD, "bind_platform"); + public final static String CHANGE_VIDEO_STATUS = getUrl(BASE_URL, ANCHOR_FIELD, "set_video_status"); + public final static String SWITCH_SERVICE_NUM = getUrl(BASE_URL, ANCHOR_FIELD, "switchServiceNum"); + public final static String GET_GLOBAL_CONFIG = getUrl(BASE_URL, APP_FIELD, "config"); + public final static String GET_BLACK_LIST = getUrl(BASE_URL, USER_FIELD, "black_list"); + public final static String SEARCH = getUrl(BASE_URL, INDEX_FIELD, "search"); + public final static String WALLET_INDEX = getUrl(BASE_URL, WALLET_FIELD, "index"); + public final static String GET_RECHARGE_INFO = getUrl(BASE_URL, WALLET_FIELD, "goods_list"); + public final static String PAY_TO_RECHARGE = getUrl(BASE_URL, WALLET_FIELD, "recharge"); + public final static String PAY_TO_RECHARGEV2 = getUrl(BASE_URL, WALLET_FIELD, "rechargeV2"); + public final static String GETWECHATPAYSITE = getUrl(BASE_URL, WALLET_FIELD, "getWechatPaySite"); + + + public final static String GET_BILL_LIST = getUrl(BASE_URL, WALLET_FIELD, "record"); + public final static String GET_CALL_INFO_FROM_ROOM = getUrl(BASE_URL, CHAT_FIELD, "get_room"); + public final static String GET_VIDEO_FEE = getUrl(BASE_URL, CHAT_FIELD, "video_charging"); + public final static String GET_COMPLAINT_LIST = getUrl(BASE_URL, USER_FIELD, "report_cate"); + public final static String DO_COMPLAINT = getUrl(BASE_URL, USER_FIELD, "report"); + public final static String DO_BLACK = getUrl(BASE_URL, USER_FIELD, "black"); + public final static String GET_USER_DYNAMIC_LIST = getUrl(BASE_URL, USER_FIELD, "dynamic_list"); + public final static String GET_WITHDRAW_INFO = getUrl(BASE_URL, WALLET_FIELD, "withdraw"); + public final static String BIND_ACCOUNT = getUrl(BASE_URL, WALLET_FIELD, "bind_alipay"); + public final static String GET_BIND_ACCOUNT = getUrl(BASE_URL, WALLET_FIELD, "alipay"); + public final static String DO_WITHDRAW = getUrl(BASE_URL, WALLET_FIELD, "user_withdrawv1"); + // public final static String DO_WITHDRAW = getUrl(BASE_URL, WALLET_FIELD, "user_withdraw"); + public final static String GET_USERS_IN_SAME_CITY = getUrl(BASE_URL, INDEX_FIELD, "city_users"); + public final static String GET_ACTIVE_USERS = getUrl(BASE_URL, INDEX_FIELD, "active_users"); + public final static String GET_SYSTEM_VERSION = getUrl(BASE_URL, APP_FIELD, "system"); + public final static String EVALUATE_VIDEO = getUrl(BASE_URL, CHAT_FIELD, "video_score"); + public final static String INVITE_LIST = getUrl(BASE_URL, USER_FIELD, "invite_list"); + public final static String SETTING_BRAND_LIST = getUrl(BASE_URL, USER_FIELD, "setting_brand"); + public final static String ACTIVE_UPDATE = getUrl(BASE_URL, USER_FIELD, "active_update"); + public final static String GET_MARKET_STATUS = getUrl(BASE_URL, APP_FIELD, "getMarketStatus"); + public final static String ATTENTION_DIALOG_LIST = getUrl(BASE_URL, MAIN_FIELD, "recommend_follows"); + public final static String BATCH_FOLLOW = getUrl(BASE_URL, MAIN_FIELD, "batch_follow"); + public final static String RECOMMEND_ANCHORS = getUrl(BASE_URL, INDEX_FIELD, "recommend_anchors"); + public final static String NEW_ANCHORS = getUrl(BASE_URL, INDEX_FIELD, "new_anchors"); + public final static String ACTIVE_ANCHORS = getUrl(BASE_URL, INDEX_FIELD, "active_anchors"); + public final static String COVER_VIDEO = getUrl(BASE_URL, INDEX_FIELD, "cover_video"); + public final static String CITY_ANCHORS = getUrl(BASE_URL, INDEX_FIELD, "city_anchors"); + public final static String CHAT_TIP = getUrl(BASE_URL, CHAT_FIELD, "chat_tip"); + public final static String CHAT_SETTING = getUrl(BASE_URL, CHAT_FIELD, "chat_setting"); + public final static String GREET_LISTS = getUrl(BASE_URL, GREET_FIELD, "lists"); + public final static String GREET_ADD = getUrl(BASE_URL, GREET_FIELD, "add"); + public final static String GREET_SEND = getUrl(BASE_URL, GREET_FIELD, "send"); + public final static String USER_LITE = getUrl(BASE_URL, USER_FIELD, "lite"); + public final static String GREET_DELETE = getUrl(BASE_URL, GREET_FIELD, "delete"); + public final static String CALL_LIST = getUrl(BASE_URL, USER_FIELD, "call_list"); + public final static String USER_MEMBER = getUrl(BASE_URL, USER_FIELD, "member"); + public final static String USER_MEMBER_PRIVILEGES = getUrl(BASE_URL, USER_FIELD, "privileges"); + public final static String CHAT_SNAPSHOOT = getUrl(BASE_URL, CHAT_FIELD, "snapshoot_v2"); + public final static String SET_ADOLESCENT = getUrl(BASE_URL, USER_FIELD, "set_adolescent"); + public final static String CLOSE_ADOLESCENT = getUrl(BASE_URL, USER_FIELD, "switch_adolescent"); + public final static String VERIFY_MOBILE_CODE = getUrl(BASE_URL, USER_FIELD, "verify_mobile_code"); + public final static String GET_ADOLESCENT_STATUS = getUrl(BASE_URL, USER_FIELD, "get_adolescent_status"); + public final static String ADD_GUARD = getUrl(BASE_URL, GUARD, "add_guard"); + public final static String GET_USER_GUARD_LIST = getUrl(BASE_URL, GUARD, "get_user_guard_list"); + public final static String ROOM_ADD_GUARD = getUrl(BASE_URL, GUARD, "room_add_guard"); + public final static String SCREEN_NUMBER = getUrl(BASE_URL, USER_FIELD, "screen_number"); + public final static String GET_CHAT_WORD_LIST = getUrl(BASE_URL, "", "greet/getChatWordList");//获取聊天页的文字招呼列表 + public final static String GETGUARDINFO = getUrl(BASE_URL, GUARD, "getguardinfo");//获取守护价格信息 + public final static String REDWARS = getUrl(BASE_URL, ACTIVITY, "redWars"); //抢红包 + public final static String REDPACKVIEW = getUrl(BASE_URL, ACTIVITY, "redPackView"); //红包详情 + public final static String FORBID_LIST = getUrl(BASE_ROOT, "", "/index/about/siyuForbidList"); //违规公告 + public final static String WECHAT_QQ_VERIFY = getUrl(BASE_URL, USER_FIELD, "wechat_qq_verify"); //添加微信 + public final static String WECHATANDQQCHECK = getUrl(BASE_URL, USER_FIELD, "wechatAndQQCheck"); //查看微信状态 + public final static String PRICE_SETTING = getUrl(BASE_URL, ANCHOR_FIELD, "newPriceSetting"); //查看自己的价格 + public final static String SETWECHATPRICE = getUrl(BASE_URL, USER_FIELD, "setWechatPrice"); //微信价格设置 + public final static String LISTS = getUrl(BASE_URL, APIGREET, "lists"); //招呼列表 + public final static String ADD = getUrl(BASE_URL, APIGREET, "add"); //添加招呼 + public final static String DELETE = getUrl(BASE_URL, APIGREET, "delete"); //删除招呼 + public final static String CALL_END_RECOMMEND = getUrl(BASE_URL, "", "userCall/manCallEndRecommend"); //用户通话结束界面-推荐列表 + public final static String FIRST_RECHARGE_BURIED_POINT = getUrl(BASE_URL, "", "BuriedPoint/giftBag"); //首充礼包埋点 + public final static String MINE_BACKPACK = getUrl(BASE_URL, "", "item/backpack"); //我的背包列表 + public final static String BANNER_LIST = getUrl(BASE_URL, "", "index/bannerList"); //banner列表 + + public final static String CLOSE_GREET = getUrl(BASE_URL, GREET_FIELD, "closeGreet"); //关闭免打扰nf + public final static String GET_GREET = getUrl(BASE_URL, GREET_FIELD, "getGreet"); //查询用户免打扰 + public final static String GREET_SEND_ONE = getUrl(BASE_URL, GREET_FIELD, "sendOne"); //单独打招呼 + + public final static String DELETE_ACCOUNT = getUrl(BASE_URL, "", "passport/logout"); //注销账号 + public final static String ONE_KEY_LOGIN = getUrl(BASE_URL, "", "passport/mobileLogin"); //手机号一键登录 + public final static String DYNAMIC_LIKE = getUrl(BASE_URL, ZONE_FIELD, "like"); + public final static String DYNAMIC_DETAIL = getUrl(BASE_URL, ZONE_FIELD, "detail"); + public final static String COMMENT_LIST = getUrl(BASE_URL, ZONE_FIELD, "commentList"); + public final static String ADDCOMMENT = getUrl(BASE_URL, ZONE_FIELD, "addComment"); + public final static String DEL_COMMENT = getUrl(BASE_URL, ZONE_FIELD, "delComment"); + public final static String COMMENT_LIKE = getUrl(BASE_URL, ZONE_FIELD, "comment_like"); + public final static String GETWECHAT = getUrl(BASE_URL, USER_FIELD, "getWechat"); + public final static String GETNICKNAME = getUrl(BASE_URL, USER_FIELD, "getnickname"); + public final static String GETLOGOUT = getUrl(BASE_URL, USER_FIELD, "getlogout"); + public final static String UPTLOGOUT = getUrl(BASE_URL, USER_FIELD, "uptlogout"); + public final static String CUSTOMER_TIP = getUrl(BASE_URL, USER_FIELD, "customerTip"); + public final static String BANK = getUrl(BASE_URL, WALLET_FIELD, "bank"); + public final static String BIND_BANK = getUrl(BASE_URL, WALLET_FIELD, "bind_bank"); + public final static String USER_WITHDRAW_BANK = getUrl(BASE_URL, WALLET_FIELD, "user_withdraw_bank"); + public final static String MEMBERSWITCH = getUrl(BASE_URL, WALLET_FIELD, "memberswitch"); + public final static String SNAPSHOOT_IM = getUrl(BASE_URL, CHAT_FIELD, "snapshoot_im"); + public final static String GET_CALL_SPEED_INFO = getUrl(BASE_URL, CHAT_FIELD, "getCallSpeedInfo"); + public final static String VIDEO_CHECK = getUrl(BASE_URL, CHAT_FIELD, "sendVideoCheck"); + + public final static String HOME_ONLINE = getUrl(BASE_URL, "", "homePage/onlineList"); + public final static String HOME_NEW_USER = getUrl(BASE_URL, "", "homePage/newUserList"); + public final static String HOME_CITY = getUrl(BASE_URL, "", "homePage/cityUserList"); + public final static String GET_TURNTABLE = getUrl(BASE_URL, "", "activity/getTurntable"); + public final static String START_TURNTABLE = getUrl(BASE_URL, "", "activity/startTurntable"); + public final static String TURNTABLE_WINNING_RECORD = getUrl(BASE_URL, "", "activity/turntableWinningRecord"); + public final static String YEAR_TREASURE_HUNT = getUrl(BASE_URL, "", "activity/yearTreasureHunt"); + + public static String getUrl(String base, String field, String method) { + return base + field + method; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/constant/Constant.java b/app/src/main/java/com/fengliyan/tianlesue/controller/constant/Constant.java new file mode 100644 index 0000000..b85f8ea --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/constant/Constant.java @@ -0,0 +1,69 @@ +package com.fengliyan.tianlesue.controller.constant; + +/** + * Created by zhangbin on 2018/12/12. + */ + +public class Constant { + + //图片压缩大小 + public final static int IMAGE_MEMORY_SIZE = 400; + + //socket路径 + public final static String SOCKET_URL = "socket_url"; + + //主叫者连接成功 + public final static String REQUEST = "request"; + + //被叫者连接成功 + public final static String RESPONSE = "response"; + + //主叫者更新提示信息 + public final static String UPDATETIP = "updatetip"; + + //开始视频 + public final static String STARTVIDEO = "startvideo"; + + //挂断 + public final static String HANGUP = "hangup"; + + //通知 (同时发给双方) + public final static String NOTICE = "notice"; + + //心跳检测包 + public final static String HEARTBEAT = "heartbeat"; + + //剩余时长 + public final static String CANCALLTIME = "cancalltime"; + + //女生提醒充值 + public final static String PROMPTMANRECHARGE = "prompt_man_recharge"; + + //男生涉黄,女生黑屏遮罩 + public final static String PORN_MASK = "pornMask"; + + //微信Id + public final static String WECHAT_APP_ID = "wx99d6a2e2d4967362"; + + //默认消息 + public final static String LIST_DEFAULT_MESSAGE = "list_default_message"; + + //默认快捷回复 + public final static String DEFAULT_MESSAGE = "你好"; + + //新消息提醒 + public final static String NEW_MESSAGE_NOTICE = "new_message_notice"; + + //响铃通知 + public final static String RING_NOTICE = "ring_notice"; + + //震动通知 + public final static String SHAKE_NOTICE = "shake_notice"; + + //飘屏通知 + public final static String FLUTTER_NOTICE = "flutter_notice"; + + public final static String AES_PASSWORD = "KBqTS1K3qj0flRE9"; + + public static boolean IS_LOGIN_AGREEMENT_CHECK = false; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/DynamicsAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/DynamicsAdapter.java new file mode 100644 index 0000000..8d5addb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/DynamicsAdapter.java @@ -0,0 +1,515 @@ +package com.fengliyan.tianlesue.controller.dynamics.adapter; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.blankj.utilcode.util.ActivityUtils; +import com.facebook.drawee.generic.GenericDraweeHierarchy; +import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; +import com.facebook.drawee.generic.RoundingParams; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.dynamics.DynamicImage; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.diooto.Diooto; +import com.fengliyan.tianlesue.view.diooto.config.DiootoConfig; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; +import com.fengliyan.tianlesue.view.dynamics.activity.DynamicDetailActivity; +import com.fengliyan.tianlesue.view.dynamics.activity.ImageDisplayActivity; +import com.fengliyan.tianlesue.view.dynamics.activity.QYPreviewVideoActivity; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.main.utils.UiUtils; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.sketch.SketchImageView; +import com.zld.expandlayout.ExpandLayout; + +import java.util.ArrayList; +import java.util.List; + +public class DynamicsAdapter extends BaseAdapter { + private List mDynamicsItemList = new ArrayList<>(); + private Context mContext; + private OnThumbupClickedListener mListener; + private OnGiftSendListener mGiftListener; + private OnMenuClickListener mMenuClickListener; + private OnMenuDeleteClickListener mOnMunuDeleteClickListener; + public DynamicLikeCallback likeDynamicCallback; + public DynamicCommentCallback dynamicCommentCallback; + private BaseMessageDialog mDialog; + private int deleteCount = 0; + private int selfID = SPUtils.getInt(BaseApplication.getInstance(), ConsUser.USER_ID); + + public interface DynamicLikeCallback { + void likeDynamic(DynamicsItemBean bean); + } + + public interface DynamicCommentCallback { + void commentDynamic(DynamicsItemBean bean); + } + + public interface OnThumbupClickedListener { + void onClick(View v, String uid); + } + + public interface OnGiftSendListener { + void onSend(DynamicsItemBean bean, int quantity); + } + + public interface OnMenuClickListener { + void onMenuClicked(int position); + } + + //删除动态接口 + public interface OnMenuDeleteClickListener { + void onMenuDelete(int position, List mDynamicsItemList); + } + + public void setOnThumbupClickedListener(OnThumbupClickedListener listener) { + mListener = listener; + } + + public void setOnGiftSendListener(OnGiftSendListener listener) { + mGiftListener = listener; + } + + public void setOnMenuClickListener(OnMenuClickListener listener) { + mMenuClickListener = listener; + } + + public void setOnMenuDeleteClickListener(OnMenuDeleteClickListener onMunuDeleteClickListener) { + mOnMunuDeleteClickListener = onMunuDeleteClickListener; + } + + public DynamicsAdapter(Context context) { + mContext = context; + } + + public void setList(List list) { + mDynamicsItemList = list; + } + + private int nnumber; + private String id = ""; + + public void setGiftCount(int number, String id) { + this.nnumber = number; + this.id = id; + } + + @Override + public int getCount() { + return mDynamicsItemList.size(); + } + + @Override + public Object getItem(int i) { + if (i > mDynamicsItemList.size() - 1) { + return mDynamicsItemList.get(mDynamicsItemList.size() - 1); + } else { + return mDynamicsItemList.get(i); + } + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + if (null == view) { + view = View.inflate(mContext, R.layout.item_dynamic_list, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(R.id.tag_second); + } + final DynamicsItemBean bean = mDynamicsItemList.get(i); + if (bean.getUser_id().equals(String.valueOf(selfID))) { + holder.msgBtn.setVisibility(View.INVISIBLE); + } else { + holder.msgBtn.setVisibility(View.VISIBLE); + } + holder.likeCountLabel.setText(bean.getLike_count() + ""); + holder.commentCountLabel.setText(bean.getComment_count() + ""); + final int index = i; + holder.name.setText(bean.getNickname()); + holder.head.setImageURI(ConstUrl.IMAGE_URL + bean.getAvatar()); + holder.newPeopleImageView.setVisibility(View.GONE); + holder.realPeopleImageView.setVisibility(View.GONE); + + if (bean.getGender() == 1) { + holder.realPeopleImageView.setVisibility(View.VISIBLE); + if (bean.getMark() == 2) { + holder.newPeopleImageView.setVisibility(View.VISIBLE); + } + Drawable drawableLeft = ContextCompat.getDrawable(mContext, R.mipmap.sex_girl); + drawableLeft.setBounds(0, 0, drawableLeft.getMinimumWidth(), drawableLeft.getMinimumHeight()); + holder.iv_sex.setBackgroundResource(R.drawable.shape_dynamic_age_women); + holder.iv_sex.setImageResource(R.mipmap.sex_girl); + holder.years.setBackgroundResource(R.drawable.shape_dynamic_age_women); + holder.years.setCompoundDrawables(drawableLeft, null, null, null); + } else { + if (bean.getMark() == 2) { + holder.newPeopleImageView.setVisibility(View.VISIBLE); + } + holder.iv_sex.setBackgroundResource(R.drawable.shape_dynamic_age); + holder.iv_sex.setImageResource(R.mipmap.sex_men); + holder.years.setBackgroundResource(R.drawable.shape_dynamic_age); + Drawable drawableLeft = ContextCompat.getDrawable(mContext, R.mipmap.sex_men); + drawableLeft.setBounds(0, 0, drawableLeft.getMinimumWidth(), drawableLeft.getMinimumHeight()); + holder.years.setCompoundDrawables(drawableLeft, null, null, null); + } + holder.years.setText(bean.getAge() + ""); + holder.location.setText(bean.getCity() + " | " + bean.getCreate_time()); +// holder.info.setText(bean.getContent()); + holder.info.setText(bean.getContent(), bean.getExpand(), new ExpandLayout.OnExpandListener() { + @Override + public void expandChange() { + bean.setExpand(!bean.getExpand()); + notifyDataSetChanged(); + } + }); + + holder.msgBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + NimUIKit.startChat(bean.getUser_id(), mContext); + } + }); + holder.commentImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (dynamicCommentCallback != null) { + dynamicCommentCallback.commentDynamic(bean); + } else { + Intent intent = new Intent(mContext, DynamicDetailActivity.class); + intent.putExtra("dynamic_id", bean.getId()); + mContext.startActivity(intent); + } + } + }); + if (String.valueOf(SPUtils.getInt(mContext, ConsUser.USER_ID)).equals(mDynamicsItemList.get(index).getUser_id())) { + holder.getMenu.setImageResource(R.mipmap.feed_del); + } else { + holder.getMenu.setImageResource(R.mipmap.feed_more); + } + + holder.getMenu.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (String.valueOf(SPUtils.getInt(mContext, ConsUser.USER_ID)).equals(mDynamicsItemList.get(index).getUser_id())) { + if (null != mOnMunuDeleteClickListener) { + + mOnMunuDeleteClickListener.onMenuDelete(index, mDynamicsItemList); + } + } else { + if (null != mMenuClickListener) { + mMenuClickListener.onMenuClicked(index); + } + } + } + }); + + holder.rl_dynamic_item.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!(ActivityUtils.getTopActivity() instanceof DynamicDetailActivity)) { + Intent intent = new Intent(mContext, DynamicDetailActivity.class); + intent.putExtra("dynamic_id", bean.getId()); + mContext.startActivity(intent); + } + } + }); + addImageView(holder, bean.getImages()); + + + if (bean.getIs_like() == 1) { + holder.likeImageView.setImageResource(R.mipmap.feed_heart_); + } else { + holder.likeImageView.setImageResource(R.mipmap.feed_heart); + } + + holder.head.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", Integer.parseInt(bean.getUser_id())); + mContext.startActivity(intent); + } + }); + holder.likeImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (likeDynamicCallback != null) { + likeDynamicCallback.likeDynamic(bean); + } + } + }); + + view.setTag(R.id.tag_second, holder); + return view; + } + + private int isLike; + + + private void addImageView(Holder holder, final List dynamicImageList) { + + holder.imageListView1.removeAllViews(); + holder.imageListView2.removeAllViews(); + holder.imageListView3.removeAllViews(); + final List pathList = new ArrayList<>(); + if (null == dynamicImageList) { + return; + } + + if (1 == dynamicImageList.size()) { + GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder + .newInstance(mContext.getResources()).setRoundingParams(RoundingParams.fromCornersRadius(Utils.dip2px(mContext, 6))) + .build(); + + DynamicImage image = dynamicImageList.get(0); + RelativeLayout container = new RelativeLayout(mContext); + final SimpleDraweeView photoView = new SimpleDraweeView(mContext); + container.addView(photoView); + DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); + int height = dm.heightPixels; + int width = dm.widthPixels; + int newWidth = 0; + int newHeight = 0; + if (image.getWidth() > image.getHeight()) { + newWidth = (int) (0.55 * width); + newHeight = (int) (newWidth * image.getHeight() / image.getWidth()); + } else { + newHeight = (int) (0.25 * height); + newWidth = (int) (newHeight * image.getWidth() / image.getHeight()); + } + ImageView imageview = new ImageView(mContext); + if (!TextUtils.isEmpty(image.getVideo_url())) { + imageview.setImageResource(R.mipmap.feed_play); + } + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(newWidth, newHeight); + RelativeLayout.LayoutParams containerPAram = new RelativeLayout.LayoutParams(newWidth, newHeight); + RelativeLayout.LayoutParams imageParam = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + imageParam.addRule(RelativeLayout.CENTER_IN_PARENT); + container.addView(imageview, imageParam); + container.setLayoutParams(containerPAram); + photoView.setLayoutParams(params); + photoView.setHierarchy(hierarchy); + photoView.setImageURI(ConstUrl.IMAGE_URL + image.getUrl()); + ((ViewGroup) holder.imageListView1).addView(container); + pathList.add(ConstUrl.IMAGE_URL + image.getUrl()); + photoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (TextUtils.isEmpty(image.getVideo_url())) { + View[] views = new View[dynamicImageList.size()]; + views[0] = photoView; + startDisplayActivity(dynamicImageList, views, 0); + } else { + Intent intent = new Intent(mContext, QYPreviewVideoActivity.class); + intent.putExtra("videoUrl", ConstUrl.IMAGE_URL + image.getVideo_url()); + mContext.startActivity(intent); + } + } + }); + } else if (4 == dynamicImageList.size()) { + holder.imageListView1.setWeightSum(2); + holder.imageListView2.setWeightSum(2); + final View[] views = new View[dynamicImageList.size()]; + for (int i = 0; i < dynamicImageList.size(); i++) { + GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder + .newInstance(mContext.getResources()).setRoundingParams(RoundingParams.fromCornersRadius(Utils.dip2px(mContext, 6))) + .build(); + + DynamicImage image = dynamicImageList.get(i); + SimpleDraweeView photoView = new SimpleDraweeView(mContext); + LinearLayout.LayoutParams params = new LinearLayout + .LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + UiUtils.dp2px(mContext, 170)); + params.setMargins(5, 0, 5, 0); + params.weight = 1; + photoView.setLayoutParams(params); + photoView.setHierarchy(hierarchy); + photoView.setImageURI(ConstUrl.IMAGE_URL + image.getUrl()); + if (i < 2) { + ((ViewGroup) holder.imageListView1).addView(photoView); + } else { + ((ViewGroup) holder.imageListView2).addView(photoView); + } + views[i] = photoView; + final int count = i; + pathList.add(ConstUrl.IMAGE_URL + image.getUrl()); + photoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startDisplayActivity(dynamicImageList, views, count); + } + }); + } + } else { + final View[] views = new View[dynamicImageList.size()]; + for (int i = 0; i < dynamicImageList.size(); i++) { + GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder + .newInstance(mContext.getResources()).setRoundingParams(RoundingParams.fromCornersRadius(Utils.dip2px(mContext, 6))) + .build(); + + DynamicImage image = dynamicImageList.get(i); + SimpleDraweeView photoView = new SimpleDraweeView(mContext); +// LinearLayout.LayoutParams params = new LinearLayout +// .LayoutParams(UiUtils.dp2px(mContext, 110), +// UiUtils.dp2px(mContext, 110)); + + DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); +// int height = dm.heightPixels; + int width = dm.widthPixels; + int measure = (((width - UiUtils.dp2px(mContext, 32)) - 20) / 3) - 5; + LinearLayout.LayoutParams params = new LinearLayout + .LayoutParams(measure, + measure); + + + params.setMargins(5, 0, 5, 0); + photoView.setLayoutParams(params); + photoView.setHierarchy(hierarchy); + photoView.setImageURI(ConstUrl.IMAGE_URL + image.getUrl()); + if (i < 3) { + ((ViewGroup) holder.imageListView1).addView(photoView); + } else if (i < 6) { + ((ViewGroup) holder.imageListView2).addView(photoView); + } else { + ((ViewGroup) holder.imageListView3).addView(photoView); + } + views[i] = photoView; + final int count = i; + pathList.add(ConstUrl.IMAGE_URL + image.getUrl()); + photoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startDisplayActivity(dynamicImageList, views, count); + } + }); + } + } + } + + private void clickImage(ArrayList pathList, int innerCount) { + Intent intent = new Intent(mContext, ImageDisplayActivity.class); + intent.putStringArrayListExtra("urlList", pathList); + intent.putExtra("pageCount", innerCount); + mContext.startActivity(intent); + } + + private void startImageDisplaying(ArrayList url, String pageCount) { + Intent intent = new Intent(mContext, ImageDisplayActivity.class); + intent.putStringArrayListExtra("urlList", url); + intent.putExtra("pageCount", pageCount); + mContext.startActivity(intent); + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.head = v.findViewById(R.id.dynamic_list_photo); + holder.name = v.findViewById(R.id.dynamic_list_name); + holder.location = v.findViewById(R.id.dynamic_list_sub_info); + holder.years = v.findViewById(R.id.dynamic_list_age); + holder.iv_sex = v.findViewById(R.id.iv_sex); + holder.info = v.findViewById(R.id.dynamic_list_message); + holder.giftLayout = v.findViewById(R.id.item_dynamic_gift_layout); + holder.getMenu = v.findViewById(R.id.dynamic_list_menu); + holder.imageListView1 = v.findViewById(R.id.dynamic_list_image_list_1); + holder.imageListView2 = v.findViewById(R.id.dynamic_list_image_list_2); + holder.imageListView3 = v.findViewById(R.id.dynamic_list_image_list_3); + holder.msgBtn = v.findViewById(R.id.msgBtn); + holder.commentCountLabel = v.findViewById(R.id.commentCountLabel); + holder.likeCountLabel = v.findViewById(R.id.likeCountLabel); + holder.likeImageView = v.findViewById(R.id.likeImageView); + holder.commentImageView = v.findViewById(R.id.commentImageView); + holder.realPeopleImageView = v.findViewById(R.id.realPeopleImageView); + holder.newPeopleImageView = v.findViewById(R.id.newPeopleImageView); + holder.rl_dynamic_item = v.findViewById(R.id.rl_dynamic_item); + return holder; + } + + class Holder { + SimpleDraweeView head; + TextView name; + TextView location; + TextView years; + ImageView iv_sex; + ExpandLayout info; + TextView commentCountLabel; + TextView likeCountLabel; + LinearLayout imageListView1; + LinearLayout imageListView2; + LinearLayout imageListView3; + View giftLayout; + ImageView getMenu; + ImageView msgBtn; + ImageView likeImageView; + ImageView commentImageView; + ImageView realPeopleImageView; + ImageView newPeopleImageView; + RelativeLayout rl_dynamic_item; + } + + public void delete(int index) { + mDynamicsItemList.remove(index); + deleteCount++; + notifyDataSetChanged(); + } + + public int getDeleteCount() { + return deleteCount; + } + + public void setDeleteCount(int deleteCount) { + this.deleteCount = deleteCount; + } + + private void startDisplayActivity(List dynamicImageList, View[] views, int currentPosition) { + String[] strings = new String[dynamicImageList.size()]; + for (int i = 0; i < dynamicImageList.size(); i++) { + strings[i] = ConstUrl.IMAGE_URL + dynamicImageList.get(i).getUrl(); + } + Diooto diooto = new Diooto(mContext) + .urls(strings) + .type(DiootoConfig.PHOTO) + .immersive(true) + .position(currentPosition, 0) + .views(views) + .loadPhotoBeforeShowBigImage(new Diooto.OnLoadPhotoBeforeShowBigImageListener() { + @Override + public void loadView(SketchImageView sketchImageView, int position) { +// Glide.with(context).load(normalImageUlr[position]).into(sketchImageView); +// sketchImageView.displayImage(normalImageUlr[position]); + sketchImageView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { +// Toast.makeText(mContext, "Long click", Toast.LENGTH_SHORT).show(); + return false; + } + }); + } + }) + .start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/DynamicsAdapter1.java b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/DynamicsAdapter1.java new file mode 100644 index 0000000..68199b1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/DynamicsAdapter1.java @@ -0,0 +1,604 @@ +package com.fengliyan.tianlesue.controller.dynamics.adapter; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; + +import com.facebook.drawee.generic.GenericDraweeHierarchy; +import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; +import com.facebook.drawee.generic.RoundingParams; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.dynamics.DynamicImage; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.utils.GlideImageLoader1; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.diooto.Diooto; +import com.fengliyan.tianlesue.view.diooto.config.DiootoConfig; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; +import com.fengliyan.tianlesue.view.dynamics.activity.DynamicDetailActivity; +import com.fengliyan.tianlesue.view.dynamics.activity.ImageDisplayActivity; +import com.fengliyan.tianlesue.view.dynamics.activity.QYPreviewVideoActivity; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.tianlesue.view.main.utils.UiUtils; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.sketch.SketchImageView; +import com.youth.banner.Banner; +import com.youth.banner.listener.OnBannerListener; +import com.zld.expandlayout.ExpandLayout; + +import java.util.ArrayList; +import java.util.List; + +public class DynamicsAdapter1 extends BaseAdapter { + private List mDynamicsItemList = new ArrayList<>(); + private Context mContext; + private OnThumbupClickedListener mListener; + private OnGiftSendListener mGiftListener; + private OnMenuClickListener mMenuClickListener; + private OnMenuDeleteClickListener mOnMunuDeleteClickListener; + public DynamicLikeCallback likeDynamicCallback; + public DynamicCommentCallback dynamicCommentCallback; + private OnDetailClickListener onDetailClicked; + private BaseMessageDialog mDialog; + private int deleteCount = 0; + private int selfID = SPUtils.getInt(BaseApplication.getInstance(), ConsUser.USER_ID); + private List bannerImages = new ArrayList<>(); + private boolean showBanner; + + public interface DynamicLikeCallback { + void likeDynamic(DynamicsItemBean bean); + } + + public interface DynamicCommentCallback { + void commentDynamic(DynamicsItemBean bean); + } + + public interface OnThumbupClickedListener { + void onClick(View v, String uid); + } + + public interface OnGiftSendListener { + void onSend(DynamicsItemBean bean, int quantity); + } + + public interface OnMenuClickListener { + void onMenuClicked(int position); + } + + public interface OnDetailClickListener { + void onDetailClicked(int position, String id); + } + + //删除动态接口 + public interface OnMenuDeleteClickListener { + void onMenuDelete(int position, List mDynamicsItemList); + } + + public void setOnThumbupClickedListener(OnThumbupClickedListener listener) { + mListener = listener; + } + + public void setOnGiftSendListener(OnGiftSendListener listener) { + mGiftListener = listener; + } + + public void setOnMenuClickListener(OnMenuClickListener listener) { + mMenuClickListener = listener; + } + + public void setOnMenuDeleteClickListener(OnMenuDeleteClickListener onMunuDeleteClickListener) { + mOnMunuDeleteClickListener = onMunuDeleteClickListener; + } + + public void setOnDetailClicked(OnDetailClickListener onDetailClicked) { + this.onDetailClicked = onDetailClicked; + } + + public DynamicsAdapter1(Context context) { + mContext = context; + } + + public void setList(List list) { + mDynamicsItemList = list; + } + + public List getmDynamicsItemList() { + return mDynamicsItemList; + } + + private int nnumber; + private String id = ""; + + public void setGiftCount(int number, String id) { + this.nnumber = number; + this.id = id; + } + + public void setBannerImages(List bannerImages, boolean showBanner) { + this.bannerImages = bannerImages; + this.showBanner = showBanner; + notifyDataSetChanged(); + } + + @Override + public int getCount() { + return mDynamicsItemList.size(); + } + + @Override + public Object getItem(int i) { + return mDynamicsItemList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + if (null == view) { + view = View.inflate(mContext, R.layout.item_dynamic_list1, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(R.id.tag_second); + } + final DynamicsItemBean bean = mDynamicsItemList.get(i); + if (i == 0 && showBanner && bannerImages != null && bannerImages.size() > 0) { + if (NoClearSPUtils.getInt(mContext, Constans.MARKET_STATUS) == 0 || SPUtils.getInt(mContext, ConsUser.TYPE) == 2) { + holder.image_banner.setVisibility(View.GONE); + } else { + holder.image_banner.setVisibility(View.VISIBLE); + holder.image_banner.setImages(bannerImages) + .setImageLoader(new GlideImageLoader1()) + .setOnBannerListener(new OnBannerListener() { + @Override + public void OnBannerClick(int position) { + int size = bannerImages.size(); + if (size != 0) { + int i = position % size; + JumpUtils.jump(bannerImages.get(i).getLink_type(), bannerImages.get(i).getLink_url(), mContext); + } + } + }) + .setDelayTime(3000) + .start(); + } + } else { + holder.image_banner.setVisibility(View.GONE); + } + + if (bean.getUser_id().equals(String.valueOf(selfID))) { + holder.msgBtn.setVisibility(View.INVISIBLE); + } else { + holder.msgBtn.setVisibility(View.VISIBLE); + } + holder.likeCountLabel.setText(bean.getLike_count() + ""); + holder.commentCountLabel.setText(bean.getComment_count() + ""); + final int index = i; + holder.name.setText(bean.getNickname()); + holder.head.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.newPeopleImageView.setVisibility(View.GONE); + holder.realPeopleImageView.setVisibility(View.GONE); + + if (bean.getGender() == 1) { + holder.realPeopleImageView.setVisibility(View.VISIBLE); + if (bean.getMark() == 2) { + holder.newPeopleImageView.setVisibility(View.VISIBLE); + } + Drawable drawableLeft = ContextCompat.getDrawable(mContext, R.mipmap.sex_girl); + drawableLeft.setBounds(0, 0, drawableLeft.getMinimumWidth(), drawableLeft.getMinimumHeight()); + holder.iv_sex.setBackgroundResource(R.drawable.shape_dynamic_age_women); + holder.iv_sex.setImageResource(R.mipmap.sex_girl); + holder.years.setBackgroundResource(R.drawable.shape_dynamic_age_women); + holder.years.setCompoundDrawables(drawableLeft, null, null, null); + } else { + if (bean.getMark() == 2) { + holder.newPeopleImageView.setVisibility(View.VISIBLE); + } + holder.iv_sex.setBackgroundResource(R.drawable.shape_dynamic_age); + holder.iv_sex.setImageResource(R.mipmap.sex_men); + holder.years.setBackgroundResource(R.drawable.shape_dynamic_age); + Drawable drawableLeft = ContextCompat.getDrawable(mContext, R.mipmap.sex_men); + drawableLeft.setBounds(0, 0, drawableLeft.getMinimumWidth(), drawableLeft.getMinimumHeight()); + holder.years.setCompoundDrawables(drawableLeft, null, null, null); + } + holder.years.setText(bean.getAge() + ""); + holder.location.setText(bean.getCity() + " | " + bean.getCreate_time()); +// holder.info.setText(bean.getContent()); + holder.info.setText(bean.getContent(), bean.getExpand(), new ExpandLayout.OnExpandListener() { + @Override + public void expandChange() { + bean.setExpand(!bean.getExpand()); + notifyDataSetChanged(); + } + }); + holder.msgBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + NimUIKit.startChat(bean.getUser_id(), mContext); + } + }); + holder.commentImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (dynamicCommentCallback != null) { + dynamicCommentCallback.commentDynamic(bean); + } else { + Intent intent = new Intent(mContext, DynamicDetailActivity.class); + intent.putExtra("dynamic_id", bean.getId()); + mContext.startActivity(intent); + } + } + }); + holder.getMenu.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (String.valueOf(SPUtils.getInt(mContext, ConsUser.USER_ID)).equals(mDynamicsItemList.get(index).getUser_id())) { + if (null != mOnMunuDeleteClickListener) { + + mOnMunuDeleteClickListener.onMenuDelete(index, mDynamicsItemList); + } + } else { + if (null != mMenuClickListener) { + mMenuClickListener.onMenuClicked(index); + } + } + } + }); + + holder.rl_dynamic_item.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != onDetailClicked) { + onDetailClicked.onDetailClicked(index, bean.getId()); + } + } + }); + addImageView(holder, bean.getImages()); + + + if (bean.getIs_like() == 1) { + holder.likeImageView.setImageResource(R.mipmap.feed_heart_); + } else { + holder.likeImageView.setImageResource(R.mipmap.feed_heart); + } + + holder.head.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", Integer.parseInt(bean.getUser_id())); + mContext.startActivity(intent); + } + }); + holder.likeImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (likeDynamicCallback != null) { + likeDynamicCallback.likeDynamic(bean); + } + + } + }); + + view.setTag(R.id.tag_second, holder); + return view; + } + + private int isLike; + + + private void addImageView(Holder holder, final List dynamicImageList) { + + holder.imageListView1.removeAllViews(); +// holder.imageListView2.removeAllViews(); + holder.imageListView2.setVisibility(View.GONE); + holder.imageListView3.removeAllViews(); + final List pathList = new ArrayList<>(); + if (null == dynamicImageList || dynamicImageList.size() == 0) { + return; + } + + if (1 == dynamicImageList.size()) { + GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder + .newInstance(mContext.getResources()).setRoundingParams(RoundingParams.fromCornersRadius(Utils.dip2px(mContext, 16))) + .build(); + DynamicImage image = dynamicImageList.get(0); + RelativeLayout container = new RelativeLayout(mContext); + final SimpleDraweeView photoView = new SimpleDraweeView(mContext); + container.addView(photoView); + DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); + int height = dm.heightPixels; + int width = dm.widthPixels; + int newWidth = 0; + int newHeight = 0; + if (image.getWidth() > image.getHeight()) { + newWidth = (int) (0.55 * width); + newHeight = (int) (newWidth * image.getHeight() / image.getWidth()); + } else { + newHeight = (int) (0.25 * height); + newWidth = (int) (newHeight * image.getWidth() / image.getHeight()); + } + ImageView imageview = new ImageView(mContext); + if (!TextUtils.isEmpty(image.getVideo_url())) { + imageview.setImageResource(R.mipmap.feed_play); + } + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(newWidth, newHeight); + RelativeLayout.LayoutParams containerPAram = new RelativeLayout.LayoutParams(newWidth, newHeight); + RelativeLayout.LayoutParams imageParam = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + imageParam.addRule(RelativeLayout.CENTER_IN_PARENT); + container.addView(imageview, imageParam); + container.setLayoutParams(containerPAram); + photoView.setLayoutParams(params); + photoView.setHierarchy(hierarchy); + photoView.setImageURI(StrU.getResourcePath(image.getUrl(), mContext)); + ((ViewGroup) holder.imageListView1).addView(container); + pathList.add(StrU.getResourcePath(image.getUrl(), mContext)); + photoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (TextUtils.isEmpty(image.getVideo_url())) { + View[] views = new View[dynamicImageList.size()]; + views[0] = photoView; + startDisplayActivity(dynamicImageList, views, 0); + } else { + Intent intent = new Intent(mContext, QYPreviewVideoActivity.class); + intent.putExtra("videoUrl", StrU.getResourcePath(image.getVideo_url(), mContext)); + mContext.startActivity(intent); + } + } + }); + } else if (2 == dynamicImageList.size()) { + holder.imageListView1.setWeightSum(2); + final View[] views = new View[dynamicImageList.size()]; + for (int i = 0; i < dynamicImageList.size(); i++) { + RoundingParams roundingParams; + if (i == 0) { + roundingParams = RoundingParams.fromCornersRadii(Utils.dip2px(mContext, 16), 0, 0, Utils.dip2px(mContext, 16)); + } else { + roundingParams = RoundingParams.fromCornersRadii(0, Utils.dip2px(mContext, 16), Utils.dip2px(mContext, 16), 0); + } + GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder + .newInstance(mContext.getResources()).setRoundingParams(roundingParams).build(); + DynamicImage image = dynamicImageList.get(i); + SimpleDraweeView photoView = new SimpleDraweeView(mContext); + LinearLayout.LayoutParams params = new LinearLayout + .LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + UiUtils.dp2px(mContext, 170)); + params.setMargins(5, 0, 5, 0); + params.weight = 1; + photoView.setLayoutParams(params); + photoView.setHierarchy(hierarchy); + photoView.setImageURI(StrU.getResourcePath(image.getUrl(), mContext)); + ((ViewGroup) holder.imageListView1).addView(photoView); + views[i] = photoView; + final int count = i; + pathList.add(StrU.getResourcePath(image.getUrl(), mContext)); + photoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startDisplayActivity(dynamicImageList, views, count); + } + }); + } +// } else if (4 == dynamicImageList.size()) { +// holder.imageListView1.setWeightSum(2); +//// holder.imageListView2.setWeightSum(2); +// final View[] views = new View[dynamicImageList.size()]; +// for (int i = 0; i < dynamicImageList.size(); i++) { +// GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder +// .newInstance(mContext.getResources()).setRoundingParams(RoundingParams.fromCornersRadius(Utils.dip2px(mContext, 6))) +// .build(); +// +// DynamicImage image = dynamicImageList.get(i); +// SimpleDraweeView photoView = new SimpleDraweeView(mContext); +// LinearLayout.LayoutParams params = new LinearLayout +// .LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, +// UiUtils.dp2px(mContext, 170)); +// params.setMargins(5, 0, 5, 0); +// params.weight = 1; +// photoView.setLayoutParams(params); +// photoView.setHierarchy(hierarchy); +// photoView.setImageURI(ConstUrl.IMAGE_URL + image.getUrl()); +// if (i < 2) { +// ((ViewGroup) holder.imageListView1).addView(photoView); +// } else { +// ((ViewGroup) holder.imageListView2).addView(photoView); +// } +// views[i] = photoView; +// final int count = i; +// pathList.add(ConstUrl.IMAGE_URL + image.getUrl()); +// photoView.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// startDisplayActivity(dynamicImageList, views, count); +// } +// }); +// } + } else { + holder.imageListView2.setVisibility(View.VISIBLE); + holder.dynamic_image1.setImageURI(StrU.getResourcePath(dynamicImageList.get(0).getUrl(), mContext)); + holder.dynamic_image2.setImageURI(StrU.getResourcePath(dynamicImageList.get(1).getUrl(), mContext)); + holder.dynamic_image3.setImageURI(StrU.getResourcePath(dynamicImageList.get(2).getUrl(), mContext)); + if (dynamicImageList.size() > 3) { + holder.dynamic_image_num.setText(dynamicImageList.size() + ""); + holder.dynamic_image_num.setVisibility(View.VISIBLE); + } else { + holder.dynamic_image_num.setVisibility(View.GONE); + } + + final View[] views = new View[dynamicImageList.size()]; + for (int i = 0; i < dynamicImageList.size(); i++) { + GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder + .newInstance(mContext.getResources()).setRoundingParams(RoundingParams.fromCornersRadius(Utils.dip2px(mContext, 6))) + .build(); + DynamicImage image = dynamicImageList.get(i); + SimpleDraweeView photoView = new SimpleDraweeView(mContext); + + DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); + int width = dm.widthPixels; + int measure = (((width - UiUtils.dp2px(mContext, 32)) - 20) / 3) - 5; + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(measure, measure); + params.setMargins(5, 0, 5, 0); + photoView.setLayoutParams(params); + photoView.setHierarchy(hierarchy); + photoView.setImageURI(StrU.getResourcePath(image.getUrl(), mContext)); + views[i] = photoView; + pathList.add(StrU.getResourcePath(image.getUrl(), mContext)); + } + holder.dynamic_image1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startDisplayActivity(dynamicImageList, views, 0); + } + }); + holder.dynamic_image2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startDisplayActivity(dynamicImageList, views, 1); + } + }); + holder.dynamic_image3.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startDisplayActivity(dynamicImageList, views, 2); + } + }); + } + } + + private void clickImage(ArrayList pathList, int innerCount) { + Intent intent = new Intent(mContext, ImageDisplayActivity.class); + intent.putStringArrayListExtra("urlList", pathList); + intent.putExtra("pageCount", innerCount); + mContext.startActivity(intent); + } + + private void startImageDisplaying(ArrayList url, String pageCount) { + Intent intent = new Intent(mContext, ImageDisplayActivity.class); + intent.putStringArrayListExtra("urlList", url); + intent.putExtra("pageCount", pageCount); + mContext.startActivity(intent); + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.image_banner = v.findViewById(R.id.image_banner); + holder.head = v.findViewById(R.id.dynamic_list_photo); + holder.name = v.findViewById(R.id.dynamic_list_name); + holder.location = v.findViewById(R.id.dynamic_list_sub_info); + holder.years = v.findViewById(R.id.dynamic_list_age); + holder.iv_sex = v.findViewById(R.id.iv_sex); + holder.info = v.findViewById(R.id.dynamic_list_message); + holder.giftLayout = v.findViewById(R.id.item_dynamic_gift_layout); + holder.getMenu = v.findViewById(R.id.dynamic_list_menu); + holder.imageListView1 = v.findViewById(R.id.dynamic_list_image_list_1); + holder.imageListView2 = v.findViewById(R.id.dynamic_list_image_list_2); + holder.dynamic_image1 = v.findViewById(R.id.dynamic_image1); + holder.dynamic_image2 = v.findViewById(R.id.dynamic_image2); + holder.dynamic_image3 = v.findViewById(R.id.dynamic_image3); + holder.dynamic_image_num = v.findViewById(R.id.dynamic_image_num); + holder.imageListView3 = v.findViewById(R.id.dynamic_list_image_list_3); + holder.msgBtn = v.findViewById(R.id.msgBtn); + holder.commentCountLabel = v.findViewById(R.id.commentCountLabel); + holder.likeCountLabel = v.findViewById(R.id.likeCountLabel); + holder.likeImageView = v.findViewById(R.id.likeImageView); + holder.commentImageView = v.findViewById(R.id.commentImageView); + holder.realPeopleImageView = v.findViewById(R.id.realPeopleImageView); + holder.newPeopleImageView = v.findViewById(R.id.newPeopleImageView); + holder.rl_dynamic_item = v.findViewById(R.id.rl_dynamic_item); + return holder; + } + + class Holder { + Banner image_banner; + SimpleDraweeView head; + TextView name; + TextView location; + TextView years; + ImageView iv_sex; + ExpandLayout info; + TextView commentCountLabel; + TextView likeCountLabel; + LinearLayout imageListView1; + ConstraintLayout imageListView2; + SimpleDraweeView dynamic_image1; + SimpleDraweeView dynamic_image2; + SimpleDraweeView dynamic_image3; + TextView dynamic_image_num; + LinearLayout imageListView3; + View giftLayout; + ImageView getMenu; + ImageView msgBtn; + ImageView likeImageView; + ImageView commentImageView; + ImageView realPeopleImageView; + ImageView newPeopleImageView; + RelativeLayout rl_dynamic_item; + } + + public void delete(int index) { + mDynamicsItemList.remove(index); + deleteCount++; + notifyDataSetChanged(); + } + + public int getDeleteCount() { + return deleteCount; + } + + public void setDeleteCount(int deleteCount) { + this.deleteCount = deleteCount; + } + + private void startDisplayActivity(List dynamicImageList, View[] views, int currentPosition) { + String[] strings = new String[dynamicImageList.size()]; + for (int i = 0; i < dynamicImageList.size(); i++) { + strings[i] = StrU.getResourcePath(dynamicImageList.get(i).getUrl(), mContext); + } + Diooto diooto = new Diooto(mContext) + .urls(strings) + .type(DiootoConfig.PHOTO) + .immersive(true) + .position(currentPosition, 0) + .views(views) + .loadPhotoBeforeShowBigImage(new Diooto.OnLoadPhotoBeforeShowBigImageListener() { + @Override + public void loadView(SketchImageView sketchImageView, int position) { +// Glide.with(context).load(normalImageUlr[position]).into(sketchImageView); +// sketchImageView.displayImage(normalImageUlr[position]); + sketchImageView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { +// Toast.makeText(mContext, "Long click", Toast.LENGTH_SHORT).show(); + return false; + } + }); + } + }) + .start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/ImageSlidePagerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/ImageSlidePagerAdapter.java new file mode 100644 index 0000000..0ea742a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/ImageSlidePagerAdapter.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.controller.dynamics.adapter; + + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; + +import com.fengliyan.tianlesue.view.dynamics.fragment.ImageSlideFragment; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by abby on 2017/7/1. + */ + +public class ImageSlidePagerAdapter extends FragmentStatePagerAdapter { + + private List mImagePath = new ArrayList<>(); + public ImageSlidePagerAdapter(FragmentManager fm, List imagePath) { + super(fm); + mImagePath.addAll(imagePath); + } + + @Override + public Fragment getItem(int position) { + return ImageSlideFragment.newInstance(mImagePath.get(position)); + } + + @Override + public int getCount() { + return mImagePath.size(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/MenuPopupItemAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/MenuPopupItemAdapter.java new file mode 100644 index 0000000..95c5e6d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/adapter/MenuPopupItemAdapter.java @@ -0,0 +1,50 @@ +package com.fengliyan.tianlesue.controller.dynamics.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.ryan.github.menupopupview.MenuPopupAdapter; + +import java.util.List; + +public class MenuPopupItemAdapter extends MenuPopupAdapter { + + private List mData; + + public MenuPopupItemAdapter(List data) { + mData = data; + } + + // 返回Item View视图对象 + @Override + public View getView(ViewGroup container, int position) { + View view = LayoutInflater.from(container.getContext()).inflate(R.layout.item_menu_popup, null); + TextView tv = view.findViewById(R.id.label); + tv.setText(getItem(position)); + return view; + } + + /** + * 获取item数 + * + * @return item数量 + */ + @Override + public int getItemCount() { + return mData.size(); + } + + /** + * 获取position位置的数据对象 + * + * @param position 位置索引 + * @return 数据对象 + */ + @Override + public String getItem(int position) { + return mData.get(position); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/manager/DynamicsManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/manager/DynamicsManager.java new file mode 100644 index 0000000..985b584 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/dynamics/manager/DynamicsManager.java @@ -0,0 +1,543 @@ +package com.fengliyan.tianlesue.controller.dynamics.manager; + +import android.text.TextUtils; + +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.dynamics.DynamicPostBean; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.model.dynamics.DynamicsListBean; +import com.fengliyan.tianlesue.model.dynamics.ImageUploadBean; +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean; +import com.fengliyan.tianlesue.model.login.bean.VipBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; + +import java.util.List; + +public class DynamicsManager { + public static void getDynamicList(BaseActivity activity, + final int type, + final int page, + final int limit, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_DYNAMIC_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("page", page + "") + .addParam("limit", limit + "") + .addParam("type", type + ""); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + public static void getMyDynamicCityList(BaseActivity activity, + final int type, + final int page, + final int limit, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_USER_MY_DYNAMIC; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("page", page + "") + .addParam("limit", limit + "") + .addParam("status", type + ""); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + + public static void getDynamicCityList(BaseActivity activity, + final int type, + final int page, + final int limit, + final String cityId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_DYNAMIC_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("page", page + "") + .addParam("limit", limit + "") + .addParam("type", type + "") + .addParam("city", cityId); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + public static void getUserDynamicList(BaseActivity activity, + final String userid, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_USER_DYNAMIC_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("user_id", userid + ""); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + public static void thumbup(BaseActivity activity, + final int type, + final String dynamicId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.THUMB_UP; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId + ""); + builder.addParam("type", type + ""); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + public static void follow(BaseActivity activity, + final String uid, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.FOLLOW; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("follow_uid", uid); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + public static void setVideoUrl(BaseActivity baseActivity, final String dynamicId, final String images, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(baseActivity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.UPLOAD_PHOTO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + builder.addParam("images", images); + builder.addParam("video_url", images); + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + public static void setImageUrl(BaseActivity baseActivity, final String dynamicId, + final String images, final String videoUrl, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(baseActivity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.UPLOAD_PHOTO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + builder.addParam("images", images); + if (!TextUtils.isEmpty(videoUrl)) { + builder.addParam("video_url", videoUrl); + } + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + + public static void uploadImage(BaseActivity activity, + final UploadFile[] uploadFiles, + final String type, + HttpUiCallBack> httpUiCallBack) { + HttpWithUiTask> task = new HttpWithUiTask>(activity, httpUiCallBack) { + @Override + protected HttpResult> run() throws Exception { + final String url = ConstUrl.UPLOADIMAGE; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType( + new TType>>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addUploadFiles(uploadFiles); + builder.addParam("type", type); + return builder.build().upload(); + } + }; + task.start(false); + } + + public static void uploadImageNew(BaseActivity activity, + final UploadFile[] uploadFiles, + final String type, + boolean refresh, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.UPLOADIMAGE1; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType( + new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addUploadFiles(uploadFiles); + builder.addParam("type", type); + return builder.build().upload(); + } + }; + task.start(refresh); + } + + public static void uploadVoice(BaseActivity activity, + final UploadFile[] uploadFiles, + final String type, + final int dur, + boolean refresh, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.UPLOADIMAGE1; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType( + new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addUploadFiles(uploadFiles); + builder.addParam("type", type); + builder.addParam("dur", String.valueOf(dur)); + return builder.build().upload(); + } + }; + task.start(refresh); + } + + public static void uploadImage(BaseActivity activity, + final UploadFile[] uploadFiles, + final String type, + boolean refresh, + HttpUiCallBack> httpUiCallBack) { + HttpWithUiTask> task = new HttpWithUiTask>(activity, httpUiCallBack) { + @Override + protected HttpResult> run() throws Exception { + final String url = ConstUrl.UPLOADIMAGE; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType( + new TType>>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addUploadFiles(uploadFiles); + builder.addParam("type", type); + return builder.build().upload(); + } + }; + task.start(refresh); + } + + public static void postDynamics(BaseActivity activity, + final String content, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.POST_DYNAMICS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + + if (null != content) { + builder.addParam("content", content); + } + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + public static void sendGifts(BaseActivity activity, + final String dynamicId, + final int number, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.DYNAMIC_SEND_GIFT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + builder.addParam("num", number + ""); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } + + //删除动态 + public static void deleteDynamics(BaseActivity activity, final String dynamicId, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.DELETE_DYNAMICS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + + } + + //点赞动态 + public static void likeDynamic(BaseActivity activity, final String dynamicId, boolean isLike, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.DYNAMIC_LIKE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + builder.addParam("type", isLike ? "0" : "1"); + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + + } + + // api/dynamic/detail + public static void dynamicDeteail(BaseActivity activity, final String dynamicId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.DYNAMIC_DETAIL; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.setShowWaitingDialog(false); + task.start(); + } + + public static void dynamicCommentList(BaseActivity activity, final String dynamic_id, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.COMMENT_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamic_id); + builder.addParam("page", page + ""); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.setShowWaitingDialog(false); + task.start(); + } + + public static void dynamicComment(BaseActivity activity, final String dynamicId, + String content, + String parentId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.ADDCOMMENT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + builder.addParam("content", content); + if (!TextUtils.isEmpty(parentId)) { + builder.addParam("parentId", parentId); + } + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.setShowWaitingDialog(false); + task.start(); + } + + public static void dynamicDelComment(BaseActivity activity, final String dynamicId, + String contentId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.DEL_COMMENT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + builder.addParam("content_id", contentId); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.setShowWaitingDialog(false); + task.start(); + } + + public static void commentLike(BaseActivity activity, final String dynamicId, + final String comment_id, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.COMMENT_LIKE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("dynamic_id", dynamicId); + builder.addParam("comment_id", comment_id); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.setShowWaitingDialog(false); + task.start(); + } + + /** + * @param activity + */ + public static void isVip(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_USER_IS_VIP; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * banner列表 + * + * @param activity + * @param httpUiCallBack + */ + public static void getBannerList(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.BANNER_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.setShowWaitingDialog(false); + task.start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/ActiveUpdateEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/ActiveUpdateEvent.java new file mode 100644 index 0000000..e160cc6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/ActiveUpdateEvent.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2019/1/5. + */ + +public class ActiveUpdateEvent { + private boolean isFront; + + public boolean isFront() { + return isFront; + } + + public ActiveUpdateEvent(boolean isFront) { + this.isFront = isFront; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/BeAnchorEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/BeAnchorEvent.java new file mode 100644 index 0000000..f66b166 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/BeAnchorEvent.java @@ -0,0 +1,11 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2018/11/21. + */ + +public class BeAnchorEvent { + public BeAnchorEvent() { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/DynamicEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/DynamicEvent.java new file mode 100644 index 0000000..e7074a7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/DynamicEvent.java @@ -0,0 +1,11 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2018/12/25. + */ + +public class DynamicEvent { + + public DynamicEvent() { + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/DynamicLikeEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/DynamicLikeEvent.java new file mode 100644 index 0000000..bb3f9e6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/DynamicLikeEvent.java @@ -0,0 +1,30 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2018/12/19. + */ + +public class DynamicLikeEvent { + + private int isLike; + private int likeNum; + private int from; + + public DynamicLikeEvent(int isLike, int likeNum, int from) { + this.isLike = isLike; + this.likeNum = likeNum; + this.from = from; + } + + public int isLike() { + return isLike; + } + + public int getLikeNum() { + return likeNum; + } + + public int getFrom() { + return from; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/InviteTypeEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/InviteTypeEvent.java new file mode 100644 index 0000000..e9de3fd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/InviteTypeEvent.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class InviteTypeEvent { + + private String type; + + public InviteTypeEvent(String type) { + this.type = type; + } + + public String getType() { + return type; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/KidEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/KidEvent.java new file mode 100644 index 0000000..8400475 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/KidEvent.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class KidEvent { + + private int type; + + public KidEvent(int type) { + this.type = type; + } + + public int getType() { + return type; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/NotificationEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/NotificationEvent.java new file mode 100644 index 0000000..0510ec7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/NotificationEvent.java @@ -0,0 +1,20 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +import com.fengliyan.tianlesue.model.main.VideoRequestBean; + +/** + * Created by zhangbin on 2018/12/24. + */ + +public class NotificationEvent { + + VideoRequestBean mVideoRequestBean; + + public NotificationEvent(VideoRequestBean mVideoRequestBean) { + this.mVideoRequestBean = mVideoRequestBean; + } + + public VideoRequestBean getCustomNotification() { + return mVideoRequestBean; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/PayEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/PayEvent.java new file mode 100644 index 0000000..af4f02a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/PayEvent.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2018/12/19. + */ + +public class PayEvent { + + private int errCode; + + public PayEvent(int errCode) { + this.errCode = errCode; + } + + public int getErrCode() { + return errCode; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/RegisterInfoEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/RegisterInfoEvent.java new file mode 100644 index 0000000..f8e3298 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/RegisterInfoEvent.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +import com.fengliyan.tianlesue.model.login.bean.LoginBean; + +/** + * Created by zhangbin on 2018/11/22. + * 资料完善后通知登录界面关闭 + */ + +public class RegisterInfoEvent { + + private LoginBean mBean; + private int newerStatus; + + public RegisterInfoEvent(LoginBean mBean) { + this.mBean = mBean; + } + + public RegisterInfoEvent(int newerStatus) { + this.newerStatus = newerStatus; + } + + public int getNewerStatus() { + return newerStatus; + } + + + public LoginBean getBean() { + return mBean; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/SocialToSettingEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/SocialToSettingEvent.java new file mode 100644 index 0000000..bcd2876 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/SocialToSettingEvent.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2018/12/18. + */ + +public class SocialToSettingEvent { + + private int type; + + public SocialToSettingEvent(int type) { + this.type = type; + } + + public int getType() { + return type; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/TurntableEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/TurntableEvent.java new file mode 100644 index 0000000..2bfb8cd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/TurntableEvent.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class TurntableEvent { + + private int type; + + public TurntableEvent(int type) { + this.type = type; + } + + public int getType() { + return type; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/UnReadCountEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/UnReadCountEvent.java new file mode 100644 index 0000000..e802f25 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/UnReadCountEvent.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2018/12/15. + */ + +public class UnReadCountEvent { + + private int count; + private String avatar; + + public UnReadCountEvent(int count, String avatar) { + this.count = count; + this.avatar = avatar; + } + + public int getCount() { + return count; + } + + public String getAvatar() { + return avatar; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/UpdateChatEvent.java b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/UpdateChatEvent.java new file mode 100644 index 0000000..4385131 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/eventBus/UpdateChatEvent.java @@ -0,0 +1,12 @@ +package com.fengliyan.tianlesue.controller.eventBus; + +/** + * Created by zhangbin on 2019/2/20. + * 通知刷新聊天消息 + */ + +public class UpdateChatEvent { + + public UpdateChatEvent() { + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/login/manager/ForgetManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/login/manager/ForgetManager.java new file mode 100644 index 0000000..776feb9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/login/manager/ForgetManager.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.controller.login.manager; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; + +/** + * Created by abby on 2018/4/16. + */ + +public class ForgetManager { + public static void forget(BaseActivity activity, + final String userName, + final String password, + final String authcode, + final boolean shouldShowWaitingView, + HttpUiCallBack httpUiCallBack){ + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.FORGET; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("mobile", userName) + .addParam("password", password) + .addParam("phone_code", authcode); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(shouldShowWaitingView); + task.start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/login/manager/LoginManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/login/manager/LoginManager.java new file mode 100644 index 0000000..c7b8a6e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/login/manager/LoginManager.java @@ -0,0 +1,122 @@ +package com.fengliyan.tianlesue.controller.login.manager; + +import android.text.TextUtils; + +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.login.bean.CustomerTipBean; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; + +/** + * Created by abby on 2018/4/7. + */ +public class LoginManager { + public static void login(BaseActivity activity, + final String userName, + final String password, + final boolean shouldShowWaitingView, String risk_engine_token, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.LOGIN; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("account", userName) + .addParam("password", password) + .addParam("x-risk-engine-token", risk_engine_token); +// builder.setExt(risk_engine_token); + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(shouldShowWaitingView); + task.start(); + } + + public static void thirdLogin(BaseActivity activity, final String platform, + final String openid, final String accessToken, + final String inviteCode, String risk_engine_token, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.THIRD; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("platform", platform) + .addParam("openid", openid) + .addParam("access_token", accessToken) + .addParam("x-risk-engine-token", risk_engine_token); +// builder.setExt(risk_engine_token); + + if (null != inviteCode) { + builder.addParam("invite_code", inviteCode); + } + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 手机验证码登录 + * + * @param activity + * @param mobile type = 2 时必传,手机号 + * @param phone_code type = 2 时必传,手机验证码 + * @param invite_code 通过openinstall获取的邀请码 + * @param httpUiCallBack + */ + public static void onSMSLogin(BaseActivity activity, + final String mobile, String phone_code, final String invite_code, String risk_engine_token, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.ONE_KEY_LOGIN; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("type", "2");//登录类型:1 = 运营商一键登录(默认)、2 = 手机验证码登录 + builder.addParam("mobile", mobile); + builder.addParam("phone_code", phone_code) + .addParam("x-risk-engine-token", risk_engine_token); + if (!TextUtils.isEmpty(invite_code)) { + builder.addParam("invite_code", invite_code); + } +// builder.setExt(risk_engine_token); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void getCustomerTip(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CUSTOMER_TIP; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/AllChannelRecyclerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/AllChannelRecyclerAdapter.java new file mode 100644 index 0000000..c40f03e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/AllChannelRecyclerAdapter.java @@ -0,0 +1,80 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.SkillAnchorBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +public class AllChannelRecyclerAdapter extends RecyclerView.Adapter { + private List mSkillList = new ArrayList<>(); + private Context mContext; + private OnItemClickListener mListener; + + public void setOnItemClickListener(OnItemClickListener listener) { + mListener = listener; + } + + public interface OnItemClickListener { + void onItemClicked(View v, int position); + } + + public AllChannelRecyclerAdapter(Context context) { + mContext = context; + } + + public void setSkillList(List list) { + mSkillList = list; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_all_channels, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + SkillAnchorBean bean = mSkillList.get(position); + Holder dataHolder = (Holder) holder; + final int finalPos = position; + dataHolder.mLogo.setImageURI(StrU.getResourcePath(bean.getIcon(), mContext)); + dataHolder.mName.setText(bean.getName()); + dataHolder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onItemClicked(view, finalPos); + } + } + }); + } + + @Override + public int getItemCount() { + return mSkillList.size(); + } + + public class Holder extends ViewHolder { + SimpleDraweeView mLogo; + TextView mName; + View mThisView; + + public Holder(Context context, View itemView) { + super(context, itemView); + mLogo = itemView.findViewById(R.id.all_channels_logo); + mName = itemView.findViewById(R.id.all_channels_name); + mThisView = itemView; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/AutoPollAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/AutoPollAdapter.java new file mode 100644 index 0000000..a1558e5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/AutoPollAdapter.java @@ -0,0 +1,79 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.model.main.SpeedInfoBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.List; + + +public class AutoPollAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mData; + + public AutoPollAdapter(Context mContext) { + this.mContext = mContext; + } + + public void setmData(List mData) { + this.mData = mData; + notifyDataSetChanged(); + } + + @NonNull + @Override + public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_auto_poll, parent, false); + BaseViewHolder holder = new BaseViewHolder(view); + return holder; + } + + @Override + public void onBindViewHolder(@NonNull BaseViewHolder baseViewHolder, int position) { + SimpleDraweeView iv_speed_avatar1 = baseViewHolder.getView(R.id.iv_speed_avatar1); + SimpleDraweeView iv_speed_avatar2 = baseViewHolder.getView(R.id.iv_speed_avatar2); + if (mData != null && mData.size() > 0) { + SpeedInfoBean.SpeedListBean bean = mData.get(position % mData.size()); + if (bean != null) { + iv_speed_avatar1.setImageURI(StrU.getResourcePath(bean.getIncome_avatar(), mContext)); + //女 + if (UserManager.getUserInfo().getGender() == 1) { + String text = bean.getIncome_nickname() + " 收入 " + bean.getCall_amount() + "金币"; + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#FFB444")), text.length() - bean.getCall_amount().length() - 2, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + baseViewHolder.setText(R.id.tv_auto_poll, spannableString); + iv_speed_avatar2.setVisibility(View.GONE); + } else { + String text = bean.getIncome_nickname() + " 和 " + bean.getPay_nickname() + " 连线成功了"; + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#C4C4C4")), bean.getIncome_nickname().length() + 1, bean.getIncome_nickname().length() + 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#C4C4C4")), text.length() - 5, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + baseViewHolder.setText(R.id.tv_auto_poll, spannableString); + iv_speed_avatar2.setVisibility(View.VISIBLE); + iv_speed_avatar2.setImageURI(StrU.getResourcePath(bean.getPay_avatar(), mContext)); + } + } + } + } + + @Override + public int getItemCount() { + return Integer.MAX_VALUE; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/BlackAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/BlackAdapter.java new file mode 100644 index 0000000..95c3544 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/BlackAdapter.java @@ -0,0 +1,146 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.settings.SocialBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/14. + */ + +public class BlackAdapter extends BaseAdapter { + private List mSocialBeans = new ArrayList<>(); + private Context mContext; + private OnButtonClickedListener mListener; + + public BlackAdapter(Context context) { + mContext = context; + } + + public void setOnButtonClickedListener(OnButtonClickedListener listener) { + mListener = listener; + } + + public void setSocialBeans(List beans) { + mSocialBeans = beans; + } + + public interface OnButtonClickedListener { + void onCliked(int position, String userId); + } + + @Override + public int getCount() { + return mSocialBeans.size(); + } + + @Override + public Object getItem(int i) { + return mSocialBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(final int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final SocialBean bean = mSocialBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_black_list, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + + if (0 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_pvip); + } else if (1 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_gvip); + } else { + holder.ivMemberSign.setVisibility(View.GONE); + } + + holder.photo.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.name.setText(bean.getNickname()); + if (bean.getGender() == 2) { + holder.age.setTextColor(mContext.getResources().getColor(R.color.mainColor)); + } else { + holder.age.setTextColor(Color.RED); + } + + holder.sub.setText(bean.getCity() + " | "); + holder.age.setText(bean.getAge() + "岁"); + holder.time.setText(bean.getCreate_time()); + + holder.focus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onCliked(i, mSocialBeans.get(i).getUserid() + ""); + } + } + }); + + holder.thisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUserid()); + mContext.startActivity(intent); + } + }); + + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.photo = v.findViewById(R.id.social_list_photo); + holder.name = v.findViewById(R.id.social_list_name); + holder.sub = v.findViewById(R.id.socical_list_location); + holder.age = v.findViewById(R.id.socical_list_age); + holder.time = v.findViewById(R.id.social_list_time); + holder.focus = v.findViewById(R.id.social_list_button); + holder.ivMemberSign = v.findViewById(R.id.iv_member_sign); +// holder.redPoint = v.findViewById(R.id.social_red_point); + holder.background = v.findViewById(R.id.socail_background); + holder.thisView = v; + + return holder; + } + + class Holder { + SimpleDraweeView photo; + TextView name; + TextView sub; + TextView age; + TextView time; + Button focus; + View background; + ImageView ivMemberSign; + // View redPoint; + View thisView; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/CardAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/CardAdapter.java new file mode 100644 index 0000000..0b4da6c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/CardAdapter.java @@ -0,0 +1,99 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.main.AnchorBean; + +import java.util.List; + + +/** + * Created by Shall on 2015-06-23. + */ +public class CardAdapter extends BaseAdapter { + private Context mContext; + private List mCardList; + private int mPosition; + + public CardAdapter(Context mContext, List mCardList) { + this.mContext = mContext; + this.mCardList = mCardList; + } + + @Override + public int getCount() { + return mCardList.size(); + } + + @Override + public Object getItem(int position) { + return mCardList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder = null; + if (convertView == null) { + LayoutInflater inflater = (LayoutInflater) mContext + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(R.layout.demo_item, parent, false); + holder = new ViewHolder(); + holder.mCardImageView = convertView.findViewById(R.id.helloText); + holder.mCardName = convertView.findViewById(R.id.card_name); + holder.tv_age = convertView.findViewById(R.id.tv_age); + holder.iv_tag = convertView.findViewById(R.id.iv_tag); + holder.ll_gender_and_age = convertView.findViewById(R.id.ll_gender_and_age); + holder.iv_gender = convertView.findViewById(R.id.iv_gender); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + AnchorBean luckItemBean = mCardList.get(position); + if (luckItemBean != null) { + holder.mCardImageView.setImageURI(ConstUrl.IMAGE_URL + luckItemBean.getCover()); + holder.mCardName.setText(luckItemBean.getNickname()); + holder.tv_age.setText(luckItemBean.getAge() + ""); + //1.女 2.男 + if (luckItemBean.getGender() == 2) { + holder.ll_gender_and_age.setBackgroundResource(R.drawable.shape_stroke_age); + holder.iv_gender.setImageResource(R.mipmap.sex_men1); + holder.tv_age.setTextColor(Color.parseColor("#002E9F")); + holder.iv_tag.setImageResource(R.mipmap.tag_supermember); + holder.iv_tag.setVisibility(View.GONE); + } else { + holder.ll_gender_and_age.setBackgroundResource(R.drawable.shape_stroke_age_women); + holder.iv_gender.setImageResource(R.mipmap.sex_girl1); + holder.tv_age.setTextColor(Color.parseColor("#F9528F")); + holder.iv_tag.setImageResource(R.mipmap.ag_real); + holder.iv_tag.setVisibility(View.VISIBLE); + } + } + return convertView; + } + + class ViewHolder { + TextView mCardName; + LinearLayout ll_gender_and_age; + ImageView iv_gender; + ImageView iv_tag; + TextView tv_age; + SimpleDraweeView mCardImageView; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ChannelAnchorRecyclerViewAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ChannelAnchorRecyclerViewAdapter.java new file mode 100644 index 0000000..812fa1e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ChannelAnchorRecyclerViewAdapter.java @@ -0,0 +1,86 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.content.Intent; +import androidx.recyclerview.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +public class ChannelAnchorRecyclerViewAdapter extends RecyclerView.Adapter { + private List anchorBeans = new ArrayList<>(); + private Context mContext; + private OnViewClickedListener mListener; + + public void setOnViewClickedListener(OnViewClickedListener listener) { + mListener = listener; + } + + public interface OnViewClickedListener { + void onViewClicked(View v, int position); + } + + public ChannelAnchorRecyclerViewAdapter(Context context) { + mContext = context; + } + + public void setAnchorListBeans(List beans) { + anchorBeans = beans; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_channel_anchor, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + final AnchorBean bean = anchorBeans.get(position); + Holder dataHolder = (Holder) holder; + dataHolder.mPhoto.setImageURI(StrU.getResourcePath(bean.getCover(), mContext)); + dataHolder.mCost.setText(anchorBeans.get(position).getNickname()); + dataHolder.mScore.setText("评分:" + anchorBeans.get(position).getGive_score()); + dataHolder.mLocation.setText(anchorBeans.get(position).getCity()); + dataHolder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUserid()); + mContext.startActivity(intent); + } + }); + } + + @Override + public int getItemCount() { + return anchorBeans.size(); + } + + public class Holder extends ViewHolder { + SimpleDraweeView mPhoto; + TextView mCost; + TextView mScore; + TextView mLocation; + View mThisView; + + public Holder(Context context, View itemView) { + super(context, itemView); + mPhoto = itemView.findViewById(R.id.channel_anchor_id_photo_1); + mCost = itemView.findViewById(R.id.channel_anchor_id_cost_1); + mScore = itemView.findViewById(R.id.channel_anchor_id_score_1); + mLocation = itemView.findViewById(R.id.channel_anchor_location_1); + mThisView = itemView; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ComplaintAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ComplaintAdapter.java new file mode 100644 index 0000000..986cf17 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ComplaintAdapter.java @@ -0,0 +1,88 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.CheckBox; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.ComplaintListBean; + +import java.util.ArrayList; +import java.util.List; + +public class ComplaintAdapter extends BaseAdapter { + private List mComplaintList = new ArrayList<>(); + private Context mContext; + private OnComplaintCheckerCheckedListener mListener; + + public interface OnComplaintCheckerCheckedListener{ + void onComplaintChecked(int index, boolean checker); + } + + public void setOnComplaintCheckerCheckedListener(OnComplaintCheckerCheckedListener listener){ + mListener = listener; + } + public ComplaintAdapter(Context context){ + mContext = context; + } + + public void setComplaintList(List beans){ + mComplaintList = beans; + } + + @Override + public int getCount() { + return mComplaintList.size(); + } + + @Override + public Object getItem(int i) { + return mComplaintList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(final int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final ComplaintListBean bean = mComplaintList.get(i); + if(view == null){ + view = View.inflate(mContext, R.layout.item_complaint, null); + holder = initView(view); + }else{ + holder = (Holder) view.getTag(); + } + + holder.mCheckBoxItem.setText(bean.getName()); + holder.mCheckBoxItem.setChecked(bean.isChecked()); + holder.mCheckBoxItem.setClickable(false); + holder.mCheckBoxView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if(null != mListener){ + mListener.onComplaintChecked(i, !bean.isChecked()); + } + } + }); + + view.setTag(holder); + return view; + } + + private Holder initView(View v){ + Holder holder = new Holder(); + holder.mCheckBoxItem = v.findViewById(R.id.complaint_check_box); + holder.mCheckBoxView = v.findViewById(R.id.complaint_view); + return holder; + } + + class Holder{ + View mCheckBoxView; + CheckBox mCheckBoxItem; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/FreeVideoAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/FreeVideoAdapter.java new file mode 100644 index 0000000..1f664ac --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/FreeVideoAdapter.java @@ -0,0 +1,84 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.FreeVideoBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +/** + * ying 2020/12/16 + * Describe : + */ + +public class FreeVideoAdapter extends RecyclerView.Adapter { + + private List mList = new ArrayList<>(); + private OnVideoClickListener mOnClickListener; + + public FreeVideoAdapter(RecyclerView recyclerView) { + recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext(), 2)); + recyclerView.setAdapter(this); + } + + + @Override + public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new MyHolder(View.inflate(parent.getContext(), R.layout.item_free_video, null)); + } + + @Override + public void onBindViewHolder(MyHolder holder, int position) { + Glide.with(holder.mImage.getContext()) + .load(StrU.getResourcePath(mList.get(position).avatar, holder.mImage.getContext())) + .into(holder.mImage); + holder.mVideo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mOnClickListener != null) + mOnClickListener.onVideo(mList.get(position).user_id); + } + }); + } + + @Override + public int getItemCount() { + return mList.size(); + } + + public void setList(List list) { + mList = list; + notifyDataSetChanged(); + } + + public void setOnClickListener(OnVideoClickListener onClickListener) { + mOnClickListener = onClickListener; + } + + public interface OnVideoClickListener { + void onVideo(int id); + } + + class MyHolder extends RecyclerView.ViewHolder { + + private final ImageView mImage; + private final ImageView mVideo; + + public MyHolder(View itemView) { + super(itemView); + mImage = itemView.findViewById(R.id.item_free_video_image); + mVideo = itemView.findViewById(R.id.item_free_video_video); + + } + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GenderUserAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GenderUserAdapter.java new file mode 100644 index 0000000..d84b1d8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GenderUserAdapter.java @@ -0,0 +1,113 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.settings.UserInfoBean; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +public class GenderUserAdapter extends BaseAdapter { + private List mUserList = new ArrayList<>(); + private Context mContext; + + public GenderUserAdapter(Context context) { + mContext = context; + } + + public void setUserList(List list) { + mUserList = list; + } + + @Override + public int getCount() { + return mUserList.size(); + } + + @Override + public Object getItem(int i) { + return mUserList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final UserInfoBean bean = mUserList.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_user_gender, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + if (0 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_pvip); + } else if (1 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_gvip); + } else { + holder.ivMemberSign.setVisibility(View.GONE); + } + + holder.photo.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.name.setText(bean.getNickname()); + holder.location.setText(bean.getCity() + " | " + bean.getAge() + "岁"); + holder.time.setText(bean.getDateline()); + + holder.rlItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mOnClickItemListener) + mOnClickItemListener.onClickItemListener(bean); + } + }); + + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.photo = v.findViewById(R.id.user_photo); + holder.name = v.findViewById(R.id.user_name); + holder.location = v.findViewById(R.id.user_location); + holder.time = v.findViewById(R.id.user_time); + holder.rlItem = v.findViewById(R.id.user_background); + holder.ivMemberSign = v.findViewById(R.id.iv_member_sign); + return holder; + } + + class Holder { + SimpleDraweeView photo; + TextView name; + TextView location; + TextView time; + ImageView ivMemberSign; + RelativeLayout rlItem; + } + + private OnClickItemListener mOnClickItemListener; + + public void setOnClickItemListener(OnClickItemListener onClickItemListener) { + mOnClickItemListener = onClickItemListener; + } + + public interface OnClickItemListener { + void onClickItemListener(UserInfoBean userInfoBean); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GiftReceivedAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GiftReceivedAdapter.java new file mode 100644 index 0000000..a0eee46 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GiftReceivedAdapter.java @@ -0,0 +1,77 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.GiftReceivedItemBean; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +public class GiftReceivedAdapter extends BaseAdapter { + private List mGiftReceivedList = new ArrayList<>(); + private Context mContext; + + public GiftReceivedAdapter(Context context) { + mContext = context; + } + + public void setGiftReceivedList(List giftReceivedList) { + mGiftReceivedList = giftReceivedList; + } + + @Override + public int getCount() { + return mGiftReceivedList.size(); + } + + @Override + public Object getItem(int i) { + return mGiftReceivedList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + GiftReceivedItemBean bean = mGiftReceivedList.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_gift_received, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + holder.mGiftLogo.setImageURI(StrU.getResourcePath(bean.getImg(), mContext)); + holder.mGiftName.setText(bean.getName()); + holder.mGiftNumber.setText(bean.getTotal() + "个"); + view.setTag(holder); + + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.mGiftLogo = v.findViewById(R.id.gift_received_logo); + holder.mGiftName = v.findViewById(R.id.gift_received_name); + holder.mGiftNumber = v.findViewById(R.id.gift_received_number); + + return holder; + } + + class Holder { + SimpleDraweeView mGiftLogo; + TextView mGiftName; + TextView mGiftNumber; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GroupCallAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GroupCallAdapter.java new file mode 100644 index 0000000..44ea059 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GroupCallAdapter.java @@ -0,0 +1,124 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.graphics.Color; +import androidx.recyclerview.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.GroupCallListBean; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/28. + */ + +public class GroupCallAdapter extends RecyclerView.Adapter { + + private Context mContext; + List mList = new ArrayList<>(); + private int id; + private int isSelect; //0未选中, 1选中 + + public GroupCallAdapter(Context context) { + mContext = context; + } + + public void setData(List mList) { + this.mList = mList; + } + + public void setSelect(int id, int isSelect) { + this.id = id; + this.isSelect = isSelect; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = View.inflate(mContext, R.layout.item_channel_group_call, null); + CallHolder holder = new CallHolder(v); + return holder; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + CallHolder callHolder = (CallHolder) holder; + final GroupCallListBean bean = mList.get(position); + callHolder.tvContent.setText(bean.getTitle()); + + if (id == bean.getId() && isSelect == 1) { + callHolder.tvSelect.setVisibility(View.VISIBLE); + }else { + callHolder.tvSelect.setVisibility(View.GONE); + } + + if (bean.getStatus() == 1) { + callHolder.tvContent.setTextColor(Color.parseColor("#333333")); + callHolder.tvTip.setVisibility(View.GONE); + }else { + callHolder.tvContent.setTextColor(Color.parseColor("#999999")); + callHolder.tvTip.setVisibility(View.VISIBLE); + if (bean.getStatus() == 0) { + callHolder.tvTip.setText("审核中"); + }else if (bean.getStatus() == 2) { + callHolder.tvTip.setText("审核不通过"); + } + } + + callHolder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mItemOnClickListener) { + mItemOnClickListener.itemOnClick(bean); + } + } + }); + + callHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + if (null != mItemOnClickListener) { + mItemOnClickListener.itemOnLongClick(position, bean); + } + return true; + } + }); + } + + @Override + public int getItemCount() { + return mList == null ? 0 : mList.size(); + } + + class CallHolder extends RecyclerView.ViewHolder { + + TextView tvContent; + TextView tvSelect; + TextView tvTip; + RelativeLayout rlItem; + + public CallHolder(View itemView) { + super(itemView); + tvContent = itemView.findViewById(R.id.tv_content); + tvSelect = itemView.findViewById(R.id.tv_select); + tvTip = itemView.findViewById(R.id.tv_tip); + rlItem = itemView.findViewById(R.id.rl_item); + } + } + + private ItemOnClickListener mItemOnClickListener; + + public void setItemOnClickListener(ItemOnClickListener itemOnClickListener) { + mItemOnClickListener = itemOnClickListener; + } + + public interface ItemOnClickListener { + void itemOnClick(GroupCallListBean bean); + void itemOnLongClick(int position, GroupCallListBean bean); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GuardRankAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GuardRankAdapter.java new file mode 100644 index 0000000..f4046d1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/GuardRankAdapter.java @@ -0,0 +1,135 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.GuardRankBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/12/17. + */ +public class GuardRankAdapter extends BaseAdapter { + private List mdGuardRankBeans = new ArrayList<>(); + private Context mContext; + + public GuardRankAdapter(Context context) { + mContext = context; + } + + public void setDatas(List beans) { + mdGuardRankBeans = beans; + } + + @Override + public int getCount() { + return mdGuardRankBeans.size(); + } + + @Override + public Object getItem(int i) { + return mdGuardRankBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(final int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final GuardRankBean bean = mdGuardRankBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_guard_list, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + holder.daka_rank_other_number.setText(bean.getNo() + ""); + holder.daka_rank_other_photo.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + + if (1 == bean.getNo()) { + holder.iv_tag.setVisibility(View.VISIBLE); + holder.iv_border.setVisibility(View.VISIBLE); + holder.iv_tag.setImageResource(R.drawable.ic_guard1); + } else if (2 == bean.getNo()) { + holder.iv_tag.setVisibility(View.VISIBLE); + holder.iv_border.setVisibility(View.VISIBLE); + holder.iv_tag.setImageResource(R.drawable.ic_guard2); + } else if (3 == bean.getNo()) { + holder.iv_tag.setVisibility(View.VISIBLE); + holder.iv_border.setVisibility(View.VISIBLE); + holder.iv_tag.setImageResource(R.drawable.ic_guard3); + } else { + holder.iv_tag.setVisibility(View.GONE); + holder.iv_border.setVisibility(View.GONE); + } + + holder.daka_rank_other_name.setText(bean.getNickname()); + setTextMoney(holder.daka_rank_other_cost, bean.getTotalMoney()); + +// holder.thisView.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// Intent intent = new Intent(mContext, MainPageActivity.class); +// intent.putExtra("userId", bean.getUser_id()); +// mContext.startActivity(intent); +// } +// }); + + view.setTag(holder); + return view; + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, double totalMoney) { + if (totalMoney >= 10000) { + double money = totalMoney / 10000; + view.setText(String.format("%.1f", money) + "万"); + } else { + view.setText(String.format("%.0f", totalMoney)); + } + } + + private Holder initView(View v) { + Holder holder = new Holder(); + + holder.daka_rank_other_number = v.findViewById(R.id.daka_rank_other_number); + holder.daka_rank_other_photo = v.findViewById(R.id.daka_rank_other_photo); + holder.iv_tag = v.findViewById(R.id.iv_tag); + holder.daka_rank_other_name = v.findViewById(R.id.daka_rank_other_name); + holder.daka_rank_other_cost = v.findViewById(R.id.daka_rank_other_cost); + holder.iv_border = v.findViewById(R.id.iv_border); + holder.thisView = v; + + return holder; + } + + class Holder { + + TextView daka_rank_other_number; + SimpleDraweeView daka_rank_other_photo; + ImageView iv_tag; + TextView daka_rank_other_name; + TextView daka_rank_other_cost; + ImageView iv_border; + View thisView; + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/LuckListAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/LuckListAdapter.java new file mode 100644 index 0000000..3ee395e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/LuckListAdapter.java @@ -0,0 +1,178 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.viewholder.BaseViewHolder; +import com.facebook.drawee.view.SimpleDraweeView; +import com.flyco.roundview.RoundTextView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +import org.jetbrains.annotations.NotNull; + +public class LuckListAdapter extends BaseQuickAdapter { + private static final String TAG = "LuckListAdapter"; + private OnClickedListener mClickListener; + private Context mContext; + + public interface OnClickedListener { + void onItemClick(int position, int type, ImageView imageView); + + void onSendGreedOne(AnchorBean luckItemBean, String useId); + } + + public void setOnClickedListener(OnClickedListener listener) { + mClickListener = listener; + } + + public LuckListAdapter(Context context) { + super(R.layout.item_luck_list); + mContext = context; + } + + @Override + protected void convert(@NotNull BaseViewHolder baseViewHolder, AnchorBean luckItemBean) { + SimpleDraweeView user_head = baseViewHolder.getView(R.id.user_head); + TextView tv_nick_name = baseViewHolder.getView(R.id.tv_nick_name); + TextView tv_user_info = baseViewHolder.getView(R.id.tv_user_info); + TextView tv_user_signer = baseViewHolder.getView(R.id.tv_user_signer); + TextView tv_city = baseViewHolder.getView(R.id.tv_city); + TextView tv_age = baseViewHolder.getView(R.id.tv_age); + ImageView iv_is_real_people = baseViewHolder.getView(R.id.iv_is_real_people); + ImageView iv_man_vip = baseViewHolder.getView(R.id.iv_man_vip); + ImageView iv_man_svip = baseViewHolder.getView(R.id.iv_man_svip); + ImageView iv_anchor_tag = baseViewHolder.getView(R.id.iv_anchor_tag); + LinearLayout ll_photos = baseViewHolder.getView(R.id.ll_photos); + TextView iv_luck_hi = baseViewHolder.getView(R.id.iv_luck_hi); + TextView iv_luck_msg = baseViewHolder.getView(R.id.iv_luck_msg); + LinearLayout lin_luck_item = baseViewHolder.getView(R.id.lin_luck_item); + RoundTextView iv_status = baseViewHolder.getView(R.id.iv_status); + + user_head.setImageURI(StrU.getResourcePath(luckItemBean.getCover(), mContext)); + + tv_user_info.setText(((!StrU.isEmpty(luckItemBean.getCity())) ? luckItemBean.getCity() + " | " : "") + luckItemBean.getAge() + "岁" + ((!StrU.isEmpty(luckItemBean.getJob())) ? " | " + luckItemBean.getJob() : "")); + if (!StrU.isEmpty(luckItemBean.getSignature())) { + tv_user_signer.setText(luckItemBean.getSignature()); + } else { + tv_user_signer.setText(""); + } + + tv_nick_name.setText(luckItemBean.getNickname()); + tv_city.setText(luckItemBean.getCity()); + tv_age.setText(luckItemBean.getAge() + ""); + if (luckItemBean.getOnline_status() == 1) { + iv_status.setVisibility(View.VISIBLE); + } else { + iv_status.setVisibility(View.GONE); + } + +// List imagesList = new ArrayList<>(); +// if (!TextUtils.isEmpty(luckItemBean.getCover_video())) { +// imagesList.add(luckItemBean.getCover_video()); +// } +// if (luckItemBean.getImg_list() != null && luckItemBean.getImg_list().size() > 0) { +// imagesList.addAll(luckItemBean.getImg_list()); +// } +// if (imagesList.size() > 0) { +// ll_photos.removeAllViews(); +// ll_photos.setVisibility(View.VISIBLE); +// //最多只展示3张照片,包括封面视频在内 +// for (int i = 0; i < Math.min(imagesList.size(), 3); i++) { +// View view = View.inflate(mContext, R.layout.item_luck_img_list, null); +// SimpleDraweeView iv_photo = view.findViewById(R.id.iv_photo); +// ImageView iv_luck_play = view.findViewById(R.id.iv_luck_play); +//// iv_photo.setImageURI(StrU.getResourcePath(imagesList.get(i), mContext)); +// GlideUtils.loadImage(iv_photo, StrU.getResourcePath(imagesList.get(i), mContext), UiUtils.dp2px(mContext, 2), 0); +//// Glide.with(mContext).load(StrU.getResourcePath(imagesList.get(i), mContext)) +//// .apply(new RequestOptions() +//// .error(R.drawable.nim_default_img_failed) +//// .dontAnimate()) +//// .into(iv_photo); +// if (!TextUtils.isEmpty(luckItemBean.getCover_video()) && i == 0) { +// iv_luck_play.setVisibility(View.VISIBLE); +// } else { +// iv_luck_play.setVisibility(View.GONE); +// } +// ll_photos.addView(view); +// } +// } else { +// ll_photos.setVisibility(View.GONE); +// } + + if (luckItemBean.getGender() == 2) { + iv_is_real_people.setVisibility(View.GONE); + tv_age.setBackgroundResource(R.drawable.bg_btn_man1); + tv_age.setTextColor(ContextCompat.getColor(mContext, R.color.E9F)); + tv_age.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.mipmap.sex_men1), null, null, null); + //是否是会员 + if (luckItemBean.getVip() == 0) { + iv_man_vip.setVisibility(View.VISIBLE); + iv_man_svip.setVisibility(View.GONE); + } else if (luckItemBean.getVip() == 1) { + iv_man_vip.setVisibility(View.GONE); + iv_man_svip.setVisibility(View.VISIBLE); + } else { + iv_man_vip.setVisibility(View.GONE); + iv_man_svip.setVisibility(View.GONE); + } + } else { + iv_is_real_people.setVisibility(View.VISIBLE); + tv_age.setBackgroundResource(R.drawable.bg_btn_woman1); + tv_age.setTextColor(ContextCompat.getColor(mContext, R.color.F9528F)); + tv_age.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.icon_women1), null, null, null); + iv_man_vip.setVisibility(View.GONE); + iv_man_svip.setVisibility(View.GONE); + + if (luckItemBean.getAnchor_tag() == 1) { + iv_anchor_tag.setVisibility(View.VISIBLE); + iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag1); + } else if (luckItemBean.getAnchor_tag() == 2) { + iv_anchor_tag.setVisibility(View.VISIBLE); + iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag2); + } else { + iv_anchor_tag.setVisibility(View.GONE); + } + } + + //招呼私信 + if (UserManager.getUserInfo().getGender() == 2) {//男 + iv_luck_msg.setVisibility(View.VISIBLE); + iv_luck_hi.setVisibility(View.GONE); + } else { + if (luckItemBean.getGreet_status() == 1) { + iv_luck_hi.setVisibility(View.VISIBLE); + iv_luck_msg.setVisibility(View.GONE); + } else { + iv_luck_hi.setVisibility(View.GONE); + iv_luck_msg.setVisibility(View.VISIBLE); + } + } + iv_luck_hi.setOnClickListener(v -> { + if (mClickListener != null) { + if (StrU.isFastClick()) { + mClickListener.onSendGreedOne(luckItemBean, luckItemBean.getUserid() + ""); + } + } + }); + iv_luck_msg.setOnClickListener(v -> { + NimUIKit.startP2PSession(mContext, luckItemBean.getUserid() + ""); + }); + lin_luck_item.setOnClickListener(v -> { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", luckItemBean.getUserid()); + mContext.startActivity(intent); + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainChannelAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainChannelAdapter.java new file mode 100644 index 0000000..99f7f18 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainChannelAdapter.java @@ -0,0 +1,142 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2018/12/7. + */ + +public class MainChannelAdapter extends RecyclerView.Adapter { + + private List anchorBeans = new ArrayList<>(); + + private Context context; + private int[] mImage_bg; + + public boolean isShowNewPeople() { + return showNewPeople; + } + + public void setShowNewPeople(boolean showNewPeople) { + this.showNewPeople = showNewPeople; + } + + private boolean showNewPeople; + + public MainChannelAdapter(Context context, int[] mImage_bg) { + this.context = context; + this.mImage_bg = mImage_bg; + } + + public void setAnchorListBeans(List beans) { + anchorBeans = beans; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = View.inflate(context, R.layout.item_channel_anchor, null); + RecyclerView.ViewHolder holder = new ChannelHolder(view); + return holder; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder instanceof ChannelHolder) { + setMainChannel((ChannelHolder) holder, position); + } + } + + private void setMainChannel(ChannelHolder holder, int position) { + final AnchorBean bean = anchorBeans.get(position); + + int x = (int) (Math.random() * 6); +// holder.mPhoto.setBackgroundColor(mImage_bg[x]); + holder.mPhoto.setImageURI(StrU.getResourcePath(bean.getCover(), context)); + +// RequestOptions requestOptions = new RequestOptions(); +// requestOptions +// .placeholder(mImage_bg[x]) +// .transform(new GlideRoundTransform2(context, 32)); +// Glide.with(context).load(ConstUrl.IMAGE_URL + bean.getCover()) +// .apply(requestOptions) +// .into(holder.mPhoto); + holder.mCost.setText(bean.getNickname()); + holder.mScore.setText("评分:" + bean.getGive_score()); +// holder.mScore.setText(bean.getAge() + "岁"); + holder.mLocation.setText(bean.getCity()); + if (bean.getAnchor_tag() == 1) { + holder.iv_anchor_tag.setVisibility(View.VISIBLE); + holder.iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag1); + holder.newPeopleImageView.setVisibility(View.INVISIBLE); + } else if (bean.getAnchor_tag() == 2) { + holder.iv_anchor_tag.setVisibility(View.VISIBLE); + holder.iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag2); + holder.newPeopleImageView.setVisibility(View.INVISIBLE); + } else { + holder.iv_anchor_tag.setVisibility(View.GONE); + if (showNewPeople) { + if (bean.getMark() == 2) { + holder.newPeopleImageView.setVisibility(View.VISIBLE); + } else { + holder.newPeopleImageView.setVisibility(View.INVISIBLE); + } + } + } + holder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", bean.getUserid()); + context.startActivity(intent); + } + }); + } + + @Override + public int getItemCount() { + return anchorBeans.size(); + } + + @Override + public int getItemViewType(int position) { + return 0; + } + + class ChannelHolder extends RecyclerView.ViewHolder { + + SimpleDraweeView mPhoto; + ImageView newPeopleImageView; + TextView mCost; + TextView mScore; + TextView mLocation; + ImageView iv_anchor_tag; + View mThisView; + + public ChannelHolder(View itemView) { + super(itemView); + mPhoto = itemView.findViewById(R.id.channel_anchor_id_photo_1); + mCost = itemView.findViewById(R.id.channel_anchor_id_cost_1); + mScore = itemView.findViewById(R.id.channel_anchor_id_score_1); + mLocation = itemView.findViewById(R.id.channel_anchor_location_1); + newPeopleImageView = itemView.findViewById(R.id.newPeopleImageView); + iv_anchor_tag = itemView.findViewById(R.id.iv_anchor_tag); + mThisView = itemView; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainChannelAdapter1.kt b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainChannelAdapter1.kt new file mode 100644 index 0000000..c8b337a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainChannelAdapter1.kt @@ -0,0 +1,191 @@ +package com.fengliyan.tianlesue.controller.main.adapter + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.CountDownTimer +import android.text.TextUtils +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import com.chad.library.adapter.base.BaseDelegateMultiAdapter +import com.chad.library.adapter.base.delegate.BaseMultiTypeDelegate +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.facebook.drawee.view.SimpleDraweeView +import com.google.android.exoplayer2.DefaultRenderersFactory +import com.google.android.exoplayer2.ExoPlayer +import com.google.android.exoplayer2.Player +import com.google.android.exoplayer2.SimpleExoPlayer +import com.google.android.exoplayer2.ui.PlayerView +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.model.main.AnchorBean +import com.fengliyan.tianlesue.utils.GlideUtils +import com.fengliyan.tianlesue.utils.ProgressView +import com.fengliyan.tianlesue.utils.StrU +import com.fengliyan.tianlesue.view.main.MainPageActivity +import com.fengliyan.tianlesue.view.main.utils.DefaultExoConfig + +class MainChannelAdapter1(private val mContext: Context, val key: String) : + BaseDelegateMultiAdapter() { + var showNewPeople: Boolean = false + var isPlay: Boolean = false + private var mCallCountDownTimer: CountDownTimer? = null + var onPlay: OnPlay? = null + var player: ExoPlayer? = null + + interface OnPlay { + fun getVideo(data: AnchorBean) + fun goPlayVideoList() + } + + init { + setMultiTypeDelegate(object : BaseMultiTypeDelegate() { + override fun getItemType( + data: List, + position: Int + ): Int { + return if (data[position].isVideo) { + 1 + } else { + 0 + } + } + }) + getMultiTypeDelegate()?.addItemType(0, R.layout.item_channel_anchor) + getMultiTypeDelegate()?.addItemType(1, R.layout.item_channel_anchor1) + } + + override fun convert(holder: BaseViewHolder, item: AnchorBean) { + when (holder.itemViewType) { + 0 -> { + val mPhoto = holder.getView(R.id.channel_anchor_id_photo_1) + val mCost = holder.getView(R.id.channel_anchor_id_cost_1) + val mScore = holder.getView(R.id.channel_anchor_id_score_1) + val mLocation = holder.getView(R.id.channel_anchor_location_1) + val newPeopleImageView = holder.getView(R.id.newPeopleImageView) + val iv_anchor_tag = holder.getView(R.id.iv_anchor_tag) + mPhoto.setImageURI(StrU.getResourcePath(item.cover, context)) + mCost.text = item.nickname + mScore.text = "评分:" + item.give_score + mLocation.text = item.city + when (item.anchor_tag) { + 1 -> { + iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag1) + iv_anchor_tag.visibility = View.VISIBLE + newPeopleImageView.visibility = View.INVISIBLE + } + 2 -> { + iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag2) + iv_anchor_tag.visibility = View.VISIBLE + newPeopleImageView.visibility = View.INVISIBLE + } + else -> { + iv_anchor_tag.visibility = View.GONE + if (showNewPeople) { + if (item.mark == 2) { + newPeopleImageView.visibility = View.VISIBLE + } else { + newPeopleImageView.visibility = View.INVISIBLE + } + } + } + } + holder.itemView.setOnClickListener(View.OnClickListener { + val intent = Intent(context, MainPageActivity::class.java) + intent.putExtra("userId", item.userid) + context.startActivity(intent) + }) + } + + 1 -> { + val iv_avatar = holder.getView(R.id.iv_avatar) + val mVideo = holder.getView(R.id.video_player) + val mProgress = holder.getView(R.id.progress) + val tv_video = holder.getView(R.id.tv_video) + if (!isPlay) { + if (mCallCountDownTimer == null) { + mCallCountDownTimer = object : CountDownTimer(15000, 1000) { + override fun onTick(millisUntilFinished: Long) { + } + + override fun onFinish() { + if (player?.playWhenReady == true) { + player?.playWhenReady = false + player?.release() + } +// mVideo.onVideoPause() + isPlay = false + onPlay?.getVideo(item) + } + } + } + mCallCountDownTimer?.cancel() + mCallCountDownTimer?.start() + player?.playWhenReady = false + player?.release() + if (mProgress.animator != null) { + mProgress.animator.cancel() + } + if (!TextUtils.isEmpty(item.cover_video)) { + iv_avatar.visibility = View.GONE + iv_avatar.setImageResource(0) + player = SimpleExoPlayer.Builder( + context, + DefaultRenderersFactory(context).setEnableDecoderFallback(true) + ).build() + mVideo.player = player + player?.repeatMode = Player.REPEAT_MODE_ONE + player?.audioComponent?.volume = 0f + DefaultExoConfig(mContext).createMediaSource( + Uri.parse( + StrU.getResourcePath( + item.cover_video, + mContext + ) + ) + ) + ?.let { player?.setMediaSource(it) } + player?.prepare() + player?.playWhenReady = true + +// GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL) +// mVideo.key = key +// mVideo.isLooping = true +// mVideo.setVideoAllCallBack(object : GSYSampleCallBack() { +// override fun onPrepared(url: String, vararg objects: Any) { +// super.onPrepared(url, *objects) +// mVideo.gsyVideoManager.player.setNeedMute(true) +//// GSYVideoManager.instance().isNeedMute = true +// } +// }) +// mVideo.setUp(StrU.getResourcePath(item.cover_video, mContext), true, "") +// mVideo.startPlayLogic() + } else { + iv_avatar.visibility = View.VISIBLE + GlideUtils.showImage(mContext, iv_avatar, item.cover) + } + isPlay = true + mProgress.setRadius(36f) + mProgress.post(Runnable { + //设置进度条长度 默认px + mProgress.progress = mProgress.measuredWidth.toFloat() + //设置动画时间 + mProgress.setDuration(15000) + mProgress.startAnim() + }) + } + holder.itemView.setOnClickListener(View.OnClickListener { + val intent = Intent(context, MainPageActivity::class.java) + intent.putExtra("userId", item.userid) + context.startActivity(intent) + }) + + tv_video.setOnClickListener { + onPlay?.goPlayVideoList() +// val intent = Intent(context, PlayVideoActivity1::class.java) +// context.startActivity(intent) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainViewPagerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainViewPagerAdapter.java new file mode 100644 index 0000000..839e21e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MainViewPagerAdapter.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; + +import java.util.List; + +/** + * Created by ChenQihong on 2017/1/5. + */ + +public class MainViewPagerAdapter extends FragmentPagerAdapter { + + private List mFragmentList; + public MainViewPagerAdapter(FragmentManager fm, List fragmentList){ + super(fm); + mFragmentList = fragmentList; + } + + @Override + public Fragment getItem(int position) { + return mFragmentList.get(position); + } + + @Override + public int getCount() { + return mFragmentList.size(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MsgCallListAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MsgCallListAdapter.java new file mode 100644 index 0000000..ff9b576 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/MsgCallListAdapter.java @@ -0,0 +1,69 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.content.Intent; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.viewholder.BaseViewHolder; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.settings.greeting.TextGrettingListActivity; + +import org.jetbrains.annotations.NotNull; + +public class MsgCallListAdapter extends BaseQuickAdapter { + private static final String TAG = "MsgCallListAdapter"; + private OnClickedListener mClickListener; + private Context mContext; + + public interface OnClickedListener { + void onSendCall(String content); + } + + public void setOnClickedListener(OnClickedListener listener) { + mClickListener = listener; + } + + public MsgCallListAdapter(Context context) { + super(R.layout.item_msg_call_list); + mContext = context; + } + + @Override + protected void convert(@NotNull BaseViewHolder baseViewHolder, String content) { + TextView tv_call_name = baseViewHolder.getView(R.id.tv_call_name); + ImageView iv_msg_call_add = baseViewHolder.getView(R.id.iv_msg_call_add); + if (!StrU.isEmpty(content)) { + tv_call_name.setText(content); + tv_call_name.setVisibility(View.VISIBLE); + iv_msg_call_add.setVisibility(View.GONE); + } else { + tv_call_name.setVisibility(View.GONE); + iv_msg_call_add.setVisibility(View.VISIBLE); + } + tv_call_name.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (StrU.isFastClick()) { + if (mClickListener != null) { + mClickListener.onSendCall(content); + } + } + } + }); + + iv_msg_call_add.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Log.i("info", "onClick: --------->"); + if (StrU.isFastClick()) { + mContext.startActivity(new Intent(mContext, TextGrettingListActivity.class)); + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/OneKeyAttentionAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/OneKeyAttentionAdapter.java new file mode 100644 index 0000000..70f9c0d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/OneKeyAttentionAdapter.java @@ -0,0 +1,97 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import androidx.recyclerview.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.model.main.AttentionBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/10. + */ + +public class OneKeyAttentionAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List recommendAttentionList = new ArrayList<>(); + + public OneKeyAttentionAdapter(Context context) { + mContext = context; + } + + public void setRecommendAttentionList(List recommendAttentionList) { + this.recommendAttentionList = recommendAttentionList; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_recommend_attention, null); + return new AttentionHolder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + AttentionHolder attentionHolder = (AttentionHolder) holder; + AttentionBean attentionBean = recommendAttentionList.get(position); + attentionHolder.mTvName.setText(attentionBean.getNickname()); +// attentionHolder.mAvatar.setImageURI(ConstUrl.IMAGE_URL + attentionBean.getCover()); + attentionHolder.mAvatar.loadAvatar(StrU.getResourcePath(attentionBean.getCover(), mContext)); + + + if (attentionBean.getSelect() == 0) { + attentionHolder.mIvSelect.setVisibility(View.VISIBLE); + } else { + attentionHolder.mIvSelect.setVisibility(View.INVISIBLE); + } + + final int finalPos = position; + attentionHolder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mOnClickItem) { + mOnClickItem.onClickItem(finalPos); + } + } + }); + } + + @Override + public int getItemCount() { + return recommendAttentionList == null ? 0 : recommendAttentionList.size(); + } + + public class AttentionHolder extends ViewHolder { + + TextView mTvName; + HeadImageView mAvatar; + ImageView mIvSelect; + + public AttentionHolder(Context context, View itemView) { + super(context, itemView); + mAvatar = itemView.findViewById(R.id.item_sv_avatar); + mTvName = itemView.findViewById(R.id.tv_name); + mIvSelect = itemView.findViewById(R.id.item_iv_select); + + } + } + + private OnClickItem mOnClickItem; + + public void setOnClickItem(OnClickItem onClickItem) { + mOnClickItem = onClickItem; + } + + public interface OnClickItem { + void onClickItem(int position); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/Recommend1ListAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/Recommend1ListAdapter.java new file mode 100644 index 0000000..46d1f18 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/Recommend1ListAdapter.java @@ -0,0 +1,152 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.AnchorListBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/18. + */ + +public class Recommend1ListAdapter extends BaseAdapter { + + private List anchorListBeans = new ArrayList<>(); + private Context mContext; + private int[] mImage_bg; + + public Recommend1ListAdapter(Context context, int[] mImage_bg) { + mContext = context; + this.mImage_bg = mImage_bg; + } + + public void setAnchorListBeans(List listBeans) { + anchorListBeans = listBeans; + } + + @Override + public int getCount() { + return anchorListBeans.size(); + } + + @Override + public Object getItem(int i) { + return anchorListBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + AnchorListBean bean = anchorListBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_channel_recommend1, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + holder.mTitle.setText(bean.getSkill_name()); + final List anchors = bean.getAnchors(); + for (int index = 0; index < holder.mRecommendView.length; index++) { + holder.mRecommendView[index].setVisibility(View.INVISIBLE); + } + + for (int index = 0; index < holder.mRecommendParentView.length; index++) { + holder.mRecommendParentView[index].setVisibility(View.GONE); + } + + for (int index = 0; index < anchors.size(); index++) { + final AnchorBean anchor = anchors.get(index); + int x = (int) (Math.random() * 6); + holder.mPhoto[index].setBackgroundColor(mImage_bg[x]); +// holder.mPhoto[index].setImageURI(ConstUrl.IMAGE_URL + anchor.getCover()); + Glide.with(mContext).load(StrU.getResourcePath(anchor.getCover(), mContext)).into(holder.mPhoto[index]); + holder.mPhoto[index].setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", anchor.getUserid()); + mContext.startActivity(intent); + } + }); + + holder.mCost[index].setText(anchor.getNickname()); + holder.mScore[index].setText("评分" + anchor.getGive_score() + ""); + holder.mLocation[index].setText(anchor.getCity()); + holder.mRecommendView[index].setVisibility(View.VISIBLE); + } + + if (anchors.size() > 0) { + holder.mRecommendParentView[0].setVisibility(View.VISIBLE); + } + + if (anchors.size() > 2) { + holder.mRecommendParentView[1].setVisibility(View.VISIBLE); + } + + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.mTitle = v.findViewById(R.id.channel_recommend_title); + holder.mRecommendParentView = new View[2]; + holder.mRecommendParentView[0] = v.findViewById(R.id.channel_recommend_parent_1); + holder.mRecommendParentView[1] = v.findViewById(R.id.channel_recommend_parent_2); + holder.mRecommendView = new View[4]; + holder.mRecommendView[0] = v.findViewById(R.id.channel_recommend_id_1); + holder.mRecommendView[1] = v.findViewById(R.id.channel_recommend_id_2); + holder.mRecommendView[2] = v.findViewById(R.id.channel_recommend_id_3); + holder.mRecommendView[3] = v.findViewById(R.id.channel_recommend_id_4); + holder.mPhoto = new SimpleDraweeView[4]; + holder.mPhoto[0] = v.findViewById(R.id.channel_recommend_id_photo_1); + holder.mPhoto[1] = v.findViewById(R.id.channel_recommend_id_photo_2); + holder.mPhoto[2] = v.findViewById(R.id.channel_recommend_id_photo_3); + holder.mPhoto[3] = v.findViewById(R.id.channel_recommend_id_photo_4); + holder.mCost = new TextView[4]; + holder.mCost[0] = v.findViewById(R.id.channel_recommend_id_cost_1); + holder.mCost[1] = v.findViewById(R.id.channel_recommend_id_cost_2); + holder.mCost[2] = v.findViewById(R.id.channel_recommend_id_cost_3); + holder.mCost[3] = v.findViewById(R.id.channel_recommend_id_cost_4); + holder.mScore = new TextView[4]; + holder.mScore[0] = v.findViewById(R.id.channel_recommend_id_score_1); + holder.mScore[1] = v.findViewById(R.id.channel_recommend_id_score_2); + holder.mScore[2] = v.findViewById(R.id.channel_recommend_id_score_3); + holder.mScore[3] = v.findViewById(R.id.channel_recommend_id_score_4); + holder.mLocation = new TextView[4]; + holder.mLocation[0] = v.findViewById(R.id.channel_recommend_location_1); + holder.mLocation[1] = v.findViewById(R.id.channel_recommend_location_2); + holder.mLocation[2] = v.findViewById(R.id.channel_recommend_location_3); + holder.mLocation[3] = v.findViewById(R.id.channel_recommend_location_4); + return holder; + } + + class Holder { + TextView mTitle; + View[] mRecommendParentView; + View[] mRecommendView; + SimpleDraweeView[] mPhoto; + TextView[] mCost; + TextView[] mScore; + TextView[] mLocation; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/RecommendListAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/RecommendListAdapter.java new file mode 100644 index 0000000..12ffa9c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/RecommendListAdapter.java @@ -0,0 +1,147 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.AnchorListBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +public class RecommendListAdapter extends BaseAdapter { + private List anchorListBeans = new ArrayList<>(); + private Context mContext; + private int[] mImage_bg; + + public RecommendListAdapter(Context context, int[] mImage_bg) { + mContext = context; + this.mImage_bg = mImage_bg; + } + + public void setAnchorListBeans(List listBeans) { + anchorListBeans = listBeans; + } + + @Override + public int getCount() { + return anchorListBeans.size(); + } + + @Override + public Object getItem(int i) { + return anchorListBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + AnchorListBean bean = anchorListBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_channel_recommend, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + holder.mTitle.setText(bean.getSkill_name()); + final List anchors = bean.getAnchors(); + for (int index = 0; index < holder.mRecommendView.length; index++) { + holder.mRecommendView[index].setVisibility(View.INVISIBLE); + } + + for (int index = 0; index < holder.mRecommendParentView.length; index++) { + holder.mRecommendParentView[index].setVisibility(View.GONE); + } + + for (int index = 0; index < anchors.size(); index++) { + final AnchorBean anchor = anchors.get(index); + int x = (int) (Math.random() * 6); + holder.mPhoto[index].setBackgroundColor(mImage_bg[x]); +// holder.mPhoto[index].setImageURI(ConstUrl.IMAGE_URL + anchor.getCover()); + Glide.with(mContext).load(StrU.getResourcePath(anchor.getCover(), mContext)).into(holder.mPhoto[index]); + holder.mPhoto[index].setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", anchor.getUserid()); + mContext.startActivity(intent); + } + }); + + holder.mCost[index].setText(anchor.getNickname()); + holder.mScore[index].setText("评分" + anchor.getGive_score() + ""); + holder.mLocation[index].setText(anchor.getCity()); + holder.mRecommendView[index].setVisibility(View.VISIBLE); + } + + if (anchors.size() > 0) { + holder.mRecommendParentView[0].setVisibility(View.VISIBLE); + } + + if (anchors.size() > 2) { + holder.mRecommendParentView[1].setVisibility(View.VISIBLE); + } + + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.mTitle = v.findViewById(R.id.channel_recommend_title); + holder.mRecommendParentView = new View[2]; + holder.mRecommendParentView[0] = v.findViewById(R.id.channel_recommend_parent_1); + holder.mRecommendParentView[1] = v.findViewById(R.id.channel_recommend_parent_2); + holder.mRecommendView = new View[4]; + holder.mRecommendView[0] = v.findViewById(R.id.channel_recommend_id_1); + holder.mRecommendView[1] = v.findViewById(R.id.channel_recommend_id_2); + holder.mRecommendView[2] = v.findViewById(R.id.channel_recommend_id_3); + holder.mRecommendView[3] = v.findViewById(R.id.channel_recommend_id_4); + holder.mPhoto = new SimpleDraweeView[4]; + holder.mPhoto[0] = v.findViewById(R.id.channel_recommend_id_photo_1); + holder.mPhoto[1] = v.findViewById(R.id.channel_recommend_id_photo_2); + holder.mPhoto[2] = v.findViewById(R.id.channel_recommend_id_photo_3); + holder.mPhoto[3] = v.findViewById(R.id.channel_recommend_id_photo_4); + holder.mCost = new TextView[4]; + holder.mCost[0] = v.findViewById(R.id.channel_recommend_id_cost_1); + holder.mCost[1] = v.findViewById(R.id.channel_recommend_id_cost_2); + holder.mCost[2] = v.findViewById(R.id.channel_recommend_id_cost_3); + holder.mCost[3] = v.findViewById(R.id.channel_recommend_id_cost_4); + holder.mScore = new TextView[4]; + holder.mScore[0] = v.findViewById(R.id.channel_recommend_id_score_1); + holder.mScore[1] = v.findViewById(R.id.channel_recommend_id_score_2); + holder.mScore[2] = v.findViewById(R.id.channel_recommend_id_score_3); + holder.mScore[3] = v.findViewById(R.id.channel_recommend_id_score_4); + holder.mLocation = new TextView[4]; + holder.mLocation[0] = v.findViewById(R.id.channel_recommend_location_1); + holder.mLocation[1] = v.findViewById(R.id.channel_recommend_location_2); + holder.mLocation[2] = v.findViewById(R.id.channel_recommend_location_3); + holder.mLocation[3] = v.findViewById(R.id.channel_recommend_location_4); + return holder; + } + + class Holder { + TextView mTitle; + View[] mRecommendParentView; + View[] mRecommendView; + SimpleDraweeView[] mPhoto; + TextView[] mCost; + TextView[] mScore; + TextView[] mLocation; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/RedEnvelopesAdpater.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/RedEnvelopesAdpater.java new file mode 100644 index 0000000..804f261 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/RedEnvelopesAdpater.java @@ -0,0 +1,95 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.base.RecyclerLoadAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.RedEnvelopesBean; +import com.fengliyan.tianlesue.utils.GlideUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBackBase; + +import java.util.ArrayList; + +/** + * ying 2021/1/25 + * Describe : + */ + +public class RedEnvelopesAdpater extends RecyclerLoadAdapter { + + private final BaseActivity mActivity; + private final String mRp_id; + private final onRedEnvelopesListener mListener; + public ArrayList mList = new ArrayList(); + + public RedEnvelopesAdpater(BaseActivity activity, String rp_id, RecyclerView recyclerView, onRedEnvelopesListener listener) { + super(recyclerView); + mActivity = activity; + mRp_id = rp_id; + mListener = listener; + getloadData(1); + } + + @Override + public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new MyHolder(View.inflate(parent.getContext(), R.layout.item_red, null)); + } + + @Override + public void onBindViewHolder(MyHolder holder, int position) { + RedEnvelopesBean.RpDataBean rpDataBean = mList.get(position); + GlideUtils.showImage(holder.itemView.getContext(), holder.mPhoto, rpDataBean.avatar); + holder.mName.setText(rpDataBean.nickname); + holder.mTime.setText(rpDataBean.create_time); + holder.mMoney.setText(rpDataBean.reward + "金币"); + holder.mOptimum.setVisibility(rpDataBean.bestLuck == 1 ? View.VISIBLE : View.INVISIBLE); + } + + @Override + public int getItemCount() { + return mList.size(); + } + + @Override + protected void getloadData(int page) { + MainManager.redPackView(mActivity, mRp_id, page, new HttpUiCallBackBase() { + @Override + public void onSuccessBase(BaseActivity activity, RedEnvelopesBean result, String message) { + if (result.page == 1) { + mList.clear(); + mListener.oneListener(result); + } + mList.addAll(result.rpData); + } + }); + } + + class MyHolder extends RecyclerView.ViewHolder { + + private final ImageView mPhoto; + private final ImageView mOptimum; + private final TextView mMoney; + private final TextView mName; + private final TextView mTime; + + public MyHolder(View itemView) { + super(itemView); + mPhoto = itemView.findViewById(R.id.item_red_photo); + mOptimum = itemView.findViewById(R.id.item_red_optimum); + mMoney = itemView.findViewById(R.id.item_red_money); + mName = itemView.findViewById(R.id.item_red_name); + mTime = itemView.findViewById(R.id.item_red_time); + } + } + + public interface onRedEnvelopesListener { + void oneListener(RedEnvelopesBean result);//第一页的回调 用于修改列表以外的 + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/SearchAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/SearchAdapter.java new file mode 100644 index 0000000..89b4582 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/SearchAdapter.java @@ -0,0 +1,92 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.SearchBean; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +public class SearchAdapter extends BaseAdapter { + private List mSearchList = new ArrayList<>(); + private Context mContext; + + public SearchAdapter(Context context) { + mContext = context; + } + + public void setSearchList(List list) { + mSearchList = list; + } + + @Override + public int getCount() { + return mSearchList.size(); + } + + @Override + public Object getItem(int i) { + return mSearchList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + SearchBean bean = mSearchList.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_search, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + if (0 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_pvip); + } else if (1 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_gvip); + } else { + holder.ivMemberSign.setVisibility(View.GONE); + } + + holder.mPhoto.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.mName.setText(bean.getNickname()); + holder.mInfo.setText(bean.getCity() + " | " + bean.getAge() + "岁"); + holder.mTime.setText(bean.getDateline()); + view.setTag(holder); + return view; + } + + private Holder initView(View view) { + Holder holder = new Holder(); + holder.mPhoto = view.findViewById(R.id.search_list_photo); + holder.mName = view.findViewById(R.id.search_list_name); + holder.mInfo = view.findViewById(R.id.search_list_location); + holder.mTime = view.findViewById(R.id.search_list_time); + holder.ivMemberSign = view.findViewById(R.id.iv_member_sign); + return holder; + } + + + class Holder { + private SimpleDraweeView mPhoto; + private TextView mName; + private TextView mInfo; + private TextView mTime; + ImageView ivMemberSign; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/VideoAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/VideoAdapter.java new file mode 100644 index 0000000..b53fb06 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/VideoAdapter.java @@ -0,0 +1,132 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.google.gson.Gson; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.model.main.websocket.NoticeBean; +import com.fengliyan.tianlesue.model.main.websocket.NoticeGiftBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketChatBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; + +import java.util.ArrayList; +import java.util.List; + +public class VideoAdapter extends BaseAdapter { + List mChatBeanList = new ArrayList<>(); + Context mContext; + + public VideoAdapter(Context context) { + mContext = context; + } + + public void setChatBeanList(List chatBeanList) { + mChatBeanList = chatBeanList; + } + + @Override + public int getCount() { + return mChatBeanList.size(); + } + + @Override + public Object getItem(int i) { + return mChatBeanList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder; + WebSocketChatBean bean = mChatBeanList.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_video_chat, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + final WebSocketChatBean noticeBean = bean; + if (noticeBean.getData().getType() == 3) { + Gson gson = new Gson(); + NoticeGiftBean noticeGiftBean = gson.fromJson(noticeBean.getData().getContent(), + NoticeGiftBean.class); + holder.giftLogo.setImageURI(StrU.getResourcePath(noticeGiftBean.getGifticon(), mContext)); + if (noticeBean.getData().getFrom_uid().equals(SPUtils.getInt(mContext, ConsUser.USER_ID) + "")) { + holder.giftTextView.setText("送" + noticeGiftBean.getGiftname()); + } else { + holder.giftTextView.setText("收" + noticeGiftBean.getGiftname()); + } + + holder.giftCount.setText("x1"); + holder.giftView.setVisibility(View.VISIBLE); + holder.chatView.setVisibility(View.GONE); + } else { + holder.giftView.setVisibility(View.GONE); + holder.chatView.setVisibility(View.VISIBLE); + if (noticeBean.getData().getType() == 1) { + holder.chatView.setText("系统消息:" + noticeBean.getData().getContent()); + holder.chatView.setTextColor(mContext.getResources().getColor(R.color.giftText)); + } else { + holder.chatView.setTextColor(Color.WHITE); + if (noticeBean.getData().getFrom_uid().equals(SPUtils.getInt(mContext, ConsUser.USER_ID) + "")) { + holder.chatView.setText("我:" + noticeBean.getData().getContent()); + } else { + holder.chatView.setText("对方:" + noticeBean.getData().getContent()); + } + } + } + + holder.chatView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (!TextUtils.isEmpty(noticeBean.getData().getLink_type()) && !TextUtils.isEmpty(noticeBean.getData().getLink_url())) { + int type = Integer.parseInt(noticeBean.getData().getLink_type()); + if (type == 2 && "rechargeCoin".equals(noticeBean.getData().getLink_url())) { + BaseApplication.getInstance().getRechargeInfo((BaseActivity) mContext, 0); + } else { + JumpUtils.jump(type, noticeBean.getData().getLink_url(), mContext); + } + } + } + }); + + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.chatView = v.findViewById(R.id.video_chat_text); + holder.giftView = v.findViewById(R.id.video_chat_gift_layout); + holder.giftLogo = v.findViewById(R.id.video_chat_gift_logo); + holder.giftTextView = v.findViewById(R.id.video_chat_gift_name); + holder.giftCount = v.findViewById(R.id.video_chat_gift_count); + + return holder; + } + + class Holder { + TextView chatView; + View giftView; + TextView giftTextView; + SimpleDraweeView giftLogo; + TextView giftCount; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ViewHolder.java new file mode 100644 index 0000000..c7e59d7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/adapter/ViewHolder.java @@ -0,0 +1,269 @@ +package com.fengliyan.tianlesue.controller.main.adapter; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.util.Linkify; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AlphaAnimation; +import android.widget.Checkable; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.RatingBar; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +public class ViewHolder extends RecyclerView.ViewHolder{ + private SparseArray mViews; + private View mConvertView; + private Context mContext; + + public ViewHolder(Context context, View itemView) + { + super(itemView); + mContext = context; + mConvertView = itemView; + mViews = new SparseArray(); + } + + + public static ViewHolder createViewHolder(Context context, View itemView) + { + ViewHolder holder = new ViewHolder(context, itemView); + return holder; + } + + public static ViewHolder createViewHolder(Context context, + ViewGroup parent, int layoutId) + { + View itemView = LayoutInflater.from(context).inflate(layoutId, parent, + false); + ViewHolder holder = new ViewHolder(context, itemView); + return holder; + } + + /** + * 通过viewId获取控件 + * + * @param viewId + * @return + */ + public T getView(int viewId) + { + View view = mViews.get(viewId); + if (view == null) + { + view = mConvertView.findViewById(viewId); + mViews.put(viewId, view); + } + return (T) view; + } + + public View getConvertView() + { + return mConvertView; + } + + + + + /****以下为辅助方法*****/ + + /** + * 设置TextView的值 + * + * @param viewId + * @param text + * @return + */ + public ViewHolder setText(int viewId, String text) + { + TextView tv = getView(viewId); + tv.setText(text); + return this; + } + + public ViewHolder setImageResource(int viewId, int resId) + { + ImageView view = getView(viewId); + view.setImageResource(resId); + return this; + } + + public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) + { + ImageView view = getView(viewId); + view.setImageBitmap(bitmap); + return this; + } + + public ViewHolder setImageDrawable(int viewId, Drawable drawable) + { + ImageView view = getView(viewId); + view.setImageDrawable(drawable); + return this; + } + + public ViewHolder setBackgroundColor(int viewId, int color) + { + View view = getView(viewId); + view.setBackgroundColor(color); + return this; + } + + public ViewHolder setBackgroundRes(int viewId, int backgroundRes) + { + View view = getView(viewId); + view.setBackgroundResource(backgroundRes); + return this; + } + + public ViewHolder setTextColor(int viewId, int textColor) + { + TextView view = getView(viewId); + view.setTextColor(textColor); + return this; + } + + public ViewHolder setTextColorRes(int viewId, int textColorRes) + { + TextView view = getView(viewId); + view.setTextColor(mContext.getResources().getColor(textColorRes)); + return this; + } + + @SuppressLint("NewApi") + public ViewHolder setAlpha(int viewId, float value) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + { + getView(viewId).setAlpha(value); + } else + { + // Pre-honeycomb hack to set Alpha value + AlphaAnimation alpha = new AlphaAnimation(value, value); + alpha.setDuration(0); + alpha.setFillAfter(true); + getView(viewId).startAnimation(alpha); + } + return this; + } + + public ViewHolder setVisible(int viewId, boolean visible) + { + View view = getView(viewId); + view.setVisibility(visible ? View.VISIBLE : View.GONE); + return this; + } + + public ViewHolder linkify(int viewId) + { + TextView view = getView(viewId); + Linkify.addLinks(view, Linkify.ALL); + return this; + } + + public ViewHolder setTypeface(Typeface typeface, int... viewIds) + { + for (int viewId : viewIds) + { + TextView view = getView(viewId); + view.setTypeface(typeface); + view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); + } + return this; + } + + public ViewHolder setProgress(int viewId, int progress) + { + ProgressBar view = getView(viewId); + view.setProgress(progress); + return this; + } + + public ViewHolder setProgress(int viewId, int progress, int max) + { + ProgressBar view = getView(viewId); + view.setMax(max); + view.setProgress(progress); + return this; + } + + public ViewHolder setMax(int viewId, int max) + { + ProgressBar view = getView(viewId); + view.setMax(max); + return this; + } + + public ViewHolder setRating(int viewId, float rating) + { + RatingBar view = getView(viewId); + view.setRating(rating); + return this; + } + + public ViewHolder setRating(int viewId, float rating, int max) + { + RatingBar view = getView(viewId); + view.setMax(max); + view.setRating(rating); + return this; + } + + public ViewHolder setTag(int viewId, Object tag) + { + View view = getView(viewId); + view.setTag(tag); + return this; + } + + public ViewHolder setTag(int viewId, int key, Object tag) + { + View view = getView(viewId); + view.setTag(key, tag); + return this; + } + + public ViewHolder setChecked(int viewId, boolean checked) + { + Checkable view = (Checkable) getView(viewId); + view.setChecked(checked); + return this; + } + + /** + * 关于事件的 + */ + public ViewHolder setOnClickListener(int viewId, + View.OnClickListener listener) + { + View view = getView(viewId); + view.setOnClickListener(listener); + return this; + } + + public ViewHolder setOnTouchListener(int viewId, + View.OnTouchListener listener) + { + View view = getView(viewId); + view.setOnTouchListener(listener); + return this; + } + + public ViewHolder setOnLongClickListener(int viewId, + View.OnLongClickListener listener) + { + View view = getView(viewId); + view.setOnLongClickListener(listener); + return this; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/manager/GlobalManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/manager/GlobalManager.java new file mode 100644 index 0000000..d4bcacf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/manager/GlobalManager.java @@ -0,0 +1,53 @@ +package com.fengliyan.tianlesue.controller.main.manager; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; +import com.google.gson.internal.LinkedTreeMap; + +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +public class GlobalManager { + private static Map sCityMap = new LinkedTreeMap<>(); + + public static Map getCityMap() { + return sCityMap; + } + + public static void setCityMap(Map cityMap) { + Set keys = cityMap.keySet(); + Iterator iterator = keys.iterator(); + while(iterator.hasNext()){ + String id = iterator.next(); + String name = cityMap.get(id); + sCityMap.put(name, id); + } + } + + public static void queryCity(BaseActivity activity, + HttpUiCallBack httpUiCallBack){ + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.QUERY_CITIES; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(false); + task.start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/main/manager/MainManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/main/manager/MainManager.java new file mode 100644 index 0000000..3dd1ef1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/main/manager/MainManager.java @@ -0,0 +1,1484 @@ +package com.fengliyan.tianlesue.controller.main.manager; + +import android.app.Activity; +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.HttpRequestFactory; +import com.fengliyan.http.httprequest.OkHttp.CaiWebSocket; +import com.fengliyan.http.httprequest.TType; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.main.AnchorListBean; +import com.fengliyan.tianlesue.model.main.AttentionDialogBean; +import com.fengliyan.tianlesue.model.main.BlackBean; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.model.main.ChatShootBean; +import com.fengliyan.tianlesue.model.main.CloseGreetBean; +import com.fengliyan.tianlesue.model.main.ComplaintListBean; +import com.fengliyan.tianlesue.model.main.DialogAdBean; +import com.fengliyan.tianlesue.model.main.FreeVideoBean; +import com.fengliyan.tianlesue.model.main.GiftReceivedBean; +import com.fengliyan.tianlesue.model.main.GlobalConfigBean; +import com.fengliyan.tianlesue.model.main.GroupCallBean; +import com.fengliyan.tianlesue.model.main.GuardListBean; +import com.fengliyan.tianlesue.model.main.IsKidModelBean; +import com.fengliyan.tianlesue.model.main.MainBean; +import com.fengliyan.tianlesue.model.main.MainPageAnchorBean; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.model.main.MainPageSwitchSwerviceNumBean; +import com.fengliyan.tianlesue.model.main.PrizeBean; +import com.fengliyan.tianlesue.model.main.RedEnvelopesBean; +import com.fengliyan.tianlesue.model.main.RedEnvlopesRedwarsBean; +import com.fengliyan.tianlesue.model.main.SearchListBean; +import com.fengliyan.tianlesue.model.main.SkillAnchorBean; +import com.fengliyan.tianlesue.model.main.SystemVersionBean; +import com.fengliyan.tianlesue.model.main.UserGenderListBean; +import com.fengliyan.tianlesue.model.main.VersionBean; +import com.fengliyan.tianlesue.model.main.VideoFeeBean; +import com.fengliyan.tianlesue.model.main.VideoGuardBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketRequestBean; +import com.fengliyan.tianlesue.model.settings.BackPackListBean; +import com.fengliyan.tianlesue.model.user.bean.UserLiteBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; +import com.fengliyan.uikit.dialog.GiftListBean; + +import java.util.List; + +public class MainManager { + public static void index(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.MAIN_BANNER_FIELD; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + +// task.start(); + task.start(false); + } + + public static void getChannelAnchors(BaseActivity activity, + final String skillId, + final String type, + final int page, + final String cityId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CHANNEL_DATA; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("skill_id", skillId + "") + .addParam("type", type + "") + .addParam("page", page + "") + .addParam("city", cityId) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + +// task.start(); + task.start(false); + } + + public static void getCityAnchors(BaseActivity activity, + final String city, + final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CITY_ANCHORS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("city", city) + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + +// task.start(); + task.start(false); + } + + /** + * 首页缘分列表 + * + * @param activity + * @param type 1.在线 2.新人 3.同城 + * @param page + * @param httpUiCallBack + */ + public static void getLuckList(BaseActivity activity, int type, String city, final int page, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() { + String url = ConstUrl.HOME_ONLINE; + switch (type) { + case 1: + url = ConstUrl.HOME_ONLINE; + break; + case 2: + url = ConstUrl.HOME_NEW_USER; + break; + case 3: + url = ConstUrl.HOME_CITY; + break; + } + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("city", city) + .addParam("page", page + "") + .setUrl(url); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + /** + * 首页活跃列表 + * + * @param activity + * @param page + * @param httpUiCallBack + */ + public static void getActiveAnchors(BaseActivity activity, + final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.ACTIVE_ANCHORS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "").setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + +// task.start(); + task.start(false); + } + + /** + * 首页新人列表 + * + * @param activity + * @param page + * @param httpUiCallBack + */ + public static void getNewAnchors(BaseActivity activity, + final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.NEW_ANCHORS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "").setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + +// task.start(); + task.start(false); + } + + /** + * 首页推荐女神 + * + * @param activity + * @param page + * @param httpUiCallBack + */ + public static void getRecommendAnchors(BaseActivity activity, + final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.RECOMMEND_ANCHORS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "").setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + +// task.start(); + task.start(false); + } + + /** + * 视频结束后推荐主播列表 + * + * @param activity + * @param httpUiCallBack + */ + public static void getCallEndRecommend(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CALL_END_RECOMMEND; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 获取封面视频 + * + * @param activity + * @param httpUiCallBack + */ + public static void getCoverVideo(BaseActivity activity, int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.COVER_VIDEO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "").setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void redwars(BaseActivity activity, final String rp_id, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.REDWARS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("rp_id", rp_id) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void redPackView(BaseActivity activity, final String rp_id, final int page, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.REDPACKVIEW; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("rp_id", rp_id) + .addParam("page", String.valueOf(page)) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getMainPageData(BaseActivity activity, + final int userId, final String user_code, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.MAIN_PAGE_DATA; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", userId + "") + .addParam("user_code", user_code) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getAllChannels(BaseActivity activity, + HttpUiCallBack> httpUiCallBack) { + HttpWithUiTask> task = new HttpWithUiTask>(activity, httpUiCallBack) { + @Override + protected HttpResult> run() throws Exception { + final String url = ConstUrl.GET_ALL_CHANNELS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 获取转盘奖品 + * + * @param activity + * @param httpUiCallBack + */ + public static void getTurntable(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_TURNTABLE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 开始抽奖 + * + * @param activity + * @param httpUiCallBack + */ + public static void startTurntable(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.START_TURNTABLE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 获取抽奖记录 + * + * @param activity + * @param httpUiCallBack + */ + public static void turntableWinningRecord(BaseActivity activity, int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.TURNTABLE_WINNING_RECORD; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 新春夺宝抽奖 + * + * @param activity + * @param httpUiCallBack + */ + public static void startTreasureHunt(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.YEAR_TREASURE_HUNT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 拨打电话 + * + * @param activity + * @param toUid + * @param skillId + * @param type 0.视频 1.语音 + * @param httpUiCallBack + */ + public static void getCallInfo(BaseActivity activity, + final int toUid, + final int skillId, + int type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_CHAT_INFO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("to_uid", toUid + "") + .addParam("type", type + "") + .addParam("skill_id", skillId + "").setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getGiftBeans(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_GIFT_DATA; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void sendGift(BaseActivity activity, + final int type, + final int toUid, + final int giftId, + final int num, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SEND_GIFT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("to_uid", toUid + "") + .addParam("gift_id", giftId + "") + .addParam("num", num + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void receivedGiftList(BaseActivity activity, + final int userId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.RECEIVED_GIFT_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", userId + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void changeVideoStatus(BaseActivity activity, + final int status, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CHANGE_VIDEO_STATUS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("status", status + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void changeswitchServiceNum(BaseActivity activity, + final int status, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SWITCH_SERVICE_NUM; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("status", status + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getGlobalConfig(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_GLOBAL_CONFIG; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void freeAnchor(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.FREEANCHOR); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void search(BaseActivity activity, + final int type, + final String text, + final int gender, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SEARCH; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("text", text) + .addParam("gender", gender + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getCallInfoFromRoom(BaseActivity activity, + final int roomId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_CALL_INFO_FROM_ROOM; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("room_id", roomId + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 截取主叫者的图片 + * + * @param activity + * @param roomId + * @param from + * @param httpUiCallBack + */ + public static void postChatShootFrom(BaseActivity activity, + final int roomId, final String from, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CHAT_SNAPSHOOT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("room_id", roomId + "") + .addParam("from", from) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(false); + } + + /** + * 截取被叫者的图片 + * + * @param activity + * @param roomId + * @param to + * @param httpUiCallBack + */ + public static void postChatShootTo(BaseActivity activity, + final int roomId, final String to, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CHAT_SNAPSHOOT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("room_id", roomId + "") + .addParam("to", to) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(false); + } + + public static void getVideoFee(BaseActivity activity, + final String roomId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_VIDEO_FEE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("room_id", roomId) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getComplaintList(BaseActivity activity, + HttpUiCallBack> httpUiCallBack) { + HttpWithUiTask> task = new HttpWithUiTask>(activity, httpUiCallBack) { + @Override + protected HttpResult> run() throws Exception { + final String url = ConstUrl.GET_COMPLAINT_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void doComplaint(BaseActivity activity, + final int type, + final int cateId, + final String uid, + final String content, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.DO_COMPLAINT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("cate_id", cateId + "") + .addParam("report_uid", uid + "") + .addParam("content", content) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void doBlack(BaseActivity activity, + final String uid, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.DO_BLACK; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("black_uid", uid) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getGenderUserList(BaseActivity activity, + final String cityId, + final int gender, + final int type, + final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GET_ACTIVE_USERS; + if (type == 1) { + url = ConstUrl.GET_USERS_IN_SAME_CITY; + } + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("city", cityId) + .addParam("gender", gender + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getSystemVersion(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GET_SYSTEM_VERSION; + + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void downloadNewApp(BaseActivity activity, String url, String path, HttpCallback callback) { + HttpRequest request = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url).build(); + + request.download(path, true, callback); + } + + public static void createWebSocket(CaiWebSocket.WebSocketListener listener, String url, Activity activity) { + HttpRequestFactory.createWebSocket(listener, url, activity); + } + + public static void sendWebSocketMessage(WebSocketRequestBean bean) { + Gson gson = new Gson(); + String message = gson.toJson(bean); + message = message + "@@"; + HttpRequestFactory.sendWebSocketMessage(message); + } + + public static void checkUpdate(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GET_SYSTEM_VERSION; + + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void evaluateVideo(BaseActivity activity, + final String roomId, + final int score, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.EVALUATE_VIDEO; + + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("room_id", roomId) + .addParam("score", score + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 用户活跃更新 + * + * @param activity + * @param httpUiCallBack + */ + public static void activeUpdate(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.ACTIVE_UPDATE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + /** + * 获取是否为审核模式 + * + * @param activity + * @param httpUiCallBack + */ + public static void getMarketStatus(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GET_MARKET_STATUS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + /** + * 推荐关注列表 + * + * @param activity + * @param page + * @param httpUiCallBack + */ + public static void attentionDialogList(BaseActivity activity, final int page, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.ATTENTION_DIALOG_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + /** + * 批量关注 + * + * @param activity + * @param httpUiCallBack + */ + public static void batchFollow(BaseActivity activity, final String uids, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.BATCH_FOLLOW; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("uids", uids) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void getGroupCallInfo(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GREET_LISTS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void setAddGroupCall(BaseActivity activity, final String title, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GREET_ADD; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("title", title) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void sendGroupCall(BaseActivity activity, final int gid, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GREET_SEND; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + if (gid != -1) { + builder.addParam("gid", gid + ""); + } + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void sendGreetSendOne(BaseActivity activity, final String to_user_id, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GREET_SEND_ONE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + builder.addParam("to_user_id", to_user_id); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void deleteGroupCall(BaseActivity activity, final int id, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GREET_DELETE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("id", id + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void getUserLite(BaseActivity activity, final String user_id, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.USER_LITE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", user_id) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void setKidPassword(BaseActivity activity, final String password, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.SET_ADOLESCENT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("password", password) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void setOpenKidModel(BaseActivity activity, final String password, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.CLOSE_ADOLESCENT; + + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("password", password) + .addParam("is_open", "0") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void kidPhoneCode(BaseActivity activity, final String mobile, final String phone_code, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.VERIFY_MOBILE_CODE; + + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("mobile", mobile) + .addParam("phone_code", phone_code) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void getIsKidModel(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GET_ADOLESCENT_STATUS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void postGuard(BaseActivity activity, final String user_id, final int guard_num, final String guard_price, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.ADD_GUARD; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", user_id) + .addParam("guard_num", guard_num + "") + .addParam("guard_price", guard_price) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void getGuardList(BaseActivity activity, final int page, final String user_id, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GET_USER_GUARD_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "") + .addParam("user_id", user_id) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void postVideoGuard(BaseActivity activity, final int user_id, final int room_id, final int guard_num, final String guard_price, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.ROOM_ADD_GUARD; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", user_id + "") + .addParam("room_id", room_id + "") + .addParam("guard_num", guard_num + "") + .addParam("guard_price", guard_price) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void adDialog(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.GETADVERT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void postScreenNumber(BaseActivity activity, final int type, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.SCREEN_NUMBER; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + public static void reconnectWebSocket(String url) { +// Log.d("nail","url===" + url); + HttpRequestFactory.reconnectWebSocket(url); + } + + public static void closeWebSocket() { + HttpRequestFactory.closeWebSocket(); + } + + public static void updateRealCity(BaseActivity activity, final double latitude, final double longitude, String province, String city, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("lat", latitude + "") + .addParam("lng", longitude + "") + .addParam("province", province) + .addParam("city", city) + .setUrl(ConstUrl.UPDATEREALCITY); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + + //关闭用户免打扰 + public static void closeGreet(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.CLOSE_GREET); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + //查询用户免打扰 + public static void getGreet(BaseActivity activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.GET_GREET); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(false); + } + + /** + * 本机手机号一键登录 + * + * @param activity + * @param accessToken app号码认证获取到的access_token + * @param invite_code 通过openinstall获取的邀请码 + * @param httpUiCallBack + */ + public static void oneKeyLogin(BaseActivity activity, + final String accessToken, final String invite_code, String risk_engine_token, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.ONE_KEY_LOGIN; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("token", accessToken); + builder.addParam("x-risk-engine-token", risk_engine_token); + if (!TextUtils.isEmpty(invite_code)) { + builder.addParam("invite_code", invite_code); + } + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/ChatAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/ChatAdapter.java new file mode 100644 index 0000000..fd2d086 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/ChatAdapter.java @@ -0,0 +1,405 @@ +package com.fengliyan.tianlesue.controller.news.manager; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.text.style.ImageSpan; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.model.news.ChatBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.utils.ToolKit; +import com.fengliyan.tianlesue.view.dynamics.activity.ImageDisplayActivity; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.tianlesue.view.news.fragment.NewFragment; +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.messaging.CustomAttachment; +import com.fengliyan.messaging.SysInfoDoubleImageAttachment; +import com.fengliyan.messaging.SysInfoImage; +import com.fengliyan.messaging.SysInfoSingleImageAttachment; +import com.fengliyan.uikit.UiUtils; +import com.fengliyan.uikit.emoji.utils.MoonUtil; +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder; +import com.facebook.drawee.view.SimpleDraweeView; +import com.facebook.imagepipeline.request.BasePostprocessor; +import com.facebook.imagepipeline.request.ImageRequestBuilder; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ChatAdapter extends BaseAdapter { + private List mChatBeanList = new ArrayList<>(); + private Context mContext; + + public ChatAdapter(Context context) { + mContext = context; + } + + public void addChatBeanList(List chatBeans) { + mChatBeanList = chatBeans; + } + + @Override + public int getCount() { + return mChatBeanList.size(); + } + + @Override + public Object getItem(int i) { + return mChatBeanList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(final int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final ChatBean bean = mChatBeanList.get(i); + if (view == null) { + if (!bean.isFromMe()) { + view = View.inflate(mContext, R.layout.item_instant_message_alice, null); + } else { + view = View.inflate(mContext, R.layout.item_instant_message_me, null); + } + + holder = initView(view, bean.isFromMe()); + + } else { + holder = (Holder) view.getTag(); + if (bean.isFromMe() != holder.isFromMe) { + if (!bean.isFromMe()) { + view = View.inflate(mContext, R.layout.item_instant_message_alice, null); + } else { + view = View.inflate(mContext, R.layout.item_instant_message_me, null); + } + + holder = initView(view, bean.isFromMe()); + } + } + + if (i - 1 >= 0) { + ChatBean previousChat = mChatBeanList.get(i - 1); + if (null != previousChat) { + long previousTimeStamp = Long.parseLong(previousChat.getDatetime()); + long currentTimeStamp = Long.parseLong(bean.getDatetime()); + if ((currentTimeStamp - previousTimeStamp) / 1000 < 120) { + holder.timeView.setVisibility(View.GONE); + } else { + holder.timeView.setVisibility(View.VISIBLE); + } + } else { + holder.timeView.setVisibility(View.VISIBLE); + } + } else { + holder.timeView.setVisibility(View.VISIBLE); + } + + String time = ToolKit.parseFormatTime(bean.getDatetime()); + if (bean.getType() == 1 && null != bean.getImageUrl()) { + holder.messageText.setVisibility(View.GONE); + if (null != holder.costView) { + holder.costView.setVisibility(View.GONE); + } + + holder.giftView.setVisibility(View.GONE); + holder.giftLogo.setVisibility(View.GONE); + holder.imageView.setVisibility(View.VISIBLE); + PipelineDraweeControllerBuilder controller = Fresco.newDraweeControllerBuilder(); + final Holder finalHolder = holder; + controller.setImageRequest(ImageRequestBuilder + .newBuilderWithSource(Uri.parse(bean.getImageUrl())) + .setPostprocessor(new BasePostprocessor() { + @Override + public void process(Bitmap bitmap) { + super.process(bitmap); + int bitmapHeight = bitmap.getHeight(); + int bitmapWidth = bitmap.getWidth(); + DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); + int height = dm.heightPixels; + int width = dm.widthPixels; + int newWidth = 0; + int newHeight = 0; + if (bitmapWidth > bitmapHeight) { + newWidth = (int) (0.25 * width); + newHeight = (int) (newWidth * bitmapHeight / bitmapWidth); + } else { + newHeight = (int) (0.25 * height); + newWidth = (int) (newHeight * bitmapWidth / bitmapHeight); + } + + RelativeLayout.LayoutParams params = + (RelativeLayout.LayoutParams) finalHolder + .imageView.getLayoutParams(); + + params.width = newWidth; + params.height = newHeight; + finalHolder.imageView.setLayoutParams(params); + } + }).build()); + + holder.imageView.setController(controller.build()); + holder.imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + ArrayList imagePathList = new ArrayList<>(); + imagePathList.add(bean.getImageUrl()); + clickImage(imagePathList, 1); + } + }); + } else if (bean.getType() == 2) { + CustomAttachment customAttachment = bean.getCustomAttachment(); + if (null != customAttachment) { + + if (14 == customAttachment.getType()) { +// GiftAttachment giftAttachment = (GiftAttachment) customAttachment; +// holder.messageText.setVisibility(View.GONE); +// if(null != holder.costView) { +// holder.costView.setVisibility(View.GONE); +// } +// +// holder.giftView.setVisibility(View.VISIBLE); +// holder.imageView.setVisibility(View.GONE); +// holder.giftLogo.setVisibility(View.VISIBLE); +// if (!bean.isFromMe()) { +// holder.notice1View.setVisibility(View.GONE); +// holder.notice2View.setVisibility(View.GONE); +// holder.notice3View.setVisibility(View.GONE); +// holder.normalView.setVisibility(View.VISIBLE); +// } +// +// holder.giftLogo.setImageURI(ConstUrl.IMAGE_URL + giftAttachment.getGift_url()); +// holder.giftName.setText(giftAttachment.getGift_name()); +// holder.giftCount.setText("x" + giftAttachment.getGift_count()); + } else if (13 == customAttachment.getType()) { + if (!bean.isFromMe()) { + holder.notice1View.setVisibility(View.VISIBLE); + holder.notice2View.setVisibility(View.GONE); + holder.notice3View.setVisibility(View.GONE); + holder.normalView.setVisibility(View.GONE); + } + + SysInfoDoubleImageAttachment attachment = (SysInfoDoubleImageAttachment) bean.getCustomAttachment(); + List images = attachment.getImageList(); + Iterator iterator = images.iterator(); + if (iterator.hasNext()) { + final SysInfoImage image = iterator.next(); + holder.notice1Image.setImageURI(image.getImage()); + holder.notice1Info.setText(image.getTitle()); + holder.notice1Image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + JumpUtils.jump(image.getLink_type(), image.getLink_url(), mContext); + } + }); + } + + while (iterator.hasNext()) { + SysInfoImage image = iterator.next(); + View imageView = View.inflate(mContext, R.layout.item_notice_1_child, null); + SimpleDraweeView childPhoto = imageView.findViewById(R.id.notice_1_child_head); + TextView childName = imageView.findViewById(R.id.notice_1_child_name); + TextView childInfo = imageView.findViewById(R.id.notice_1_child_info); + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) imageView.getLayoutParams(); + params.height = UiUtils.dip2px(mContext, 68); + params.width = LinearLayout.LayoutParams.MATCH_PARENT; + imageView.setLayoutParams(params); + childPhoto.setImageURI(StrU.getResourcePath(image.getImage(), mContext)); + childName.setText(image.getTitle()); + childInfo.setVisibility(View.GONE); + holder.notice1Layout.addView(imageView); + } + } else if (12 == customAttachment.getType()) { + if (!bean.isFromMe()) { + holder.notice1View.setVisibility(View.GONE); + holder.notice2View.setVisibility(View.VISIBLE); + holder.notice3View.setVisibility(View.GONE); + holder.normalView.setVisibility(View.GONE); + } + + final SysInfoSingleImageAttachment attachment = (SysInfoSingleImageAttachment) bean.getCustomAttachment(); + holder.notice2Image.setImageURI(attachment.getImage()); + if (attachment.getAct_type() == 1) { + holder.notice2Group.setText(attachment.getAct_string()); + } else { + holder.notice2TitleText.setText(attachment.getTitle()); + holder.notice2ContentText.setText(attachment.getTxt()); + } + + holder.notice2View.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + JumpUtils.jump(attachment.getLink_type(), attachment.getLink_url(), mContext); + } + }); + + } else if (11 == customAttachment.getType()) { + + } + } else { + holder.messageText.setVisibility(View.VISIBLE); + if (null != holder.costView) { + holder.costView.setVisibility(View.VISIBLE); + } + + holder.giftView.setVisibility(View.GONE); + holder.imageView.setVisibility(View.GONE); + holder.giftLogo.setVisibility(View.GONE); + holder.messageText.setText("内容无法显示"); + } + + } else { + holder.messageText.setVisibility(View.VISIBLE); + if (null != holder.costView) { + holder.costView.setVisibility(View.VISIBLE); + } + + holder.giftView.setVisibility(View.GONE); + holder.imageView.setVisibility(View.GONE); + holder.giftLogo.setVisibility(View.GONE); + MoonUtil.identifyFaceExpression(mContext, holder.messageText, + bean.getMessage(), ImageSpan.ALIGN_BOTTOM); + } + + if (null != holder.costView) { + if (0 != bean.getCost()) { + holder.costView.setText((0.7 * bean.getCost()) + ""); + } else { + holder.costView.setVisibility(View.GONE); + } + } + + holder.timeView.setText(time); + + holder.headView.setImageURI(StrU.getResourcePath(bean.getPhotoUrl(), mContext)); + holder.headView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + if (bean.isFromMe()) { +// intent.putExtra("userId", Integer.parseInt(UserManager.getUserInfo().getUser_id())); + intent.putExtra("userId", SPUtils.getInt(mContext, ConsUser.USER_ID)); + } else { + intent.putExtra("userId", Integer.parseInt(bean.getAccount())); + intent.putExtra("index", i); + if (NewFragment.RECENT_TAG_STICKY + == ChatManager.getInstance().getTag(bean.getAccount())) { + intent.putExtra("isOnTop", true); + } + } + + intent.putExtra("isFromChat", true); + mContext.startActivity(intent); + } + }); + + view.setTag(holder); + return view; + } + + private void clickImage(ArrayList pathList, int innerCount) { + Intent intent = new Intent(mContext, ImageDisplayActivity.class); + intent.putStringArrayListExtra("urlList", pathList); + intent.putExtra("pageCount", innerCount); + mContext.startActivity(intent); + } + + private Holder initView(View view, boolean isFromMe) { + Holder holder = null; + if (isFromMe) { + holder = initMyView(view); + } else { + holder = initAliceView(view); + } + + return holder; + } + + private Holder initAliceView(View v) { + Holder holder = new Holder(); + holder.messageText = v.findViewById(R.id.instant_message_alice_message); + holder.headView = v.findViewById(R.id.instant_message_alice_header); + holder.timeView = v.findViewById(R.id.instant_message_alice_time); + holder.costView = v.findViewById(R.id.instant_message_alice_cost); + holder.imageView = v.findViewById(R.id.instant_message_alice_image); + holder.giftView = v.findViewById(R.id.instant_message_alice_gift); + holder.giftName = v.findViewById(R.id.instant_message_alice_gift_name); + holder.giftCount = v.findViewById(R.id.instant_message_alice_gift_count); + holder.giftLogo = v.findViewById(R.id.instant_message_alice_gift_logo); + holder.notice1View = v.findViewById(R.id.instant_message_alice_notice_multi_image); + holder.notice2View = v.findViewById(R.id.instant_message_alice_notice_single_image); + holder.notice3View = v.findViewById(R.id.instant_message_alice_notice_text); + holder.normalView = v.findViewById(R.id.instant_message_alice_normal); + holder.notice1Image = v.findViewById(R.id.notice_1_head); + holder.notice1Info = v.findViewById(R.id.notice_1_child_info); + holder.notice2Group = v.findViewById(R.id.notice_2_group); + holder.notice2InfoView = v.findViewById(R.id.notice_2_view); + holder.notice1Layout = v.findViewById(R.id.notice_1_child_list); + holder.notice2Image = v.findViewById(R.id.notice_2_head); + holder.notice2TitleText = v.findViewById(R.id.notice_2_title); + holder.notice2ContentText = v.findViewById(R.id.notice_2_article); + holder.notice3TitleText = v.findViewById(R.id.notice_3_title); + holder.notice3TimeText = v.findViewById(R.id.notice_3_time); + holder.notice3ContentText = v.findViewById(R.id.notice_3_article); + holder.isFromMe = false; + return holder; + } + + private Holder initMyView(View v) { + Holder holder = new Holder(); + holder.messageText = v.findViewById(R.id.instant_message_me_message); + holder.headView = v.findViewById(R.id.instant_message_me_header); + holder.timeView = v.findViewById(R.id.instant_message_me_time); + holder.imageView = v.findViewById(R.id.instant_message_me_image); + holder.giftView = v.findViewById(R.id.instant_message_me_gift); + holder.giftName = v.findViewById(R.id.instant_message_me_gift_name); + holder.giftCount = v.findViewById(R.id.instant_message_me_gift_count); + holder.giftLogo = v.findViewById(R.id.instant_message_me_gift_logo); + holder.costView = null; + holder.isFromMe = true; + return holder; + } + + class Holder { + TextView messageText; + SimpleDraweeView headView; + TextView timeView; + TextView costView; + SimpleDraweeView imageView; + View giftView; + TextView giftName; + TextView giftCount; + SimpleDraweeView giftLogo; + View normalView; + View notice1View; + View notice2View; + View notice2InfoView; + View notice3View; + SimpleDraweeView notice1Image; + TextView notice1Info; + TextView notice2Group; + LinearLayout notice1Layout; + SimpleDraweeView notice2Image; + TextView notice2TitleText; + TextView notice2ContentText; + TextView notice3TitleText; + TextView notice3TimeText; + TextView notice3ContentText; + boolean isFromMe; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/NewAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/NewAdapter.java new file mode 100644 index 0000000..d6a6a00 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/NewAdapter.java @@ -0,0 +1,139 @@ +package com.fengliyan.tianlesue.controller.news.manager; + +import android.content.Context; +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.news.RecentContactBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.utils.ToolKit; +import com.fengliyan.tianlesue.view.news.fragment.NewFragment; +import com.fengliyan.messaging.ChatManager; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +public class NewAdapter extends BaseAdapter { + private List mRecentContactList = new ArrayList<>(); + private Context mContext; + private OnLongClickListener mLongClickListener; + public NewAdapter(Context context){ + mContext = context; + } + + public void addContactList(List recentContacts){ + mRecentContactList = recentContacts; + } + + public interface OnLongClickListener{ + void onLongClicked(View v, int index); + void onClick(View v, int index); + } + + public void setOnLongClickListener(OnLongClickListener listener){ + mLongClickListener = listener; + } + + @Override + public int getCount() { + return mRecentContactList.size(); + } + + @Override + public Object getItem(int i) { + return mRecentContactList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(final int i, View view, ViewGroup viewGroup) { + Holder holder = null; + if(null == view){ + view = View.inflate(mContext, R.layout.item_news, null); + holder = initView(view); + }else{ + holder = (Holder) view.getTag(); + } + + RecentContactBean bean = mRecentContactList.get(i); + if(0 == bean.getUncheckedMessageCount()) { + holder.mMessageCount.setVisibility(View.GONE); + }else{ + holder.mMessageCount.setVisibility(View.VISIBLE); + holder.mMessageCount.setText(bean.getUncheckedMessageCount() + ""); + } + + holder.mPhoto.setImageURI(StrU.getResourcePath(bean.getPhotoUrl(), mContext)); + + holder.mRecentMessageText.setText(bean.getRecentMessage()); + holder.mDate.setText(ToolKit.parseTime(bean.getDate())); + if(bean.getAccount().equals(UserManager.getGlobalConfigInfo().getConfig().getServId()) + || bean.getAccount().equals(UserManager.getGlobalConfigInfo().getConfig().getSysId())){ + holder.mName.setTextColor(mContext.getResources().getColor(R.color.mainColor)); + }else{ + holder.mName.setTextColor(Color.BLACK); + } + + holder.mName.setText(bean.getName()); + if(NewFragment.RECENT_TAG_STICKY == ChatManager.getInstance().getTag(bean.getAccount())){ + holder.mThisView.setBackgroundResource(R.color.mainBg); + }else { + holder.mThisView.setBackgroundResource(android.R.color.white); + } + + holder.mThisView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + if(null != mLongClickListener){ + mLongClickListener.onLongClicked(view, i); + return true; + } + + return false; + } + }); + + holder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if(null != mLongClickListener){ + mLongClickListener.onClick(view, i); + } + } + }); + + view.setTag(holder); + + return view; + } + + private Holder initView(View v){ + Holder holder = new Holder(); + holder.mPhoto = (SimpleDraweeView)v.findViewById(R.id.news_photo); + holder.mName = (TextView)v.findViewById(R.id.news_name); + holder.mDate = (TextView)v.findViewById(R.id.news_time); + holder.mRecentMessageText = (TextView)v.findViewById(R.id.news_message); + holder.mMessageCount = (TextView)v.findViewById(R.id.news_message_count); + holder.mThisView = v.findViewById(R.id.news_view); + return holder; + } + + class Holder{ + SimpleDraweeView mPhoto; + TextView mRecentMessageText; + TextView mMessageCount; + TextView mDate; + TextView mName; + View mThisView; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/NewsManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/NewsManager.java new file mode 100644 index 0000000..21b904b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/news/manager/NewsManager.java @@ -0,0 +1,225 @@ +package com.fengliyan.tianlesue.controller.news.manager; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.model.news.ChatSettingBean; +import com.fengliyan.tianlesue.model.news.ChatTipBean; +import com.fengliyan.tianlesue.model.news.CustomRemarkBean; +import com.fengliyan.tianlesue.model.news.IMCostBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; + +public class NewsManager { + public static void sendIMCost(BaseActivity activity, + final int type, + final String toUid, + final String content, + final String is_greet, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SEND_IM_COST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("to_uid", toUid) + .addParam("content", content + "") + .addParam("is_greet", is_greet) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 聊天界面提示 + * + * @param activity + * @param httpUiCallBack + */ + public static void getChatTip(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CHAT_TIP; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + +// task.start(); + task.start(false); + } + + public static void getChatSetting(BaseActivity activity, final int user_id, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CHAT_SETTING; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", user_id + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); +// task.start(false); + } + + public static void get_remark(BaseActivity activity, final int user_id, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_REMARK; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", user_id + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); +// task.start(false); + } + + + public static void remark(BaseActivity activity, final int user_id, final String remark, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.REMARK; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("user_id", user_id + "") + .addParam("remark", remark) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 打招呼 + */ + public static void sendIMHello(BaseActivity activity, + final String toUid, + final String content, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SEND_IM_COST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", "1") + .addParam("to_uid", toUid) + .addParam("content", content) + .addParam("sayhello", "1") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getGuardInfo(BaseActivity activity, final String user_id, + HttpUiCallBack httpUiCallBack) { + new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GETGUARDINFO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("to_uid", user_id) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }.start(); + } + + public static void getChatWordList(BaseActivity activity, final String to_user_id, + HttpUiCallBack httpUiCallBack) { + new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_CHAT_WORD_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("to_user_id", to_user_id) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }.start(); + } + + public static void call_delete(BaseActivity activity, int id, int type, HttpUiCallBack httpUiCallBack) { + new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CALL_DELETE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("id", id + "") + .addParam("type", type + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }.start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/rank/MibiRankAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/rank/MibiRankAdapter.java new file mode 100644 index 0000000..24ef161 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/rank/MibiRankAdapter.java @@ -0,0 +1,116 @@ +package com.fengliyan.tianlesue.controller.rank; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/3/4. + */ + +public class MibiRankAdapter extends BaseAdapter { + + private List mBeans = new ArrayList<>(); + private Context mContext; + + public MibiRankAdapter(Context context) { + mContext = context; + } + + public void setData(List beans) { + mBeans = beans; + } + + @Override + public int getCount() { + return mBeans.size(); + } + + @Override + public Object getItem(int i) { + return mBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final NewRankBean bean = mBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_mibi_rank, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + holder.photo.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.name.setText(bean.getNickname()); +// holder.location.setText(bean.getCity() + "|" + bean.getAge() + "岁"); +// setTextMoney(holder.count, bean.getTotalMoney()); + holder.count.setText(bean.getGap()); + + holder.rlItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (bean.getUser_id() != 0) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUser_id()); + mContext.startActivity(intent); + } + } + }); + + view.setTag(holder); + return view; + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, double totalMoney) { + if (totalMoney >= 10000) { + double money = totalMoney / 10000; + view.setText("剩余" + String.format("%.1f", money) + "万个金币"); + } else { + view.setText("剩余" + String.format("%.0f", totalMoney) + "个金币"); + } + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.photo = v.findViewById(R.id.user_photo); + holder.name = v.findViewById(R.id.user_name); + holder.location = v.findViewById(R.id.user_location); + holder.count = v.findViewById(R.id.tv_count); + holder.rlItem = v.findViewById(R.id.user_background); + return holder; + } + + class Holder { + SimpleDraweeView photo; + TextView name; + TextView location; + TextView count; + RelativeLayout rlItem; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/register/manager/RegisterManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/register/manager/RegisterManager.java new file mode 100644 index 0000000..1228b3b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/register/manager/RegisterManager.java @@ -0,0 +1,256 @@ +package com.fengliyan.tianlesue.controller.register.manager; + +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.login.bean.NickNameBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; + +import java.util.Map; + +/** + * Created by abby on 2018/4/7. + */ + +public class RegisterManager { + public static void register(BaseActivity activity, + final String userName, + final String password, + final String inviteCode, + final String agreement, + final String authCode, + final boolean shouldShowWaitingView, String risk_engine_token, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.REGISTER; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("mobile", userName) + .addParam("password", password) + .addParam("phone_code", authCode) + .addParam("agreement", agreement) + .addParam("x-risk-engine-token", risk_engine_token); +// builder.setExt(risk_engine_token); + if (null != inviteCode) { + builder.addParam("invite_code", inviteCode); + } + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.setShowWaitingDialog(shouldShowWaitingView); + task.start(); + } + + public static void sendAuthCode(BaseActivity activity, + final String phoneNumber, + final String code, + final String type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SEND_CODE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("mobile", phoneNumber); + builder.addParam("type", type); + builder.addParam("code", code.trim()); + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 修改手机号前校验验证码 + * + * @param activity + * @param phone_code + * @param httpUiCallBack + */ + public static void beforeChangeMobile(BaseActivity activity, final String phone_code, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.BEFORE_CHANGE_MOBILE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("phone_code", phone_code); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 修改新手机号 + */ + public static void submitChangeMobile(BaseActivity activity, final String old_phone_code, String phone_code, String mobile, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SUBMIT_CHANGE_MOBILE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("old_phone_code", old_phone_code); + builder.addParam("phone_code", phone_code); + builder.addParam("mobile", mobile); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 修改设置密码 + */ + public static void editUserPwd(BaseActivity activity, final String password, String again_password, String old_password, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.EDIT_USER_PWD; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("password", password); + builder.addParam("again_password", again_password); + builder.addParam("old_password", old_password); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 获取图片验证码 + * + * @param activity + * @param httpUiCallBack + */ + + public static void getPicCode(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SEND_PIC_CODE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + + public static void completeProfile(BaseActivity activity, final Map map, + HttpUiCallBack httpUiCallBack) { + + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.COMPLETE_PROFILE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("nickname", (String) map.get("nickname")); + builder.addParam("gender", (String) map.get("gender")); + if (null != map.get("avatar") && !"null".equals(map.get("avatar"))) { + builder.addParam("avatar", (String) map.get("avatar")); + } + if (null != map.get("video_url") && !"null".equals(map.get("video_url"))) { + builder.addParam("video_url", (String) map.get("video_url")); + builder.addParam("video_img", (String) map.get("video_img")); + } + builder.addParam("cityId", (String) map.get("city")); + builder.addParam("birthday", (String) map.get("birthday")); + builder.addParam("job", (String) map.get("job")); + builder.addParam("del_video", (String) map.get("del_video")); + if (null != map.get("inviteId") && !"".equals(map.get("inviteId"))) { + builder.addParam("invite_code", (String) map.get("inviteId")); + } + + if (null != map.get("albums") && !"".equals(map.get("albums"))) { + builder.addParam("albums", (String) map.get("albums")); + } + if (null != map.get("signature") && !"".equals(map.get("signature"))) { + builder.addParam("signature", (String) map.get("signature")); + } + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void uploadPhoto(BaseActivity activity, + final UploadFile[] uploadFiles, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.UPLOAD_PHOTO; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType( + new TType>() { + + }).setHttpMethod(HttpMethod.POST).setUrl(url); + + builder.addUploadFiles(uploadFiles); + return builder.build().upload(); + } + }; + + task.start(); + } + + public static void getNickname(BaseActivity activity, final String gender, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GETNICKNAME; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).setUrl(url); + builder.addParam("gender", gender); + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/AddSkillRecyclerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/AddSkillRecyclerAdapter.java new file mode 100644 index 0000000..190c740 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/AddSkillRecyclerAdapter.java @@ -0,0 +1,112 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ViewHolder; +import com.fengliyan.tianlesue.model.main.SkillAnchorBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +public class AddSkillRecyclerAdapter extends RecyclerView.Adapter { + private List mSkillList = new ArrayList<>(); + private Context mContext; + private OnItemClickListener mListener; + + public void setOnItemClickListener(OnItemClickListener listener) { + mListener = listener; + } + + public interface OnItemClickListener { + void onItemClicked(View v, int position); + } + + public AddSkillRecyclerAdapter(Context context) { + mContext = context; + } + + public void setSkillList(List list) { + mSkillList = list; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_all_channels, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + SkillAnchorBean bean = mSkillList.get(position); + Holder dataHolder = (Holder) holder; + dataHolder.mLogo.setImageURI(StrU.getResourcePath(bean.getIcon(), mContext)); + dataHolder.mName.setText(bean.getName()); + final int finalPos = position; + int status = bean.getStatus(); + dataHolder.mStatus.setVisibility(View.GONE); + dataHolder.mSelected.setVisibility(View.GONE); +// Log.d("nail","getIs_add===" + bean.getIs_add()); +// Log.d("nail","getStatus===" + bean.getStatus()); + if (bean.getIs_add() == 1) { + dataHolder.mStatus.setVisibility(View.VISIBLE); + dataHolder.mSelected.setVisibility(View.GONE); + dataHolder.mStatus.setText("已通过"); + dataHolder.mStatus.setEnabled(true); + } else if (status == 1) { + dataHolder.mStatus.setVisibility(View.VISIBLE); + dataHolder.mSelected.setVisibility(View.GONE); + dataHolder.mStatus.setText("审核中"); + dataHolder.mStatus.setEnabled(false); + + } else if (status == 2) { + dataHolder.mStatus.setVisibility(View.VISIBLE); + dataHolder.mSelected.setVisibility(View.GONE); + dataHolder.mStatus.setText("不可用"); + dataHolder.mStatus.setEnabled(false); + + } else if (status == 3) { + dataHolder.mStatus.setVisibility(View.GONE); + dataHolder.mSelected.setVisibility(View.VISIBLE); + } + + dataHolder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onItemClicked(view, finalPos); + } + } + }); + } + + @Override + public int getItemCount() { + return mSkillList.size(); + } + + public class Holder extends ViewHolder { + SimpleDraweeView mLogo; + TextView mName; + TextView mStatus; + View mSelected; + View mThisView; + + public Holder(Context context, View itemView) { + super(context, itemView); + mLogo = itemView.findViewById(R.id.all_channels_logo); + mName = itemView.findViewById(R.id.all_channels_name); + mStatus = itemView.findViewById(R.id.all_channels_status); + mSelected = itemView.findViewById(R.id.all_channels_selected); + mThisView = itemView; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/BillAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/BillAdapter.java new file mode 100644 index 0000000..7cb7e98 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/BillAdapter.java @@ -0,0 +1,94 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.settings.BillBean; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +import java.util.ArrayList; +import java.util.List; + +public class BillAdapter extends BaseAdapter { + private List mBillList = new ArrayList<>(); + private Context mContext; + + public BillAdapter(Context context) { + mContext = context; + } + + public void setBillList(List beans) { + mBillList = beans; + } + + @Override + public int getCount() { + return mBillList.size(); + } + + @Override + public Object getItem(int i) { + return mBillList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + BillBean bean = mBillList.get(i); + if (view == null) { + view = View.inflate(mContext, R.layout.item_bill, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + holder.mLogo.setImageURI(StrU.getResourcePath(bean.getIcon(), mContext)); + holder.mName.setText(bean.getSystem_str()); + holder.mDate.setText(bean.getCreate_time()); + holder.mItem.setText(bean.getChange_value() + " 金币"); + if (bean.getChange_value().startsWith("-")) { + holder.mItem.setTextColor(mContext.getResources().getColor(R.color.giftText2)); + } else { + holder.mItem.setTextColor(mContext.getResources().getColor(R.color.mainColor)); + } + holder.mLogo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (bean.getTrack_user_id() != 0 && bean.getTrack_user_id() != 2 && bean.getTrack_user_id() != 11) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getTrack_user_id()); + mContext.startActivity(intent); + } + } + }); + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.mLogo = v.findViewById(R.id.bill_logo); + holder.mName = v.findViewById(R.id.bill_name); + holder.mDate = v.findViewById(R.id.bill_date); + holder.mItem = v.findViewById(R.id.bill_item); + return holder; + } + + class Holder { + SimpleDraweeView mLogo; + TextView mName; + TextView mDate; + TextView mItem; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/CallbackItemTouch.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/CallbackItemTouch.java new file mode 100644 index 0000000..1108c0e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/CallbackItemTouch.java @@ -0,0 +1,5 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +public interface CallbackItemTouch { + void itemTouchOnMove(int oldPosition,int newPosition); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/GeneralOptionsRecyclerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/GeneralOptionsRecyclerAdapter.java new file mode 100644 index 0000000..5849e12 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/GeneralOptionsRecyclerAdapter.java @@ -0,0 +1,228 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ViewHolder; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.MemberPrivilegesInfo; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.MemberRechargeDialog; +import com.fengliyan.tianlesue.view.base.utils.view.MemberTipsDialog; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/5/15. + */ + +public class GeneralOptionsRecyclerAdapter extends RecyclerView.Adapter { + + private List mOptions = new ArrayList<>(); + private Context mContext; + private int vipType; + private String vip_day_free_send = "100"; + + public GeneralOptionsRecyclerAdapter(Context context, int vipType) { + mContext = context; + this.vipType = vipType; + } + + public void setOptions(List list) { + mOptions = list; + notifyDataSetChanged(); + Log.i("TAG", "setOptions: mOptions---->" + mOptions.size()); + } + + public List getmOptions() { + return mOptions; + } + + public void setVip_day_free_send(String vip_day_free_send) { + this.vip_day_free_send = vip_day_free_send; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_general_option, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + MemberPrivilegesInfo options = mOptions.get(position); + Holder dataHolder = (Holder) holder; + if (vipType == 0) { +// dataHolder.cl_privilege.setBackgroundResource(R.drawable.member_privilege_bg); + dataHolder.iv_privilege_tip.setImageResource(R.drawable.ic_privilege_tip); +// dataHolder.tv_member_privilege_name.setTextColor(Color.parseColor("#61380C")); +// dataHolder.tv_privilege_dec.setTextColor(Color.parseColor("#A6793E")); + } else { +// dataHolder.cl_privilege.setBackgroundResource(R.drawable.super_member_privilege_bg); + dataHolder.iv_privilege_tip.setImageResource(R.drawable.ic_privilege_tip1); +// dataHolder.tv_member_privilege_name.setTextColor(Color.parseColor("#DDD6FF")); +// dataHolder.tv_privilege_dec.setTextColor(Color.parseColor("#AAA0F0")); + } + switch (options.getId()) { + case 0: + if (vipType == 0) { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_privilege1); + dataHolder.tv_member_privilege_name.setText("私信畅聊特权"); + dataHolder.tv_privilege_dec.setText(options.getDesc()); + dataHolder.iv_privilege_tip.setVisibility(View.GONE); + } else { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_super_privilege1); + dataHolder.tv_member_privilege_name.setText("加送金币"); + dataHolder.tv_privilege_dec.setText("额外赠送金币"); + if (TextUtils.equals("VISIBLE", options.getName())) { + dataHolder.iv_privilege_tip.setVisibility(View.VISIBLE); + dataHolder.iv_privilege_tip.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getGoodsList(); + } + }); + } else { + dataHolder.iv_privilege_tip.setVisibility(View.GONE); + } + } + break; + case 1: + if (vipType == 0) { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_privilege4); + } else { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_super_privilege2); + } + dataHolder.tv_member_privilege_name.setText("视频畅聊卡"); + dataHolder.tv_privilege_dec.setText(options.getDesc()); + dataHolder.iv_privilege_tip.setVisibility(View.GONE); + dataHolder.iv_privilege_tip.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MemberTipsDialog tipsDialog = new MemberTipsDialog(mContext, "隐身功能,开启后您的上线、榜单、充值、登录、访问都会隐身,并且群发和速配免打扰。"); + tipsDialog.show(); + } + }); + break; + case 2: + if (vipType == 0) { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_privilege3); + } else { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_super_privilege3); + } + dataHolder.tv_member_privilege_name.setText("充值加送金币"); + dataHolder.tv_privilege_dec.setText("额外赠送金币"); +// if (TextUtils.equals("VISIBLE", options.getName())) { +// dataHolder.iv_privilege_tip.setVisibility(View.VISIBLE); +// dataHolder.iv_privilege_tip.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// MemberTipsDialog tipsDialog = new MemberTipsDialog(mContext, "专属客服微信号: Zdhfa1234"); +// tipsDialog.show(); +// } +// }); +// } else { + dataHolder.iv_privilege_tip.setVisibility(View.GONE); +// } + break; + case 3: + if (vipType == 0) { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_privilege7); + } else { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_super_privilege7); + } + dataHolder.tv_member_privilege_name.setText("消息读取状态"); + dataHolder.tv_privilege_dec.setText("可查看是否已读"); + dataHolder.iv_privilege_tip.setVisibility(View.GONE); + break; + case 4: + if (vipType == 0) { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_privilege5); + } else { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_super_privilege4); + } + dataHolder.tv_member_privilege_name.setText("专属会员标识"); + dataHolder.tv_privilege_dec.setText("头像框、聊天气泡"); + dataHolder.iv_privilege_tip.setVisibility(View.GONE); + break; + case 5: + if (vipType == 0) { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_privilege2); + } else { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_super_privilege5); + } + dataHolder.tv_member_privilege_name.setText("隐身模式"); + dataHolder.tv_privilege_dec.setText("全平台隐身畅玩"); + dataHolder.iv_privilege_tip.setVisibility(View.GONE); + break; + case 6: + if (vipType == 0) { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_privilege6); + } else { + dataHolder.iv_privilege_img.setImageResource(R.drawable.ic_super_privilege6); + } + dataHolder.tv_member_privilege_name.setText("聊天气泡框"); + dataHolder.tv_privilege_dec.setText("VIP专属聊天框"); + dataHolder.iv_privilege_tip.setVisibility(View.GONE); + break; + } + } + + @Override + public int getItemCount() { + return mOptions.size(); + } + + + public class Holder extends ViewHolder { + ImageView iv_privilege_img; + TextView tv_member_privilege_name; + TextView tv_privilege_dec; + ImageView iv_privilege_tip; + ConstraintLayout cl_privilege; + + public Holder(Context context, View itemView) { + super(context, itemView); + iv_privilege_img = itemView.findViewById(R.id.iv_privilege_img); + tv_member_privilege_name = itemView.findViewById(R.id.tv_member_privilege_name); + tv_privilege_dec = itemView.findViewById(R.id.tv_privilege_dec); + iv_privilege_tip = itemView.findViewById(R.id.iv_privilege_tip); + cl_privilege = itemView.findViewById(R.id.cl_privilege); + } + } + + private void getGoodsList() { + SettingManager.getRechargeInfo((BaseActivity) mContext, 6, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RechargeListBean result, String message) { + if (result != null && result.getList() != null && result.getList().size() > 0) { + MemberRechargeDialog memberRechargeDialog = new MemberRechargeDialog(activity, result.getList()); + memberRechargeDialog.show(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoHolder.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoHolder.java new file mode 100644 index 0000000..04699ab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoHolder.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; + +import android.view.View; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ViewHolder; +import com.facebook.drawee.view.SimpleDraweeView; + +public class InfoEditPhotoHolder extends ViewHolder { + SimpleDraweeView mPhotoView; + SimpleDraweeView mHeadPhotoView; + View mEmptyView; + View mDeleteView; + View mSelectorView; + + public InfoEditPhotoHolder(Context context, View itemView){ + super(context, itemView); + mPhotoView = itemView.findViewById(R.id.info_edit_photo_normal); + mHeadPhotoView = itemView.findViewById(R.id.info_edit_photo_header); + mEmptyView = itemView.findViewById(R.id.info_edit_photo_empty); + mDeleteView = itemView.findViewById(R.id.info_edit_photo_delete); + mSelectorView = itemView.findViewById(R.id.info_edit_photo_selector); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoRecyclerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoRecyclerAdapter.java new file mode 100644 index 0000000..d8d099f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoRecyclerAdapter.java @@ -0,0 +1,198 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import static android.view.View.GONE; + +import android.app.Activity; +import android.content.Context; +import android.os.SystemClock; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.utils.SimpleItemTouchCallBack; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class InfoEditPhotoRecyclerAdapter extends RecyclerView.Adapter implements SimpleItemTouchCallBack.TouchCallBack { + private List mPhotoList = new ArrayList<>(); + private Context mContext; + private OnSelectorClickedListener mSelectorListener; + + public InfoEditPhotoRecyclerAdapter(Context context) { + mContext = context; + } + + public void setPhotoList(List photoList) { + mPhotoList = photoList; + } + + @Override + public void onItemMove(int fromPosition, int toPosition) { + //交换集合中两个数据的位置 + String toStr = mPhotoList.get(toPosition); + String fromStr = mPhotoList.get(fromPosition); + if (!TextUtils.isEmpty(fromStr) && !TextUtils.isEmpty(toStr) && !toStr.contains("selector") && !fromStr.contains("selector")) { + if (Math.abs(toPosition - fromPosition) <= 1) { + Collections.swap(mPhotoList, fromPosition, toPosition); + } else { + if (toPosition > fromPosition) { + for (int i = fromPosition; i < toPosition; i++) { + mPhotoList.set(i, mPhotoList.get(i + 1)); + } + } + if (toPosition < fromPosition) { + for (int i = fromPosition; i > toPosition; i--) { + mPhotoList.set(i, mPhotoList.get(i - 1)); + } + } + mPhotoList.set(toPosition, fromStr); + } + //刷新界面,局部刷新,索引会混乱 + notifyItemMoved(fromPosition, toPosition); + } + } + + @Override + public void onItemDelete(int position) { + /*goldTitleBeans.remove(position); + //局部刷新,索引会混乱+集合越界 + notifyItemRemoved(position);*/ + } + + @Override + public void animationDuration(final long time) { + new Thread(new Runnable() { + @Override + public void run() { + SystemClock.sleep(time); + ((Activity) mContext).runOnUiThread(new Runnable() { + @Override + public void run() { + //待动画执行完成后,整体刷新条目,保证数据和显示UI一一对应 + notifyDataSetChanged(); + } + }); + } + }).start(); + } + + public interface OnSelectorClickedListener { + void onSelectorClicked(); + + void onClickImage(List mPhotoList, int position); + } + + public void setOnSelectorClickedListener(OnSelectorClickedListener listener) { + mSelectorListener = listener; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_info_edit_photo, null); + return new InfoEditPhotoHolder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + String imagePath = mPhotoList.get(position); + InfoEditPhotoHolder dataHolder = (InfoEditPhotoHolder) holder; + if ("".equals(imagePath)) { + dataHolder.mDeleteView.setVisibility(GONE); + dataHolder.mHeadPhotoView.setVisibility(GONE); + dataHolder.mPhotoView.setVisibility(GONE); + dataHolder.mSelectorView.setVisibility(GONE); + dataHolder.mEmptyView.setVisibility(View.VISIBLE); + dataHolder.mEmptyView.setOnClickListener(null); + } else if ("selector".equals(imagePath)) { + dataHolder.mDeleteView.setVisibility(GONE); + dataHolder.mHeadPhotoView.setVisibility(GONE); + dataHolder.mPhotoView.setVisibility(GONE); + dataHolder.mSelectorView.setVisibility(View.VISIBLE); + dataHolder.mEmptyView.setVisibility(View.VISIBLE); + dataHolder.mEmptyView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mSelectorListener) { + mSelectorListener.onSelectorClicked(); + } + } + }); + + } else if (0 == position) { + dataHolder.mDeleteView.setVisibility(View.VISIBLE); + dataHolder.mHeadPhotoView.setVisibility(View.VISIBLE); + dataHolder.mPhotoView.setVisibility(GONE); + dataHolder.mEmptyView.setVisibility(GONE); + if (imagePath.contains("uploads/")) { + dataHolder.mHeadPhotoView.setImageURI(StrU.getResourcePath(imagePath, mContext)); + } else { + dataHolder.mHeadPhotoView.setImageURI("file://" + imagePath); + } + + } else { + dataHolder.mDeleteView.setVisibility(View.VISIBLE); + dataHolder.mHeadPhotoView.setVisibility(View.GONE); + dataHolder.mPhotoView.setVisibility(View.VISIBLE); + dataHolder.mEmptyView.setVisibility(GONE); + if (imagePath.contains("uploads/")) { + dataHolder.mPhotoView.setImageURI(StrU.getResourcePath(imagePath, mContext)); + } else { + dataHolder.mPhotoView.setImageURI("file://" + imagePath); + } + } + + dataHolder.mHeadPhotoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mSelectorListener) { + mSelectorListener.onClickImage(mPhotoList, position); + } + } + }); + + dataHolder.mPhotoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mSelectorListener) { + mSelectorListener.onClickImage(mPhotoList, position); + } + } + }); + + dataHolder.mDeleteView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + List temp = mPhotoList; + mPhotoList.remove(position); + boolean flag = false; + if (position >= 5) { + flag = false; + } else { + for (String s : temp) { + if (s.contains("selector")) { + flag = true; + } + } + } + mPhotoList.add(flag ? "" : "selector"); + notifyDataSetChanged(); + } + }); + } + + @Override + public int getItemCount() { + return mPhotoList.size(); + } + + public List getmPhotoList() { + return mPhotoList; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoTouchHelperCallback.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoTouchHelperCallback.java new file mode 100644 index 0000000..f211aea --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InfoEditPhotoTouchHelperCallback.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + +public class InfoEditPhotoTouchHelperCallback extends ItemTouchHelper.Callback { + CallbackItemTouch callbackItemTouch; // interface + + public InfoEditPhotoTouchHelperCallback(CallbackItemTouch callbackItemTouch){ + this.callbackItemTouch = callbackItemTouch; + } + + @Override + public boolean isLongPressDragEnabled() { + return true; + } + + @Override + public boolean isItemViewSwipeEnabled() { + return false; // swiped disabled + } + + @Override + public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + + int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN + | ItemTouchHelper.LEFT + | ItemTouchHelper.RIGHT; // movements drag + return makeFlag( ItemTouchHelper.ACTION_STATE_DRAG , dragFlags); + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + callbackItemTouch.itemTouchOnMove(viewHolder.getAdapterPosition(),target.getAdapterPosition()); + return true; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InviteAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InviteAdapter.java new file mode 100644 index 0000000..dfcaadc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InviteAdapter.java @@ -0,0 +1,84 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.settings.SocialBean; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2018/11/23. + */ + +public class InviteAdapter extends BaseAdapter { + + + private List mUserList = new ArrayList<>(); + private Context mContext; + + public InviteAdapter(Context context) { + mContext = context; + } + + public void setUserList(List list) { + mUserList = list; + } + + @Override + public int getCount() { + return mUserList.size(); + } + + @Override + public Object getItem(int i) { + return mUserList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + SocialBean bean = mUserList.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_invite_list, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + holder.photo.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.name.setText(bean.getNickname()); + holder.location.setText(bean.getCity() + "|" + bean.getAge() + "岁"); + holder.time.setText("绑定时间:" + bean.getAdd_time()); + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.photo = v.findViewById(R.id.user_photo); + holder.name = v.findViewById(R.id.user_name); + holder.location = v.findViewById(R.id.user_location); + holder.time = v.findViewById(R.id.user_time); + return holder; + } + + class Holder { + SimpleDraweeView photo; + TextView name; + TextView location; + TextView time; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InviteRechargeAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InviteRechargeAdapter.java new file mode 100644 index 0000000..a6bac70 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/InviteRechargeAdapter.java @@ -0,0 +1,163 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ClipboardUtil; +import com.fengliyan.tianlesue.model.settings.InviteDataListBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +import java.util.ArrayList; +import java.util.List; + +public class InviteRechargeAdapter extends RecyclerView.Adapter { + private List mRechargeList = new ArrayList<>(); + private Context mContext; + private int mItemType = 1;//邀请类型 1=直接2=间接 + + public interface OnItemClickListener { + void onItemClicked(View v, int position); + } + + public InviteRechargeAdapter(Context context) { + mContext = context; + } + + public void setRechargeList(List list) { + mRechargeList = list; + notifyDataSetChanged(); + } + + public void setmItemType(int mItemType) { + this.mItemType = mItemType; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_invite_recharge_data, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + InviteDataListBean.InviteListBean bean = mRechargeList.get(position); + final Holder dataHolder = (Holder) holder; + if (bean != null) { + dataHolder.iv_user_avatar.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + dataHolder.tv_user_name.setText(bean.getNickname()); + dataHolder.tv_user_code.setText("(" + bean.getUsercode() + ")"); + dataHolder.tv_time.setText(bean.getCreate_at()); + if (mItemType == 1) { + dataHolder.tv_invite_user.setVisibility(View.GONE); + dataHolder.tv_invite_user.setText(""); + } else { + String s = "邀请人:" + bean.getInvite_nickname() + "(" + bean.getInvite_usercode() + ")"; + StrU.setSpanTextColor(s, 4, s.length(), dataHolder.tv_invite_user, R.color.invite_text_color, mContext); + if (!StrU.isEmpty(bean.getInvite_usercode())) { + dataHolder.tv_invite_user.setVisibility(View.VISIBLE); + } else { + dataHolder.tv_invite_user.setVisibility(View.GONE); + } + } + if (bean.getRecharge_type() == 1) { + dataHolder.tv_recharge_amount.setText("充值金币:" + bean.getAmount() + "元"); + dataHolder.tv_divide_amount.setText("充值分成:" + bean.getDivide_amount() + "元"); + } else if (bean.getRecharge_type() == 2) { + dataHolder.tv_recharge_amount.setText("充值会员:" + bean.getAmount() + "元"); + dataHolder.tv_divide_amount.setText("会员分成:" + bean.getDivide_amount() + "元"); + } else if (bean.getRecharge_type() == 3) { + dataHolder.tv_recharge_amount.setText("通话收益:" + bean.getAmount() + "元"); + dataHolder.tv_divide_amount.setText("收益分成:" + bean.getDivide_amount() + "元"); + } else if (bean.getRecharge_type() == 4) { + dataHolder.tv_recharge_amount.setText("礼物收益:" + bean.getAmount() + "元"); + dataHolder.tv_divide_amount.setText("收益分成:" + bean.getDivide_amount() + "元"); + } + dataHolder.iv_user_avatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (bean.getUser_id() != 0) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUser_id()); + mContext.startActivity(intent); + } + } + }); + dataHolder.tv_user_name.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (bean.getUser_id() != 0) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUser_id()); + mContext.startActivity(intent); + } + } + }); + dataHolder.tv_user_code.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (bean.getUser_id() != 0) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUser_id()); + mContext.startActivity(intent); + } + } + }); + dataHolder.tv_invite_user.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (bean.getInvite_user_id() != 0) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getInvite_user_id()); + mContext.startActivity(intent); + } + } + }); + dataHolder.iv_copy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + ClipboardUtil.clipboardCopyText(mContext, bean.getUsercode()); + } + }); + } + } + + @Override + public int getItemCount() { + return mRechargeList.size(); + } + + public class Holder extends ViewHolder { + SimpleDraweeView iv_user_avatar; + TextView tv_user_name; + TextView tv_user_code; + ImageView iv_copy; + TextView tv_time; + TextView tv_invite_user; + TextView tv_recharge_amount; + TextView tv_divide_amount; + + + public Holder(Context context, View itemView) { + super(context, itemView); + iv_user_avatar = itemView.findViewById(R.id.iv_user_avatar); + tv_user_name = itemView.findViewById(R.id.tv_user_name); + tv_user_code = itemView.findViewById(R.id.tv_user_code); + iv_copy = itemView.findViewById(R.id.iv_copy); + tv_time = itemView.findViewById(R.id.tv_time); + tv_invite_user = itemView.findViewById(R.id.tv_invite_user); + tv_recharge_amount = itemView.findViewById(R.id.tv_recharge_amount); + tv_divide_amount = itemView.findViewById(R.id.tv_divide_amount); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/MemberRechargeAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/MemberRechargeAdapter.java new file mode 100644 index 0000000..cc3ecfe --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/MemberRechargeAdapter.java @@ -0,0 +1,71 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ViewHolder; +import com.fengliyan.tianlesue.model.settings.RechargeBean; + +import java.util.ArrayList; +import java.util.List; + +public class MemberRechargeAdapter extends RecyclerView.Adapter { + private List mRechargeList = new ArrayList<>(); + private Context mContext; + + public interface OnItemClickListener { + void onItemClicked(View v, int position); + } + + public MemberRechargeAdapter(Context context) { + mContext = context; + } + + public void setRechargeList(List list) { + mRechargeList = list; + notifyDataSetChanged(); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_dialog_recharge, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + RechargeBean bean = mRechargeList.get(position); + final Holder dataHolder = (Holder) holder; + + if (bean != null) { + if (bean.getSvip_show_reward() > 0) { + dataHolder.mGift.setText("送" + bean.getSvip_show_reward() + "金币"); + } else { + dataHolder.mGift.setText("无赠送"); + } + dataHolder.mPrice.setText(bean.getPrice() + "元"); + } + } + + @Override + public int getItemCount() { + return mRechargeList.size(); + } + + public class Holder extends ViewHolder { + TextView mPrice; + TextView mGift; + + public Holder(Context context, View itemView) { + super(context, itemView); + mPrice = itemView.findViewById(R.id.tv_recharge_price); + mGift = itemView.findViewById(R.id.tv_recharge_gift); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/MyItemsAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/MyItemsAdapter.java new file mode 100644 index 0000000..90970c7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/MyItemsAdapter.java @@ -0,0 +1,162 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.settings.BackPackListBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +public class MyItemsAdapter extends BaseAdapter { + private List mItemsBeans = new ArrayList<>(); + private Context mContext; + private int mType; + private OnButtonClickedListener mListener; + private OnItemClickedListener mItemListener; + + + public MyItemsAdapter(Context context) { + mContext = context; + } + + public void setOnButtonClickedListener(OnButtonClickedListener listener) { + mListener = listener; + } + + public void setOnItemClickedListener(OnItemClickedListener listener) { + mItemListener = listener; + } + + public void setItemsBeans(List beans) { + mItemsBeans = beans; + } + + public void setSocialType(int type) { + mType = type; + } + + public interface OnButtonClickedListener { + void onCliked(int position); + } + + public interface OnItemClickedListener { + void onClicked(int position); + } + + @Override + public int getCount() { + return mItemsBeans.size(); + } + + @Override + public Object getItem(int i) { + return mItemsBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(final int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final BackPackListBean.BackPackBean bean = mItemsBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_items_list, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + if (bean != null) { + holder.tv_item_name.setText(bean.getPrize_name()); +// holder.tv_item_num.setText("x" + bean.getNum()); +// holder.tv_items_dec.setText(bean.getUse_effect()); + holder.tv_items_time.setText(bean.getExpire_date_desc()); + if (StrU.equals("3", bean.getPrize_type()) || StrU.equals("4", bean.getPrize_type())) { + holder.tv_items_time.setVisibility(View.GONE); + } else { + holder.tv_items_time.setVisibility(View.VISIBLE); + } + Glide.with(mContext).load(ConstUrl.BASE_ROOT + bean.getPrize_url()).into(holder.iv_items); + + if (StrU.equals("1", bean.getUser_btn())) { + holder.tv_items_use.setEnabled(true); + holder.tv_items_use.setText("去使用"); + holder.tv_items_use.setVisibility(View.VISIBLE); + holder.tv_items_surplus_num_desc.setVisibility(View.GONE); + holder.tv_items_surplus_desc.setVisibility(View.GONE); + } else { + if (StrU.equals("6", bean.getPrize_type())) { + holder.tv_items_use.setText("已使用"); + holder.tv_items_use.setEnabled(false); + holder.tv_items_use.setVisibility(View.VISIBLE); + holder.tv_items_surplus_num_desc.setVisibility(View.GONE); + holder.tv_items_surplus_desc.setVisibility(View.GONE); + } else { + holder.tv_items_use.setText(""); + holder.tv_items_use.setEnabled(false); + holder.tv_items_use.setVisibility(View.GONE); + holder.tv_items_surplus_num_desc.setVisibility(View.VISIBLE); + holder.tv_items_surplus_desc.setText(bean.getSurplus_desc()); + if (StrU.isEmpty(bean.getSurplus_desc())) { + holder.tv_items_surplus_desc.setVisibility(View.GONE); + } else { + holder.tv_items_surplus_desc.setVisibility(View.VISIBLE); + } + String s = bean.getSurplus_num_desc(); + if (s.contains(bean.getSurplus_num())) { + StrU.setSpanTextSize(bean.getSurplus_num_desc(), s.indexOf(bean.getSurplus_num()), bean.getSurplus_num().length(), holder.tv_items_surplus_num_desc, 18); + } else { + holder.tv_items_surplus_num_desc.setText(bean.getSurplus_num_desc()); + } + } + } + } + + holder.tv_items_use.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onCliked(i); + } + } + }); + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.iv_items = v.findViewById(R.id.iv_items); + holder.tv_item_name = v.findViewById(R.id.tv_item_name); + holder.tv_item_num = v.findViewById(R.id.tv_item_num); + holder.tv_items_dec = v.findViewById(R.id.tv_items_dec); + holder.tv_items_time = v.findViewById(R.id.tv_items_time); + holder.tv_items_use = v.findViewById(R.id.tv_items_use); + holder.tv_items_surplus_num_desc = v.findViewById(R.id.tv_items_surplus_num_desc); + holder.tv_items_surplus_desc = v.findViewById(R.id.tv_items_surplus_desc); + return holder; + } + + class Holder { + ImageView iv_items; + TextView tv_item_name; + TextView tv_item_num; + TextView tv_items_dec; + TextView tv_items_time; + TextView tv_items_use; + TextView tv_items_surplus_num_desc; + TextView tv_items_surplus_desc; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/RechargeAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/RechargeAdapter.java new file mode 100644 index 0000000..b039213 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/RechargeAdapter.java @@ -0,0 +1,197 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; + +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ViewHolder; +import com.fengliyan.tianlesue.model.settings.RechargeBean; +import com.fengliyan.tianlesue.utils.StrU; + +import java.util.ArrayList; +import java.util.List; + +public class RechargeAdapter extends RecyclerView.Adapter { + private List mRechargeList = new ArrayList<>(); + private Context mContext; + private OnItemClickListener mListener; + public int mSelectedPosition = 1; + private int mType; + public boolean isQuick = false; + + public boolean isWXRecharge() { + return isWXRecharge; + } + + public void setWXRecharge(boolean WXRecharge) { + isWXRecharge = WXRecharge; + } + + private boolean isWXRecharge;//微信充值不要底部的字 + + public void setOnItemClickListener(OnItemClickListener listener) { + mListener = listener; + } + + public interface OnItemClickListener { + void onItemClicked(View v, int position); + } + + public RechargeAdapter(Context context) { + mContext = context; + } + + public void setRechargeList(List list) { + mRechargeList = list; + } + + public void setSelectedPosition(int position) { + mSelectedPosition = position; + } + + public void setType(int type) { + mType = type; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_recharge, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + RechargeBean bean = mRechargeList.get(position); + final Holder dataHolder = (Holder) holder; + final int finalPos = position; + + dataHolder.mGift.setVisibility(View.GONE); + if (0 == mType) { + dataHolder.mPrice.setText(bean.getAmount() + "金币"); + if (!isWXRecharge) { + dataHolder.mGift.setVisibility(View.VISIBLE); + if (0 != bean.getReward()) { + dataHolder.mGift.setText("SVIP赠" + bean.getReward() + "币"); + } else { + dataHolder.mGift.setText("无赠送"); + } + } + + + dataHolder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onItemClicked(dataHolder.mThisView, finalPos); + } + } + }); + } else if (1 == mType) { + + //如果是快捷充值,最后一个不显示 + if (isQuick && position == mRechargeList.size() - 1) { + dataHolder.mPrice.setText("… …"); + } else { + dataHolder.mPrice.setText(bean.getAmount() + "金币"); + } + + //有首冲默认展示首冲,否则按照以前的逻辑 + if (bean.getFirst_rechange_reward() > 0) { + dataHolder.firstImageView.setVisibility(View.VISIBLE); + dataHolder.mGift.setText("首冲赠送" + bean.getFirst_rechange_reward() + "币"); + dataHolder.mGift.setVisibility(View.VISIBLE); + } else { + dataHolder.firstImageView.setVisibility(View.INVISIBLE); + //快捷充值 显示更多金额 + if (isQuick && position == mRechargeList.size() - 1) { + dataHolder.mGift.setVisibility(View.VISIBLE); + dataHolder.mGift.setText("更多金额"); + } else { + if (!isWXRecharge) { + dataHolder.mGift.setVisibility(View.VISIBLE); + if (0 != bean.getReward()) { + dataHolder.mGift.setText("SVIP赠" + bean.getReward() + "币"); + } else { + if (position == 0) { + dataHolder.mGift.setText("无赠送"); + } else { + dataHolder.mGift.setText("SVIP赠送金币"); + } + } + } + } + } + if (!StrU.isEmpty(bean.getDiscount_desc())) { + dataHolder.tv_discount.setVisibility(View.VISIBLE); + dataHolder.tv_discount.setText(bean.getDiscount_desc()); + } else { + dataHolder.tv_discount.setVisibility(View.GONE); + } + + dataHolder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onItemClicked(dataHolder.mThisView, finalPos); + } + } + }); + } else if (mType == 2) { + dataHolder.mGift.setVisibility(View.VISIBLE); + //提现 + dataHolder.firstImageView.setVisibility(View.INVISIBLE); + dataHolder.mPrice.setText(bean.getAmount() + "元"); + dataHolder.mGift.setText(bean.getAmount() * 100 + "金币"); + dataHolder.mThisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onItemClicked(dataHolder.mThisView, finalPos); + } + } + }); + } + + if (mSelectedPosition == position) { + dataHolder.mGoodLayout.setBackgroundResource(R.drawable.shape_rechargeitem_selected_background); + dataHolder.selectedImageView.setVisibility(View.VISIBLE); + } else { + dataHolder.mGoodLayout.setBackgroundResource(R.drawable.shape_rechargeitem_normal_background); + dataHolder.selectedImageView.setVisibility(View.INVISIBLE); + + } + } + + @Override + public int getItemCount() { + return mRechargeList.size(); + } + + public class Holder extends ViewHolder { + TextView mPrice; + TextView mGift; + View mGoodLayout; + View mThisView; + ImageView firstImageView; + ImageView selectedImageView; + TextView tv_discount; + + public Holder(Context context, View itemView) { + super(context, itemView); + mPrice = itemView.findViewById(R.id.recharge_price); + firstImageView = itemView.findViewById(R.id.firstImageView); + selectedImageView = itemView.findViewById(R.id.selectedImageView); + mGift = itemView.findViewById(R.id.recharge_gift); + mGoodLayout = itemView.findViewById(R.id.recharge_layout); + tv_discount = itemView.findViewById(R.id.tv_discount); + mThisView = itemView; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SettingBrandAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SettingBrandAdapter.java new file mode 100644 index 0000000..8a90105 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SettingBrandAdapter.java @@ -0,0 +1,94 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ViewHolder; +import com.fengliyan.tianlesue.model.settings.SettingBrandBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.settings.LongImageActivity; + +import java.util.List; + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class SettingBrandAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mBrandBeans; + + public SettingBrandAdapter(Context context, List brandBeans) { + this.mContext = context; + this.mBrandBeans = brandBeans; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_setting_brand, null); + return new Holder(mContext, view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + final SettingBrandBean bean = mBrandBeans.get(position); + Holder dataHolder = (Holder) holder; + dataHolder.mPhoto.setImageURI(StrU.getResourcePath(bean.getIcon_url(), mContext)); + dataHolder.tvPhoneName.setText(bean.getName()); + +// Log.d("nail","mPhoto===" + ConstUrl.IMAGE_URL + bean.getIcon_url()); +// +// DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); +// int v1 = (int) ((dm.widthPixels / 2) * 0.75); +// +// ViewGroup.LayoutParams lp; +// lp= dataHolder.mLinearLayout.getLayoutParams(); +// lp.width=dm.widthPixels / 2; +// lp.height= v1; +// dataHolder.mLinearLayout.setLayoutParams(lp); + + if (position % 2 != 0) { + dataHolder.mViewLine.setVisibility(View.GONE); + } else { + dataHolder.mViewLine.setVisibility(View.VISIBLE); + } + + dataHolder.mPhoto.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, LongImageActivity.class); + intent.putExtra("url", StrU.getResourcePath(bean.getImage_url(), mContext)); + mContext.startActivity(intent); + } + }); + } + + @Override + public int getItemCount() { + return mBrandBeans.size(); + } + + public class Holder extends ViewHolder { + SimpleDraweeView mPhoto; + TextView tvPhoneName; + View mViewLine; + View mThisView; + + public Holder(Context context, View itemView) { + super(context, itemView); + mPhoto = itemView.findViewById(R.id.sv_phone_image); + tvPhoneName = itemView.findViewById(R.id.tv_phone_name); + mViewLine = itemView.findViewById(R.id.view_line); + mThisView = itemView; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SignInListAdapter.kt b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SignInListAdapter.kt new file mode 100644 index 0000000..7d5ed99 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SignInListAdapter.kt @@ -0,0 +1,79 @@ +package com.fengliyan.tianlesue.controller.settings.adapter + +import android.content.Context +import android.graphics.Color +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import com.chad.library.adapter.base.BaseDelegateMultiAdapter +import com.chad.library.adapter.base.delegate.BaseMultiTypeDelegate +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.model.settings.SignDataListBean +import com.fengliyan.tianlesue.utils.GlideUtils + +class SignInListAdapter(private val mContext: Context) : + BaseDelegateMultiAdapter() { + init { + setMultiTypeDelegate(object : BaseMultiTypeDelegate() { + override fun getItemType( + data: List, + position: Int + ): Int { + return 0 +// return if (position == 6) { +// 1 +// } else { +// 0 +// } + } + }) + getMultiTypeDelegate()?.addItemType(0, R.layout.item_sign_in) + getMultiTypeDelegate()?.addItemType(1, R.layout.item_sign_in1) + } + + override fun convert(holder: BaseViewHolder, item: SignDataListBean.SignListBean) { + val text1 = holder.getView(R.id.text1) + text1.text = item.title + val image = holder.getView(R.id.image) + GlideUtils.showImage(mContext, image, item.gold_coin_pic) + val ivSignIn = holder.getView(R.id.ivSignIn) + val tvContent = holder.getView(R.id.tvContent) + val clSignItem = holder.getView(R.id.cl_sign_item) + tvContent.text = item.reward + + if (item.is_selected == 1) { + clSignItem.setBackgroundResource(R.drawable.shape_sign_in_today_r5) + text1.setTextColor(Color.parseColor("#FFFFFF")) + tvContent.setTextColor(Color.parseColor("#FFFFFF")) + } else { + clSignItem.setBackgroundResource(R.drawable.shape_sign_in_r5) + text1.setTextColor(Color.parseColor("#FFB433")) + tvContent.setTextColor(Color.parseColor("#5D5C57")) + } + + if (item.is_check == 0) { + image.alpha = 1f + text1.alpha = 1f + tvContent.alpha = 1f + ivSignIn.visibility = View.GONE + } else { + if (item.is_selected == 1) { + image.alpha = 1f + text1.alpha = 1f + tvContent.alpha = 1f + } else { + image.alpha = 0.4f + text1.alpha = 0.4f + tvContent.alpha = 0.4f + } + if (item.is_check == 1) { + ivSignIn.setImageResource(R.drawable.icon_sign_in_true) + } else { + ivSignIn.setImageResource(R.drawable.icon_sign_in_false) + } + ivSignIn.visibility = View.VISIBLE + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SocialAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SocialAdapter.java new file mode 100644 index 0000000..d4351de --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/SocialAdapter.java @@ -0,0 +1,228 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.settings.SocialBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +import java.util.ArrayList; +import java.util.List; + +public class SocialAdapter extends BaseAdapter { + private List mSocialBeans = new ArrayList<>(); + private Context mContext; + private int mType; + private OnButtonClickedListener mListener; + private OnItemClickedListener mItemListener; + + + public SocialAdapter(Context context) { + mContext = context; + } + + public void setOnButtonClickedListener(OnButtonClickedListener listener) { + mListener = listener; + } + + public void setOnItemClickedListener(OnItemClickedListener listener) { + mItemListener = listener; + } + + public void setSocialBeans(List beans) { + mSocialBeans = beans; + } + + public void setSocialType(int type) { + mType = type; + } + + public interface OnButtonClickedListener { + void onCliked(int position); + } + + public interface OnItemClickedListener { + void onClicked(int position); + } + + @Override + public int getCount() { + return mSocialBeans.size(); + } + + @Override + public Object getItem(int i) { + return mSocialBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(final int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final SocialBean bean = mSocialBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_social_list, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + + if (0 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_pvip); + } else if (1 == bean.getVip()) { + holder.ivMemberSign.setVisibility(View.VISIBLE); + holder.ivMemberSign.setImageResource(R.drawable.ic_gvip); + } else { + holder.ivMemberSign.setVisibility(View.GONE); + } + + holder.photo.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.name.setText(bean.getNickname()); + if (bean.getGender() == 2) { + holder.age.setTextColor(mContext.getResources().getColor(R.color.mainColor)); + } else { + holder.age.setTextColor(Color.RED); + } + + holder.sub.setText(bean.getCity() + " | "); + holder.age.setText(bean.getAge() + "岁"); + + if (0 == mType || 1 == mType) { + holder.time.setVisibility(View.VISIBLE); + holder.focus.setVisibility(View.VISIBLE); + holder.socialTime.setVisibility(View.GONE); + holder.time.setText(bean.getAdd_time()); + } else if (2 == mType || 3 == mType) { + holder.time.setVisibility(View.GONE); + holder.focus.setVisibility(View.GONE); + holder.socialTime.setVisibility(View.VISIBLE); + holder.socialTime.setText(bean.getAdd_time()); + } + +// if(3 == mType) { +// holder.time.setText(bean.getCreate_time()); +// }else { +// holder.time.setText(bean.getAdd_time()); +// } + + if (1 == bean.getIs_watch()) { + holder.redPoint.setVisibility(View.GONE); + holder.background.setBackgroundColor(Color.WHITE); + } else { + holder.redPoint.setVisibility(View.VISIBLE); + holder.background.setBackgroundResource(R.color.socialNew); + } + +// holder.focus.setVisibility(View.VISIBLE); +// +// if(0 == mType){ +// holder.focus.setVisibility(View.VISIBLE); +// if(1 == bean.getIs_fans() && 1 == bean.getIs_follow()){ +// holder.focus.setBackgroundResource(R.drawable.shape_button_disable); +// holder.focus.setText("互相关注"); +// }else{ +// if(1 == bean.getIs_follow()){ +// holder.focus.setBackgroundResource(R.drawable.shape_button_disable); +// holder.focus.setText("已关注"); +// }else{ +// holder.focus.setBackgroundResource(R.drawable.shape_button_enable); +// holder.focus.setText("关注"); +// } +// } +// }else if(1 == mType){ +// holder.focus.setVisibility(View.VISIBLE); +// if(1 == bean.getIs_follow()){ +// holder.focus.setEnabled(false); +// holder.focus.setText("互相关注"); +// }else{ +// holder.focus.setEnabled(true); +// holder.focus.setText("关注"); +// } +// }else{ +// holder.focus.setVisibility(View.GONE); +// } + + if (1 == bean.getIs_fans() && 1 == bean.getIs_follow()) { + holder.focus.setBackgroundResource(R.drawable.shape_button_disable); + holder.focus.setText("互相关注"); + } else { + if (1 == bean.getIs_follow()) { + holder.focus.setBackgroundResource(R.drawable.shape_button_disable); + holder.focus.setText("已关注"); + } else { + holder.focus.setBackgroundResource(R.drawable.shape_button_enable); + holder.focus.setText("关注"); + } + } + + holder.focus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mListener) { + mListener.onCliked(i); + } + } + }); + + holder.thisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUserid()); + mContext.startActivity(intent); + if (null != mItemListener) { + mItemListener.onClicked(i); + } + } + }); + + view.setTag(holder); + return view; + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.photo = v.findViewById(R.id.social_list_photo); + holder.name = v.findViewById(R.id.social_list_name); + holder.sub = v.findViewById(R.id.socical_list_location); + holder.age = v.findViewById(R.id.socical_list_age); + holder.time = v.findViewById(R.id.social_list_time); + holder.focus = v.findViewById(R.id.social_list_button); + holder.redPoint = v.findViewById(R.id.social_red_point); + holder.background = v.findViewById(R.id.socail_background); + holder.socialTime = v.findViewById(R.id.social_time); + holder.ivMemberSign = v.findViewById(R.id.iv_member_sign); + holder.thisView = v; + + return holder; + } + + class Holder { + SimpleDraweeView photo; + TextView name; + TextView sub; + TextView age; + TextView time; + Button focus; + View background; + View redPoint; + View thisView; + TextView socialTime; + ImageView ivMemberSign; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/VideoRecordAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/VideoRecordAdapter.java new file mode 100644 index 0000000..bd8b845 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/VideoRecordAdapter.java @@ -0,0 +1,285 @@ +package com.fengliyan.tianlesue.controller.settings.adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.flyco.roundview.RoundTextView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.news.manager.NewsManager; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.settings.VideoRecordListBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.AgoraWithFUVideoActivity; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/22. + */ + +public class VideoRecordAdapter extends BaseAdapter { + + private Context mContext; + private List mBeans = new ArrayList<>(); + + public VideoRecordAdapter(Context context) { + mContext = context; + } + + public void setData(List mBeans) { + this.mBeans = mBeans; + } + + @Override + public int getCount() { + return mBeans == null ? 0 : mBeans.size(); + } + + @Override + public Object getItem(int i) { + return mBeans.get(i); + } + + @Override + public long getItemId(int i) { + return 0; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final VideoRecordListBean bean = mBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_video_record, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + +// if (bean.getCalltype() == 1) { //视频通话 + if (bean.getStatus() == 1) { //取消 + if (bean.getType() == 1) { //主叫者 + holder.tv_fail.setText("自己取消了呼叫"); + } else if (bean.getType() == 2) { //被叫者 + holder.tv_fail.setText("对方取消了呼叫"); + } + + holder.ll_video_time.setVisibility(View.GONE); + holder.tv_fail.setVisibility(View.VISIBLE); + } else if (bean.getStatus() == 2) { //拒绝 + if (bean.getType() == 1) { + holder.tv_fail.setText("对方拒绝接听"); + } else if (bean.getType() == 2) { + holder.tv_fail.setText("自己拒绝接听"); + } + holder.ll_video_time.setVisibility(View.GONE); + holder.tv_fail.setVisibility(View.VISIBLE); + } else if (bean.getStatus() == 3) { //超时 + holder.tv_fail.setText("超时未接听"); + holder.ll_video_time.setVisibility(View.GONE); + holder.tv_fail.setVisibility(View.VISIBLE); + } else if (bean.getStatus() == 4) { //已接听 + if (bean.getType() == 1) { + holder.tv_count.setText("(支出" + bean.getCall_amount() + "金币)"); + } else if (bean.getType() == 2) { + holder.tv_count.setText("(收入" + bean.getCall_income() + "金币)"); + } + holder.tv_video_time.setText("通话时长 " + secondToTime(bean.getCall_time()) + " "); + + holder.ll_video_time.setVisibility(View.VISIBLE); + holder.tv_fail.setVisibility(View.GONE); + } + + if (bean.getCalltype() == 1) { + holder.tv_call_back.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.mipmap.icon_video_white), null, null, null); + } else { + holder.tv_call_back.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.mipmap.icon_phone_white), null, null, null); + } + + holder.tv_call_back.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (bean.getCalltype() == 1) { + getCallInfo(bean.getUserid(), 1, 0); + } else { + getCallInfo(bean.getUserid(), 1, 1); + } + } + }); + + holder.tv_create_time.setText(bean.getCreate_time()); + holder.sv_avatar.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.tv_name.setText(bean.getNickname()); + + holder.rl_item.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUserid()); + mContext.startActivity(intent); + } + }); + holder.rl_item.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { +// new BaseMessageDialog.Builder(mContext).setMessage("确定要删除这条记录吗?") +// .setCancelable(true) +// .setPositiveButtonListener(new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialogInterface, int i1) { +// call_delete(position, 0); +// dialogInterface.dismiss(); +// } +// }).setNegativeButtonListener(new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialogInterface, int i) { +// dialogInterface.dismiss(); +// +// } +// }).build().show(); + + showLongClickMenu(i); + return false; + } + }); +// } + view.setTag(holder); + return view; + } + + private void showLongClickMenu(final int position) { + VideoRecordListBean bean = mBeans.get(position); + CustomAlertDialog alertDialog = new CustomAlertDialog(mContext); + alertDialog.setTitle(UserInfoHelper.getUserTitleName(bean.getNickname(), SessionTypeEnum.P2P)); + alertDialog.addItem("删除这条记录", new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + call_delete(position, 0); + } + }); + + alertDialog.addItem("删除全部记录", new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + call_delete(position, 1); + } + }); + alertDialog.show(); + } + + public void call_delete(int position, int type) { + NewsManager.call_delete((BaseActivity) mContext, mBeans.get(position).getId(), type, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + if (type == 0) mBeans.remove(position); + else mBeans.clear(); + notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "删除失败,请重试"); + } + }); + } + + private String secondToTime(long second) { + long days = second / 86400; + second = second % 86400; + long hours = second / 3600; + second = second % 3600; + long minutes = second / 60; + second = second % 60; + return String.format("%02d:%02d:%02d", hours + days * 24, minutes, second); +// if (days > 0) { +// return days + "天" + hours + "小时" + minutes + "分" + second + "秒"; +// } else { +// return hours + "小时" + minutes + "分" + second + "秒"; +// } + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.rl_item = v.findViewById(R.id.rl_item); + holder.tv_create_time = v.findViewById(R.id.tv_create_time); + holder.sv_avatar = v.findViewById(R.id.sv_avatar); + holder.tv_name = v.findViewById(R.id.tv_name); + holder.ll_video_time = v.findViewById(R.id.ll_video_time); + holder.tv_fail = v.findViewById(R.id.tv_fail); + holder.tv_video_time = v.findViewById(R.id.tv_video_time); + holder.tv_count = v.findViewById(R.id.tv_count); + holder.tv_call_back = v.findViewById(R.id.tv_call_back); + return holder; + } + + class Holder { + RelativeLayout rl_item; + TextView tv_create_time; + SimpleDraweeView sv_avatar; + TextView tv_name; + LinearLayout ll_video_time; + TextView tv_fail; + TextView tv_video_time; + TextView tv_count; + RoundTextView tv_call_back; + } + + + private void getCallInfo(int uid, int skillId, int callType) { + MainManager.getCallInfo((BaseActivity) mContext, uid, skillId, callType, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(mContext, AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", true); + intent.putExtra("callType", callType); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + mContext.startActivity(intent); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/constant/SettingOptions.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/constant/SettingOptions.java new file mode 100644 index 0000000..3d982d4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/adapter/constant/SettingOptions.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.controller.settings.adapter.constant; + +public enum SettingOptions { + WALLET, + CONTRACT,//价格设置 + INVITATION, + GUIDE,//用户指南 + RANK, + CUSTOMER,//客服 + MISSIONS, + BEAUTY,//美颜设置 + MEMBER,//会员特权 + OFFICIAL, + SETTING,//设置 + GODDESSPRIVILEGE, //女神特权 + VIOLATION,//违规公布 + ADDWECHAT,//添加微信 + HELLOW,//招呼设置 + ITEMS,//我的道具 + VIDEO, //视频聊天 + DETAIL//账单明细 +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/DataCleanManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/DataCleanManager.java new file mode 100644 index 0000000..52f8646 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/DataCleanManager.java @@ -0,0 +1,105 @@ +package com.fengliyan.tianlesue.controller.settings.manager; + +import android.content.Context; +import android.os.Environment; + +import java.io.File; +import java.math.BigDecimal; + +/** + * Created by chenqihong on 2017/3/29. + */ + +public class DataCleanManager { + public static String getTotalCacheSize(Context context) throws Exception { + long cacheSize = getFolderSize(context.getCacheDir()); + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + cacheSize += getFolderSize(context.getExternalCacheDir()); + } + return getFormatSize(cacheSize); + } + + + public static void clearAllCache(Context context) { + deleteDir(context.getCacheDir()); + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + deleteDir(context.getExternalCacheDir()); + } + } + + private static boolean deleteDir(File dir) { + if(null == dir){ + return false; + } + + if (dir.isDirectory()) { + String[] children = dir.list(); + for (int i = 0; i < children.length; i++) { + boolean success = deleteDir(new File(dir, children[i])); + if (!success) { + return false; + } + } + } + return dir.delete(); + } + + // 获取文件 + //Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据 + //Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据 + public static long getFolderSize(File file) throws Exception { + long size = 0; + try { + File[] fileList = file.listFiles(); + for (int i = 0; i < fileList.length; i++) { + // 如果下面还有文件 + if (fileList[i].isDirectory()) { + size = size + getFolderSize(fileList[i]); + } else { + size = size + fileList[i].length(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return size; + } + + /** + * 格式化单位 + * + * @param size + * @return + */ + public static String getFormatSize(double size) { + double kiloByte = size / 1024; + if (kiloByte < 1) { +// return size + "Byte"; + return "0K"; + } + + double megaByte = kiloByte / 1024; + if (megaByte < 1) { + BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); + return result1.setScale(2, BigDecimal.ROUND_HALF_UP) + .toPlainString() + "KB"; + } + + double gigaByte = megaByte / 1024; + if (gigaByte < 1) { + BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); + return result2.setScale(2, BigDecimal.ROUND_HALF_UP) + .toPlainString() + "MB"; + } + + double teraBytes = gigaByte / 1024; + if (teraBytes < 1) { + BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); + return result3.setScale(2, BigDecimal.ROUND_HALF_UP) + .toPlainString() + "GB"; + } + BigDecimal result4 = new BigDecimal(teraBytes); + return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + + "TB"; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/SettingManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/SettingManager.java new file mode 100644 index 0000000..5a96c1f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/SettingManager.java @@ -0,0 +1,1567 @@ +package com.fengliyan.tianlesue.controller.settings.manager; + +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.chat.ImageCheckBean; +import com.fengliyan.tianlesue.model.main.ContactBean; +import com.fengliyan.tianlesue.model.main.SkillAnchorBean; +import com.fengliyan.tianlesue.model.main.SpeedInfoBean; +import com.fengliyan.tianlesue.model.main.SystemVersionBean; +import com.fengliyan.tianlesue.model.settings.AccountBean; +import com.fengliyan.tianlesue.model.settings.BackPackListBean; +import com.fengliyan.tianlesue.model.settings.BankInfoBean; +import com.fengliyan.tianlesue.model.settings.BeAnchorStatusBean; +import com.fengliyan.tianlesue.model.settings.BillListBean; +import com.fengliyan.tianlesue.model.settings.BindInfoBean; +import com.fengliyan.tianlesue.model.settings.CancellationBean; +import com.fengliyan.tianlesue.model.settings.ChatPriceBean; +import com.fengliyan.tianlesue.model.settings.GoddessPrivilegeBean; +import com.fengliyan.tianlesue.model.settings.GreetingBean; +import com.fengliyan.tianlesue.model.settings.InvitationBean; +import com.fengliyan.tianlesue.model.settings.InviteDataListBean; +import com.fengliyan.tianlesue.model.settings.MemberBean; +import com.fengliyan.tianlesue.model.settings.MissionListBean; +import com.fengliyan.tianlesue.model.settings.PayBean; +import com.fengliyan.tianlesue.model.settings.PayConfigBean; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.model.settings.SDPayBean; +import com.fengliyan.tianlesue.model.settings.SelfieExampleBean; +import com.fengliyan.tianlesue.model.settings.SettingBrandBean; +import com.fengliyan.tianlesue.model.settings.SignDataListBean; +import com.fengliyan.tianlesue.model.settings.SkillSettingBean; +import com.fengliyan.tianlesue.model.settings.SocialListBean; +import com.fengliyan.tianlesue.model.settings.UserHomeBean; +import com.fengliyan.tianlesue.model.settings.VideoRecordBean; +import com.fengliyan.tianlesue.model.settings.WXAccountStatusBean; +import com.fengliyan.tianlesue.model.settings.WXPayTypeBean; +import com.fengliyan.tianlesue.model.settings.WalletIndexBean; +import com.fengliyan.tianlesue.model.settings.WithdrawInfoBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; + +import java.util.List; + +public class SettingManager { + public static void getAnchorStatus(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.BE_ANCHOR_STATUS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getSelfieExample(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_SELFIE_EXAMPLE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void getFaceCertifyId(BaseActivity activity, String meta_info, String cert_name, String cert_no, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_FACE_CERTIFY_ID; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("meta_info", meta_info) + .addParam("cert_name", cert_name) + .addParam("cert_no", cert_no) + .setUrl(url); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void faceStatusError(BaseActivity activity, String note, String certify_id, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.FACE_CERTIFY_STATUS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("note", note) + .addParam("certify_id", certify_id) + .setUrl(url); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void apply(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.ANCHOR_APPLY; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void agreeContract(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.AGREE_ANCHOR_CONTRACT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("agreement", "1").setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void missions(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.MISSION_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void sign(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.MISSION_SIGN; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void signData(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SIGN_DATA; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType(new TType>() { + }) + .setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void signIn(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SIGN_IN; + HttpRequest.Builder builder = new HttpRequest.Builder().setResultType(new TType>() { + }) + .setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void share(BaseActivity activity, + final int type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.MISSION_SHARE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "").setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void rankLove(BaseActivity activity, + final int type, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.RANK_LOVE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); +// String code = request.request().getCode(); + return request.request(); + } + }; + + task.start(false); + } + + public static void rankGift(BaseActivity activity, + final int type, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.RANK_GIFT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void rankWealth(BaseActivity activity, + final int type, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.RANK_WEALTH; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(false); + } + + public static void rankInvite(BaseActivity activity, + final int type, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.RANK_INVITE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void rankRich(BaseActivity activity, + final int type, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.RANK_RICH; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void rankGuard(BaseActivity activity, + final int type, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_GUARD_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getInvitationData(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_INVITATION_DATA; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * 获取邀请充值列表 + * + * @param list_type tab类型 1=今日2=昨日3=本周4=上周5=本月6=上月 + * @param invite_type 邀请类型 1=直接2=间接 + * @param page 当前页 + * @param user_code 用户号 + */ + + public static void getInvitationRechargeList(BaseActivity activity, String list_type, String invite_type, String page, String user_code, String type, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_INVITATION_RECHARGE_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("list_type", list_type) + .addParam("invite_type", invite_type) + .addParam("page", page) + .addParam("user_code", user_code) + .addParam("type", type) + .setUrl(url); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void getHomeUser(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_USER_INFO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getSocialData(BaseActivity activity, + final int type, + final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = null; + if (type == 0) { + url = ConstUrl.FOCUS_LIST; + } else if (1 == type) { + url = ConstUrl.FANS_LIST; + } else if (2 == type) { + url = ConstUrl.VISITOR_LIST; + } else if (3 == type) { + url = ConstUrl.TRACER_LIST; + } + + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getInviteList(BaseActivity activity, final int page, String user, HttpUiCallBack< + SocialListBean> httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "") + .addParam("user", user) + .setUrl(ConstUrl.INVITE_LIST); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void checkSelfie(BaseActivity activity, + final int actionType, + final String photo, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CHECK_SELFIE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("action_type", actionType + "") + .addParam("photo", photo) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(false); + } + + public static void getSkillInfo(BaseActivity activity, + HttpUiCallBack> httpUiCallBack) { + HttpWithUiTask> task = new HttpWithUiTask>(activity, httpUiCallBack) { + @Override + protected HttpResult> run() throws Exception { + final String url = ConstUrl.GET_SKILL_INFO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void setSkillPrice(BaseActivity activity, + final int skillId, + final String price, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SET_SKILL_PRICE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("skill_id", skillId + "") + .addParam("price", price) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + +// + + /** + * @param activity + * @param type 修改类型:视频价格 = 'video_price'、 语音价格 = 'voice_price'、视频接听状态 = 'open_video_status'、语音接听状态 = 'open_voice_status' + * @param value 修改值:价格:100-1000、状态:0 = 未开启、1 = 已开启 + * @param httpUiCallBack + */ + public static void setSkillPriceNew(BaseActivity activity, String type, String value, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.SET_SKILL_PRICE1; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type) + .addParam("value", value) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getMySkill(BaseActivity activity, + HttpUiCallBack> httpUiCallBack) { + HttpWithUiTask> task = new HttpWithUiTask>(activity, httpUiCallBack) { + @Override + protected HttpResult> run() throws Exception { + final String url = ConstUrl.GET_MY_SKILL; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /*public static void addSkill(BaseActivity activity, + final String skills, + HttpUiCallBack httpUiCallBack){ + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.ADD_SKILLS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("skills", skills) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + }*/ + + public static void addSkill(BaseActivity activity, + final String skills, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.ADD_SKILLS; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("skills", skills) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getBindInfo(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_BIND_INFO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void bindPhone(BaseActivity activity, + final String mobile, + final String code, + final String password, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.BIND_PHONE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("mobile", mobile) + .addParam("phone_code", code) + .addParam("password", password) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void bindPlatform(BaseActivity activity, + final String platform, + final String openid, + final String accessToken, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.BIND_PLATFORM; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("platform", platform) + .addParam("openid", openid) + .addParam("access_token", accessToken) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getBlackList(BaseActivity activity, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_BLACK_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getWalletIndex(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.WALLET_INDEX; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getRechargeInfo(BaseActivity activity, + final int type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_RECHARGE_INFO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void sdPay(BaseActivity activity, + final String channel, + final String goodId, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.PAY_TO_RECHARGE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("channel", channel) + .addParam("goods_id", goodId) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * @param activity + * @param channel + * @param goodId + * @param type 0.金币充值 1.会员充值 2.首充 + * @param httpUiCallBack + */ + public static void payToRecharge(BaseActivity activity, + final String channel, + final String goodId, + final int type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.PAY_TO_RECHARGEV2; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("channel", channel) + .addParam("goods_id", goodId) + .addParam("type", type + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getWechatPaySite(BaseActivity activity, + + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GETWECHATPAYSITE; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getBillList(BaseActivity activity, + final int type, + final int cateId, + final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_BILL_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .addParam("cate_id", cateId + "") + .addParam("page", page + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void withdraw(BaseActivity activity, + final String money, + boolean isBank, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + String url = ConstUrl.DO_WITHDRAW; + if (isBank) { + url = ConstUrl.USER_WITHDRAW_BANK; + } + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("money", money) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getWithdrawInfo(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_WITHDRAW_INFO; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void bindAccount(BaseActivity activity, + final String cardName, + final String cardAccount, + final String card, + final String mobile, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.BIND_ACCOUNT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("card_name", cardName) + .addParam("card", card) + .addParam("mobile", mobile) + .addParam("card_account", cardAccount) + + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getAccountInfo(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.GET_BIND_ACCOUNT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getSettingBrand(BaseActivity + activity, HttpUiCallBack> httpUiCallBack) { + HttpWithUiTask> task = new HttpWithUiTask>(activity, httpUiCallBack) { + @Override + protected HttpResult> run() throws Exception { + String url = ConstUrl.SETTING_BRAND_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>>() { + }).setHttpMethod(HttpMethod.POST) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void getVideoRecordList(BaseActivity activity, final int page, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.CALL_LIST; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("page", page + "") + .addParam("type", "0") + .addParam("calltype", "0") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(false); + } + + public static void getMemberInfo(BaseActivity activity, final int type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.USER_MEMBER; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + /** + * @param activity + * @param type 权限类型 rank 隐藏排行榜 greet 消息免打扰,(新版会员增加:login_notice_hide:上线通知隐藏、login_time_hide:登录时间隐藏、greet_hide:群招呼信息免打扰、visitor_hide:访问足迹隐藏、speed_hide:速配弹窗免打扰、avatar_hide:动画效果框) + * @param value + * @param httpUiCallBack + */ + public static void memberAuthority(BaseActivity activity, final String type, + final int value, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.USER_MEMBER_PRIVILEGES; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type) + .addParam("value", value + "") + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void privilege_info(BaseActivity + activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.PRIVILEGE_INFO); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void privilege_setting(BaseActivity activity, final String type, + final String value, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type) + .addParam("value", value) + .setUrl(ConstUrl.PRIVILEGE_SETTING); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + } + + public static void wechat_qq_verify(BaseActivity activity, final String content, + final String image, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("content", content) + .addParam("image", image) + .addParam("type", "1")//类型:1=微信 2=QQ + .setUrl(ConstUrl.WECHAT_QQ_VERIFY); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void deleteAccount(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.DELETE_ACCOUNT); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + + task.start(); + + } + + public static void wechatAndQQCheck(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).addParam("type", "1") + + .setUrl(ConstUrl.WECHATANDQQCHECK); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void priceSetting(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + + .setUrl(ConstUrl.PRICE_SETTING); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void setWechatPrice(BaseActivity activity, String price, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST).addParam("price", price) + .setUrl(ConstUrl.SETWECHATPRICE); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void greetingList(BaseActivity activity, int type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST).addParam("type", String.valueOf(type)) + + .setUrl(ConstUrl.LISTS); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void addGreet(BaseActivity activity, String title, int type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", String.valueOf(type)) + .addParam("title", title) + .setUrl(ConstUrl.ADD); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void delGreet(BaseActivity activity, int id, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("id", String.valueOf(id)) + .setUrl(ConstUrl.DELETE); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void downloadVoice(String url, String path, HttpCallback callback) { + HttpRequest request = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(url).build(); + + request.download(path, true, callback); + } + + public static void getWeChat(BaseActivity activity, String to_uid, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("to_uid", to_uid) + .setUrl(ConstUrl.GETWECHAT); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void getlogout(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.GETLOGOUT); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void uptlogout(BaseActivity activity, String type, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type) + .setUrl(ConstUrl.UPTLOGOUT); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void bank(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.BANK); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void bind_bank(BaseActivity activity, String card_name, + String mobile, + String bank, + String card_account, + String card, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("card_name", card_name) + .addParam("mobile", mobile) + .addParam("bank", bank) + .addParam("card", card) + .addParam("card_account", card_account) + .setUrl(ConstUrl.BIND_BANK); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void user_withdraw_bank(BaseActivity activity, String money, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .addParam("card_name", money) + .setUrl(ConstUrl.USER_WITHDRAW_BANK); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void payConfig(BaseActivity activity, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.MEMBERSWITCH); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void imageCheck(BaseActivity activity, + String img, + String to_uid, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("img", img) + .addParam("to_uid", to_uid) + .setUrl(ConstUrl.SNAPSHOOT_IM); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + public static void videoCheck(BaseActivity activity, + String img, + HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("base64_img_list", img) + .setUrl(ConstUrl.VIDEO_CHECK); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 我的背包 + * + * @param activity + * @param httpUiCallBack + */ + public static void getItemList(BaseActivity + activity, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .setUrl(ConstUrl.MINE_BACKPACK); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 获取速配界面信息 + * + * @param activity + * @param type 速配类型:2 = 视频速配、3 = 语音速配 + * @param httpUiCallBack + */ + public static void getCallSpeedInfo(BaseActivity activity, String + type, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("type", type) + .setUrl(ConstUrl.GET_CALL_SPEED_INFO); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + + /** + * 实名认证提交信息 + * + * @param activity + * @param user_name 姓名 + * @param cert_no 身份证号 + * @param httpUiCallBack + */ + public static void CheckRealName(BaseActivity activity, String user_name, String + cert_no, HttpUiCallBack httpUiCallBack) { + HttpWithUiTask task = new HttpWithUiTask(activity, httpUiCallBack) { + @Override + protected HttpResult run() throws Exception { + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("user_name", user_name) + .addParam("cert_no", cert_no) + .setUrl(ConstUrl.REAL_NAME_ATTEST); + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } + +} + + + diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/UserAvatarManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/UserAvatarManager.java new file mode 100644 index 0000000..4f2e069 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/settings/manager/UserAvatarManager.java @@ -0,0 +1,318 @@ +package com.fengliyan.tianlesue.controller.settings.manager; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.MediaStore; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.fengliyan.base.base.ContextHolder; +import com.fengliyan.base.base.permission.AbsPermissionResultCallBack; +import com.fengliyan.base.base.permission.PermissionHelper; +import com.fengliyan.tianlesue.view.base.utils.ActionSheetDialog; +import com.fengliyan.uikit.crop.Crop; +import com.fengliyan.uikit.crop.CropCallback; +import com.fengliyan.uikit.crop.CropFactory; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * 用户头像处理类 + * Created by neuyuandaima on 2016/1/22. + */ +public class UserAvatarManager { + + private static final String ACTION_SHEET_GALLERY = "相册"; + + private static final String ACTION_SHEET_CAMERA = "拍照"; + + private static final int REQUEST_IMAGE_CAPTURE = 101; + + private static final int ACTIVITY_NOT_NULL = 1; + + private static final int SUPPORTFRAGMENT_NOT_NULL = 2; + + private static final int FRAGMENT_NOT_NULL = 3; + private static Uri sUri; + /** + * 调用方传入的接口实现 + */ + private UserImgListener mUserImgListener; + /** + * 标志位,判断activity还是fragment传入 + */ + private int flag = 0; + /** + * 缓存activtiy + */ + private Activity mActivity; + /** + * 缓存support.Fragment + */ + private Fragment mSupportFragment; + /** + * 缓存app.Fragment + */ + private Fragment mFragment; + /** + * 缓存app.Fragment + */ + private Context mContext; + private Crop mCrop; + + /** + * 用户头像处理类的构造器 + * + * @param userImgListener 传入方 + */ + public UserAvatarManager(UserImgListener userImgListener) { + mUserImgListener = userImgListener; + if (userImgListener instanceof Activity) { + mActivity = (Activity) mUserImgListener; + flag = ACTIVITY_NOT_NULL; + mCrop = CropFactory.newCrop(mActivity); + } else if (userImgListener instanceof Fragment) { + mSupportFragment = (Fragment) mUserImgListener; + mActivity = mSupportFragment.getActivity(); + flag = SUPPORTFRAGMENT_NOT_NULL; + mCrop = CropFactory.newCrop(mSupportFragment); + } else if (userImgListener instanceof Fragment) { + mFragment = (Fragment) mUserImgListener; + mActivity = mFragment.getActivity(); + flag = FRAGMENT_NOT_NULL; + mCrop = CropFactory.newCrop(mFragment); + } + mContext = mActivity; + } + + /** + * 展现可选视图 + */ + public void showSelectDialog() { + Dialog dialog = new AlertDialog.Builder(mActivity).setItems(new String[]{"相机", "相册"}, + new MyClick()).create(); + if (!dialog.isShowing()) { + dialog.show(); + } + } + + /** + * 展现actionsheet + */ + public void showActionSheetDialog() { + new ActionSheetDialog(mContext).builder() + .addSheetItem(ACTION_SHEET_GALLERY, ActionSheetDialog.SheetItemColor.Red, + new ActionSheetDialog.OnSheetItemClickListener() { + @Override + public void onClick(int which) { + whoStartCrop(); + } + + }) + .addSheetItem(ACTION_SHEET_CAMERA, ActionSheetDialog.SheetItemColor.Red, + new ActionSheetDialog.OnSheetItemClickListener() { + @Override + public void onClick(int which) { + whoStartActivityForResult(); + } + }) + .show(); + } + + public void startCamera(){ + whoStartActivityForResult(); + } + + /** + * 哪一个开启剪切 + */ + private void whoStartCrop() { + PermissionHelper.request(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + new AbsPermissionResultCallBack() { + @Override + public void onPermissionGranted() { + switch (flag) { + case ACTIVITY_NOT_NULL: + mCrop.start(); + break; + case SUPPORTFRAGMENT_NOT_NULL: + mCrop.start(); + break; + case FRAGMENT_NOT_NULL: + mCrop.start(); + break; + } + } + }); + } + + /** + * 哪一个启动相机 + */ + private void whoStartActivityForResult() { + PermissionHelper.request(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, new AbsPermissionResultCallBack() { + @Override + public void onPermissionGranted() { + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //照相 + intent.putExtra("android.intent.extras.CAMERA_FACING", 1); +// Camera.open(1); +// int cameraCount = 0; +// Camera cam = null; +// +// Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); +// cameraCount = Camera.getNumberOfCameras(); // get cameras number +// +// for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) { +// Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo +// if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { // 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置 +// try { +// cam = Camera.open(camIdx); +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// } +// } + + int currentVersion = Build.VERSION.SDK_INT; + try { + if(currentVersion < 24) { + sUri = Uri.fromFile(createImageFile()); + intent.putExtra(MediaStore.EXTRA_OUTPUT, sUri); + }else{ + ContentValues contentValues = new ContentValues(1); + contentValues.put(MediaStore.Images.Media.DATA, createImageFile().getAbsolutePath()); + sUri = ContextHolder.getApplicationContext().getContentResolver() + .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues); + intent.putExtra(MediaStore.EXTRA_OUTPUT, sUri); + } + } catch (IOException e) { + //error create file + } + switch (flag) { + case ACTIVITY_NOT_NULL: + mActivity.startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); //启动照相 + break; + case SUPPORTFRAGMENT_NOT_NULL: + mSupportFragment.startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); //启动照相 + break; + case FRAGMENT_NOT_NULL: + mFragment.startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); //启动照相 + break; + } + } + }); + } + + private File createImageFile() throws IOException { + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINESE).format(new Date()); + String imageFileName = "JPEG_" + timeStamp + "_"; + File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); + if (!storageDir.exists() && !storageDir.mkdir()) { + storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); + if (!storageDir.exists()) storageDir.mkdir(); + } + return new File(storageDir.getAbsolutePath(), imageFileName + ".jpg"); + } + + /** + * 剪切完成回调 + * + * @param requestCode + * @param resultCode + * @param data + */ + public void onActivityResult(int requestCode, int resultCode, Intent data) { + mCrop.onActivityResult(requestCode, resultCode, data, new CropCallback() { + @Override + public void OnReceiveBitmap(@Nullable String path) { + if (mUserImgListener != null) { + mUserImgListener.getUserImg(path); + } + } + + }); + /**照相后的数据*/ + if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) { + if (sUri != null) { + whoStartCropWithUi(sUri); + } else { + if(null == data){ + return; + } + + Bitmap imageBitmap = (Bitmap) data.getExtras().get("data");//部分机型可能为空 + String uriString = MediaStore.Images.Media.insertImage(mActivity.getContentResolver(), imageBitmap, null, null); + if (uriString != null) { + Uri uri = Uri.parse(uriString); + whoStartCropWithUi(uri); + } else {//照相后获取不到图片,打开图库,由用户选择照片后裁剪 + whoStartCrop(); + } + } + } + } + + /** + * 照相完成,将其发送给剪切方 + * + * @param uri 照片uri + */ + public void whoStartCropWithUi(Uri uri) { + switch (flag) { + case ACTIVITY_NOT_NULL: + mCrop.start(uri); + break; + case SUPPORTFRAGMENT_NOT_NULL: + mCrop.start(uri); + break; + case FRAGMENT_NOT_NULL: + mCrop.start(uri); + break; + } + } + + + + /** + * 用户图片监听类 + */ + public interface UserImgListener { + /** + * 传输uri给调用方 + * + * @param path 照片本地地址 + */ + void getUserImg(@Nullable String path); + } + + /** + * onclick的实现类 + */ + private class MyClick implements DialogInterface.OnClickListener { + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == 0) { + //选择了相机 + whoStartActivityForResult(); + } else { + //选择了照片 + whoStartCrop(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/user/manager/UserManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/user/manager/UserManager.java new file mode 100644 index 0000000..430cbea --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/user/manager/UserManager.java @@ -0,0 +1,105 @@ +package com.fengliyan.tianlesue.controller.user.manager; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.fengliyan.tianlesue.model.main.GlobalConfigBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseApplication; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.Observer; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by abby on 2018/4/7. + */ + +public class UserManager { + private static UserManager mInstance; + private static BaseUserInfo userInfo = new BaseUserInfo(); + private static GlobalConfigBean globalConfigInfo; + private static String inviteCode; + private static boolean inviteResult; + private List> mEmitterList = new ArrayList<>(); + private Observable mObservable; + public static UserManager getInstance(){ + if(null == mInstance) { + mInstance = new UserManager(); + } + + return mInstance; + } + + private UserManager(){ + mObservable = Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter emitter) throws Exception { + mEmitterList.add(emitter); + } + }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) ; + } + + public void notifyUserInfoChanged(BaseUserInfo userInfo){ + Iterator> i = mEmitterList.iterator(); + while(i.hasNext()){ + ObservableEmitter emitter = i.next(); + emitter.onNext(userInfo); + } + } + + public static GlobalConfigBean getGlobalConfigInfo() { + if (globalConfigInfo==null){ + String str = SPUtils.getString(BaseApplication.getInstance(),"globalConfigInfo"); + if (TextUtils.isEmpty(str)){ + return null; + } + Gson gson = new Gson(); + globalConfigInfo = gson.fromJson(str,GlobalConfigBean.class); + } + return globalConfigInfo; + } + + public static void setGlobalConfigInfo(GlobalConfigBean globalConfigInfo) { + Gson gson = new Gson(); + String str = gson.toJson(globalConfigInfo); + SPUtils.saveString(BaseApplication.getInstance(),"globalConfigInfo",str); + UserManager.globalConfigInfo = globalConfigInfo; + } + + public void registerUserInfoObserver(Observer observer){ + mObservable.subscribe(observer); + } + + public static BaseUserInfo getUserInfo() { + return userInfo; + } + + public static void setUserInfo(BaseUserInfo userInfo) { + UserManager.userInfo = userInfo; + } + + public static String getInviteCode() { + return inviteCode; + } + + public static void setInviteCode(String inviteCode) { + UserManager.inviteCode = inviteCode; + } + + public static boolean isInviteResult() { + return inviteResult; + } + + public static void setInviteResult(boolean inviteResult) { + UserManager.inviteResult = inviteResult; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/controller/video/manager/VideoManager.java b/app/src/main/java/com/fengliyan/tianlesue/controller/video/manager/VideoManager.java new file mode 100644 index 0000000..962d335 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/controller/video/manager/VideoManager.java @@ -0,0 +1,130 @@ +package com.fengliyan.tianlesue.controller.video.manager; + +import android.content.Context; +import android.util.Log; +import android.view.SurfaceView; + +import com.fengliyan.tianlesue.R; + +import io.agora.rtc.IRtcEngineEventHandler; +import io.agora.rtc.RtcEngine; +import io.agora.rtc.video.VideoCanvas; +import io.agora.rtc.video.VideoEncoderConfiguration; + +public class VideoManager { + private static VideoManager mInstance; + private RtcEngine mRtcEngine; + private Context mContext; + private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() { + @Override + public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) { + + } + + @Override + public void onUserOffline(int uid, int reason) { + } + + @Override + public void onUserMuteVideo(final int uid, final boolean muted) { + + } + }; + + public static VideoManager getInstance() { + if(null == mInstance){ + mInstance = new VideoManager(); + } + return mInstance; + } + + public VideoManager(){ + + } + + public void init(Context context, IRtcEngineEventHandler rtcEventHandler){ + mContext = context; + initializeAgoraEngine(mContext, rtcEventHandler); + setupVideoProfile(); + } + + public void setupVideoProfile() { + mRtcEngine.enableVideo(); + +// mRtcEngine.setVideoProfile(Constants.VIDEO_PROFILE_720P, false); + VideoEncoderConfiguration videoEncoderConfiguration = new VideoEncoderConfiguration(VideoEncoderConfiguration.VD_840x480, VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15, 610, VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT); + mRtcEngine.setVideoEncoderConfiguration(videoEncoderConfiguration); + } + + public SurfaceView setupLocalVideo(){ + SurfaceView surfaceView = RtcEngine.CreateRendererView(mContext); + surfaceView.setZOrderMediaOverlay(true); + mRtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, 0)); + return surfaceView; + } + + public void joinChannel(String roomId, int fromUid) { + if (null != mRtcEngine) { + mRtcEngine.joinChannel(null, roomId, "", fromUid); // if you do not specify the uid, we will generate the uid for you + } + } + + public SurfaceView setupRemoteVideo(int uid){ + SurfaceView surfaceView = RtcEngine.CreateRendererView(mContext); + mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, + VideoCanvas.RENDER_MODE_HIDDEN, uid)); + + surfaceView.setTag(uid); + return surfaceView; + } + + public void leaveChannel() { + if (null != mRtcEngine) { + mRtcEngine.leaveChannel(); + RtcEngine.destroy(); + mRtcEngine = null; + } + } + + public void initializeAgoraEngine(Context context, IRtcEngineEventHandler rtcEventHandler) { + try { + mRtcEngine = RtcEngine.create(context, context.getString(R.string.agora_app_id), rtcEventHandler); + mRtcEngine.muteLocalAudioStream(false); + } catch (Exception e) { + + throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e)); + } + } + +// public void mute(boolean isMute){ +// mRtcEngine.muteLocalAudioStream(isMute); +// } + + public void switchCamera(){ + mRtcEngine.switchCamera(); + } + + public void enableVideo(boolean isEnable){ + mRtcEngine.muteLocalVideoStream(isEnable); + } + + public void enableAudio() { + mRtcEngine.enableAudio(); + } + + public void disableAudio() { + mRtcEngine.disableAudio(); + } + + public void speak() { + mRtcEngine.setEnableSpeakerphone(true); + } + + public RtcEngine getRtvEngine() { + if (null != mRtcEngine) { + return mRtcEngine; + }else { + return null; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/NimUIKit.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/NimUIKit.java new file mode 100644 index 0000000..28e15ad --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/NimUIKit.java @@ -0,0 +1,648 @@ +package com.fengliyan.tianlesue.im.uikit.api; + +import android.app.Activity; +import android.content.Context; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomMemberChangedObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomSessionCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactChangedObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactEventListener; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.location.LocationProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.main.CustomPushContentProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.main.OnlineStateChangeObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.main.OnlineStateContentProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.recent.RecentCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.robot.RobotInfoProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionEventListener; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamChangedObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.user.IUserInfoProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObservable; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder.ChatRoomMsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.activity.ContactSelectActivity; +import com.fengliyan.tianlesue.im.uikit.business.session.module.MsgForwardFilter; +import com.fengliyan.tianlesue.im.uikit.business.session.module.MsgRevokeFilter; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultP2PSessionCustomization; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultTeamSessionCustomization; +import com.fengliyan.tianlesue.im.uikit.impl.provider.DefaultContactProvider; +import com.fengliyan.tianlesue.im.uikit.impl.provider.DefaultUserInfoProvider; +import com.fengliyan.tianlesue.im.uikit.support.glide.ImageLoaderKit; +import com.netease.nimlib.sdk.AbortableFuture; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.auth.LoginInfo; +import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomResultData; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 云信UI组件接口/定制化入口 + * Created by huangjun on 2017/9/29. + */ + +public class NimUIKit { + + /** + * 初始化UIKit, 用户信息、联系人信息使用 {@link DefaultUserInfoProvider},{@link DefaultContactProvider} + * 若用户自行提供 userInfoProvider,contactProvider,请使用 {@link NimUIKitImpl#init(Context, IUserInfoProvider, ContactProvider)} + * + * @param context 上下文 + */ + public static void init(Context context) { + NimUIKitImpl.init(context); + } + + /** + * 初始化UIKit, 用户信息、联系人信息使用 {@link DefaultUserInfoProvider},{@link DefaultContactProvider} + * 若用户自行提供 userInfoProvider,contactProvider,请使用 {@link NimUIKitImpl#init(Context, IUserInfoProvider, ContactProvider)} + * + * @param context 上下文 + * @param option 自定义选项 + */ + public static void init(Context context, UIKitOptions option) { + NimUIKitImpl.init(context, option); + } + + /** + * 初始化UIKit,须传入context以及用户信息提供者 + * + * @param context 上下文 + * @param userInfoProvider 用户信息提供者 + * @param contactProvider 通讯录信息提供者 + */ + public static void init(Context context, IUserInfoProvider userInfoProvider, ContactProvider contactProvider) { + NimUIKitImpl.init(context, userInfoProvider, contactProvider); + } + + /** + * 初始化UIKit,须传入context以及用户信息提供者 + * + * @param context 上下文 + * @param option 自定义选项 + * @param userInfoProvider 用户信息提供者 + * @param contactProvider 通讯录信息提供者 + */ + public static void init(Context context, UIKitOptions option, IUserInfoProvider userInfoProvider, ContactProvider contactProvider) { + NimUIKitImpl.init(context, option, userInfoProvider, contactProvider); + } + + /** + * 获取配置项 + * + * @return UIKitOptions + */ + public static UIKitOptions getOptions() { + return NimUIKitImpl.getOptions(); + } + + /** + * 设置位置信息提供者 + * + * @param locationProvider 位置信息提供者 + */ + public static void setLocationProvider(LocationProvider locationProvider) { + NimUIKitImpl.setLocationProvider(locationProvider); + } + + /** + * 设置聊天界面的事件监听器 + * + * @param sessionListener 事件监听器 + */ + public static void setSessionListener(SessionEventListener sessionListener) { + NimUIKitImpl.setSessionListener(sessionListener); + } + + /** + * 设置转发消息过滤的监听器 + * + * @param msgForwardFilter 监听器 + */ + public static void setMsgForwardFilter(MsgForwardFilter msgForwardFilter) { + NimUIKitImpl.setMsgForwardFilter(msgForwardFilter); + } + + /** + * 设置消息撤回的监听器 + * + * @param msgRevokeFilter 监听器 + */ + public static void setMsgRevokeFilter(MsgRevokeFilter msgRevokeFilter) { + NimUIKitImpl.setMsgRevokeFilter(msgRevokeFilter); + } + + /** + * 注册自定义推送文案 + * + * @param mixPushCustomConfig 文案内容提供者 + */ + public static void setCustomPushContentProvider(CustomPushContentProvider mixPushCustomConfig) { + NimUIKitImpl.setCustomPushContentProvider(mixPushCustomConfig); + } + + /** + * 设置通讯录列表的事件监听器 + * + * @param contactEventListener 事件监听器 + */ + public static void setContactEventListener(ContactEventListener contactEventListener) { + NimUIKitImpl.setContactEventListener(contactEventListener); + } + + /** + * 设置单聊界面定制 SessionCustomization + * + * @param commonP2PSessionCustomization 聊天界面定制化 + */ + public static void setCommonP2PSessionCustomization(SessionCustomization commonP2PSessionCustomization) { + NimUIKitImpl.setCommonP2PSessionCustomization(commonP2PSessionCustomization); + } + + /** + * 设置群聊界面定制 SessionCustomization + * + * @param commonTeamSessionCustomization 聊天界面定制化 + */ + public static void setCommonTeamSessionCustomization(SessionCustomization commonTeamSessionCustomization) { + NimUIKitImpl.setCommonTeamSessionCustomization(commonTeamSessionCustomization); + } + + /** + * 设置最近联系人列表界面定制 RecentCustomization + * + * @param recentCustomization 最近联系人界面定制 + */ + public static void setRecentCustomization(RecentCustomization recentCustomization) { + NimUIKitImpl.setRecentCustomization(recentCustomization); + } + + /** + * 设置聊天室界面定制 ChatRoomSessionCustomization + * + * @param commonChatRoomSessionCustomization 聊天室界面定制化 + */ + public static void setCommonChatRoomSessionCustomization(ChatRoomSessionCustomization commonChatRoomSessionCustomization) { + NimUIKitImpl.setCommonChatRoomSessionCustomization(commonChatRoomSessionCustomization); + } + + /** + * 根据IM消息附件类型注册对应的消息项展示ViewHolder + * + * @param attach 附件类型 + * @param viewHolder 消息ViewHolder + */ + public static void registerMsgItemViewHolder(Class attach, Class viewHolder) { + NimUIKitImpl.registerMsgItemViewHolder(attach, viewHolder); + } + + /** + * 根据聊天室消息附件类型注册对应的消息项展示ViewHolder + * + * @param attach 附件类型 + * @param viewHolder 消息ViewHolder + */ + public static void registerChatRoomMsgItemViewHolder(Class attach, Class viewHolder) { + NimUIKitImpl.registerChatRoomMsgItemViewHolder(attach, viewHolder); + } + + /** + * 注册Tip类型消息项展示ViewHolder + * + * @param viewHolder Tip消息ViewHolder + */ + public static void registerTipMsgViewHolder(Class viewHolder) { + NimUIKitImpl.registerTipMsgViewHolder(viewHolder); + } + + /** + * 手动登陆,由于手动登陆完成之后,UIKit 需要设置账号、构建缓存等,使用此方法登陆 UIKit 会将这部分逻辑处理好,开发者只需要处理自己的逻辑即可 + * + * @param loginInfo 登陆账号信息 + * @param callback 登陆结果回调 + */ + public static AbortableFuture login(LoginInfo loginInfo, final RequestCallback callback) { + return NimUIKitImpl.login(loginInfo, callback); + } + + /** + * 手动登陆成功 + * + * @param account 登陆成功账号 + */ + public static void loginSuccess(String account) { + NimUIKitImpl.loginSuccess(account); + } + + /** + * 释放缓存,一般在注销时调用 + */ + public static void logout() { + NimUIKitImpl.logout(); + } + + /** + * 独立模式进入聊天室成功之后,调用此方法 + * + * @param data EnterChatRoomResultData + * @param independent 是否独立模式 + */ + public static void enterChatRoomSuccess(EnterChatRoomResultData data, boolean independent) { + NimUIKitImpl.enterChatRoomSuccess(data, independent); + } + + /** + * 退出聊天室之后,调用此方法 + * + * @param roomId 聊天室id + */ + public static void exitedChatRoom(String roomId) { + NimUIKitImpl.exitedChatRoom(roomId); + } + + /** + * 获取上下文 + * + * @return 必须初始化后才有值 + */ + public static Context getContext() { + return NimUIKitImpl.getContext(); + } + + + /** + * 设置当前登录用户的帐号 + * + * @param account 帐号 + */ + public static void setAccount(String account) { + NimUIKitImpl.setAccount(account); + } + + /** + * 获取当前登录的账号 + * + * @return 必须登录成功后才有值 + */ + public static String getAccount() { + return NimUIKitImpl.getAccount(); + } + + /** + * 打开单聊界面,若开发者未设置 {@link NimUIKitImpl#setCommonP2PSessionCustomization(SessionCustomization)}, + * 则定制化信息 SessionCustomization 为{@link DefaultP2PSessionCustomization} + *

+ * 若需要为目标会话提供单独定义的SessionCustomization,请使用{@link NimUIKitImpl#startChatting(Context, String, SessionTypeEnum, SessionCustomization, IMMessage)} + * + * @param context 上下文 + * @param account 目标账号 + */ + public static void startP2PSession(Context context, String account) { + NimUIKitImpl.startP2PSession(context, account); + } + + /** + * 同 {@link NimUIKitImpl#startP2PSession(Context, String)},同时聊天界面打开后,列表跳转至anchor位置 + * + * @param context 上下文 + * @param account 目标账号 + * @param anchor 跳转到指定消息的位置,不需要跳转填null + */ + public static void startP2PSession(Context context, String account, IMMessage anchor) { + NimUIKitImpl.startP2PSession(context, account, anchor); + } + + /** + * 打开群聊界面,若开发者未设置 {@link NimUIKitImpl#setCommonTeamSessionCustomization(SessionCustomization)}, + * 则定制化信息 SessionCustomization 为{@link DefaultTeamSessionCustomization} + *

+ * 若需要为目标会话提供单独定义的SessionCustomization,请使用{@link NimUIKitImpl#startChatting(Context, String, SessionTypeEnum, SessionCustomization, IMMessage)} + * + * @param context 上下文 + * @param tid 群id + */ + public static void startTeamSession(Context context, String tid) { + NimUIKitImpl.startTeamSession(context, tid); + } + + /** + * 同 {@link NimUIKitImpl#startTeamSession(Context, String)},同时聊天界面打开后,列表跳转至anchor位置 + * + * @param context 上下文 + * @param tid 群id + * @param anchor 跳转到指定消息的位置,不需要跳转填null + */ + public static void startTeamSession(Context context, String tid, IMMessage anchor) { + NimUIKitImpl.startTeamSession(context, tid, anchor); + } + + /** + * 同 {@link NimUIKitImpl#startTeamSession(Context, String)},同时聊天界面打开后,列表跳转至anchor位置 + * + * @param context 上下文 + * @param tid 群id + * @param customization 定制化信息。针对不同的聊天对象,可提供不同的定制化。 + * @param anchor 跳转到指定消息的位置,不需要跳转填null + */ + public static void startTeamSession(Context context, String tid, SessionCustomization customization, IMMessage anchor) { + NimUIKitImpl.startTeamSession(context, tid, customization, anchor); + } + + /** + * 打开一个聊天窗口,开始聊天 + * + * @param context 上下文 + * @param id 聊天对象ID(用户帐号account或者群组ID) + * @param sessionType 会话类型 + * @param customization 定制化信息。针对不同的聊天对象,可提供不同的定制化。 + * @param anchor 跳转到指定消息的位置,不需要跳转填null + */ + public static void startChatting(Context context, String id, SessionTypeEnum sessionType, SessionCustomization + customization, IMMessage anchor) { + NimUIKitImpl.startChatting(context, id, sessionType, customization, anchor); + } + + /** + * 打开一个聊天窗口(用于从聊天信息中创建群聊时,打开群聊) + * + * @param context 上下文 + * @param id 聊天对象ID(用户帐号account或者群组ID) + * @param sessionType 会话类型 + * @param customization 定制化信息。针对不同的聊天对象,可提供不同的定制化。 + * @param backToClass 返回的指定页面 + * @param anchor 跳转到指定消息的位置,不需要跳转填null + */ + public static void startChatting(Context context, String id, SessionTypeEnum sessionType, SessionCustomization customization, + Class backToClass, IMMessage anchor) { + NimUIKitImpl.startChatting(context, id, sessionType, customization, backToClass, anchor); + } + + /** + * 打开联系人选择器 + * + * @param context 上下文(Activity) + * @param option 联系人选择器可选配置项 + * @param requestCode startActivityForResult使用的请求码 + */ + public static void startContactSelector(Context context, ContactSelectActivity.Option option, int requestCode) { + NimUIKitImpl.startContactSelector(context, option, requestCode); + } + + /** + * 打开讨论组或高级群资料页 + * + * @param context 上下文 + * @param teamId 群id + */ + public static void startTeamInfo(Context context, String teamId) { + NimUIKitImpl.startTeamInfo(context, teamId); + } + + public static boolean isInitComplete() { + return NimUIKitImpl.isInitComplete(); + } + + /** + * 获取 “用户资料” 提供者 + * + * @return 必须在初始化后获取 + */ + public static IUserInfoProvider getUserInfoProvider() { + return NimUIKitImpl.getUserInfoProvider(); + } + + /** + * 获取 “用户资料” 变更监听管理者 + * UIKit 与 app 之间 userInfo 数据更新通知接口 + * + * @return UserInfoObservable + */ + public static UserInfoObservable getUserInfoObservable() { + return NimUIKitImpl.getUserInfoObservable(); + } + + /** + * 获取 “用户关系” 提供者 + * + * @return 必须在初始化后获取 + */ + public static ContactProvider getContactProvider() { + return NimUIKitImpl.getContactProvider(); + } + + /** + * 获取 “用户关系” 变更监听管理者 + * UIKit 与 app 之间 “用户关系” 数据更新通知接口 + * + * @return ContactChangedObservable + */ + public static ContactChangedObservable getContactChangedObservable() { + return NimUIKitImpl.getContactChangedObservable(); + } + + /** + * 获取群、群成员信息提供者 + * + * @return TeamProvider + */ + public static TeamProvider getTeamProvider() { + return NimUIKitImpl.getTeamProvider(); + } + + /** + * 设置群、群成员信息提供者 + * 不设置则采用 UIKit 内部默认 teamProvider + */ + public static void setTeamProvider(TeamProvider teamProvider) { + NimUIKitImpl.setTeamProvider(teamProvider); + } + + /** + * 获取群成员变化通知 + * + * @return TeamChangedObservable + */ + public static TeamChangedObservable getTeamChangedObservable() { + return NimUIKitImpl.getTeamChangedObservable(); + } + + /** + * 获取机器人信息提供者 + * + * @return RobotInfoProvider + */ + public static RobotInfoProvider getRobotInfoProvider() { + return NimUIKitImpl.getRobotInfoProvider(); + } + + /** + * 设置机器人信息提供者 + * 不设置将使用 uikit 内置默认 + * + * @param provider RobotInfoProvider + */ + public static void setRobotInfoProvider(RobotInfoProvider provider) { + NimUIKitImpl.setRobotInfoProvider(provider); + } + + /** + * 设置聊天室信息提供者 + * 不设置将使用 uikit 内置默认 + * + * @param provider ChatRoomProvider + */ + public static void setChatRoomProvider(ChatRoomProvider provider) { + NimUIKitImpl.setChatRoomProvider(provider); + } + + /** + * 获取聊天室信息提供者 + * + * @return ChatRoomProvider + */ + public static ChatRoomProvider getChatRoomProvider() { + return NimUIKitImpl.getChatRoomProvider(); + } + + /** + * 获取聊天室成员变更监听接口 + * + * @return ChatRoomMemberChangedObservable + */ + public static ChatRoomMemberChangedObservable getChatRoomMemberChangedObservable() { + return NimUIKitImpl.getChatRoomMemberChangedObservable(); + } + + /** + * 获取图片缓存 + * + * @return Glide图片缓存 + */ + public static ImageLoaderKit getImageLoaderKit() { + return NimUIKitImpl.getImageLoaderKit(); + } + + /** + * 设置在线状态文案提供者 + * + * @param onlineStateContentProvider 文案内容提供者 + */ + public static void setOnlineStateContentProvider(OnlineStateContentProvider onlineStateContentProvider) { + NimUIKitImpl.setOnlineStateContentProvider(onlineStateContentProvider); + } + + /** + * 获取配置的用户在线状态文案提供者 + * + * @return 文案提供者 + */ + public static OnlineStateContentProvider getOnlineStateContentProvider() { + return NimUIKitImpl.getOnlineStateContentProvider(); + } + + /** + * 设置了 onlineStateContentProvider 则表示UIKit需要展示在线状态 + * + * @return 在线状态开关 + */ + public static boolean enableOnlineState() { + return NimUIKitImpl.enableOnlineState(); + } + + /** + * 通知在线状态发生变化 + * + * @param accounts 状态变化的账号 + */ + @Deprecated + public static void notifyOnlineStateChange(Set accounts) { + getOnlineStateChangeObservable().notifyOnlineStateChange(accounts); + } + + /** + * 获取在线状态变更通知接口 + * @return + */ + public static OnlineStateChangeObservable getOnlineStateChangeObservable() { + return NimUIKitImpl.getOnlineStateChangeObservable(); + } + + /** + * 设置是否听筒模式 + * + * @param enable + */ + public static void setEarPhoneModeEnable(boolean enable) { + NimUIKitImpl.setEarPhoneModeEnable(enable); + } + + /** + * 获取是否听筒模式 + */ + public static boolean isEarPhoneModeEnable() { + return NimUIKitImpl.getEarPhoneModeEnable(); + } + + + public static void startChat(String id,Context activity){ + List accounts=new ArrayList<>(); + accounts.add(id); +// NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(id); +// if (info!=null){ +// jump(id,info,activity); +// return; +// } + NIMClient.getService(UserService.class).fetchUserInfo(accounts) + .setCallback(new RequestCallback>() { + @Override + public void onSuccess(List userInfos) { + NimUserInfo user=userInfos.get(0); + jump(id,user,activity); + } + @Override + public void onFailed(int i) { + NimUIKit.startP2PSession(activity, id); + } + @Override + public void onException(Throwable throwable) { + NimUIKit.startP2PSession(activity, id); + } + }); + } + public static void jump(String id,NimUserInfo user,Context from){ + Map extension = user.getExtensionMap(); + Integer status=0; + String content=""; + if(extension!=null){ + for (String key : extension.keySet()) { + if (key.equals("msg")) { + content= (String) extension.get(key); + }else if(key.equals("user_forbid_status")){ + status= (Integer) extension.get(key); + } + } + } + if(status==1&&!StringUtil.isEmpty(content)){ + MaleToast.showMessage(getContext(),content); + NIMClient.getService(MsgService.class).deleteRecentContact2(id, SessionTypeEnum.P2P); + return; + }else { + NimUIKit.startP2PSession(from, id); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/UIKitInitStateListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/UIKitInitStateListener.java new file mode 100644 index 0000000..44ae8e7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/UIKitInitStateListener.java @@ -0,0 +1,9 @@ +package com.fengliyan.tianlesue.im.uikit.api; + +/** + * Created by hzchenkang on 2017/11/6. + */ + +public interface UIKitInitStateListener { + void onFinish(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/UIKitOptions.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/UIKitOptions.java new file mode 100644 index 0000000..27c928b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/UIKitOptions.java @@ -0,0 +1,172 @@ +package com.fengliyan.tianlesue.im.uikit.api; + +import com.fengliyan.tianlesue.R; +import com.netease.nimlib.sdk.media.record.RecordType; + +/** + * Created by hzchenkang on 2017/10/19. + */ + +public class UIKitOptions { + + /** + * 配置 APP 保存图片/语音/文件/log等数据缓存的目录(一般配置在SD卡目录) + *

+ * 默认为 /sdcard/{packageName}/ + */ + public String appCacheDir; + + /** + * 独立聊天室模式,没有 IM 业务 + */ + public boolean independentChatRoom = false; + + /** + * 是否加载表情贴图 + */ + + public boolean loadSticker = true; + + /** + * 开启@功能 + */ + public boolean aitEnable = true; + + /** + * 支持@群成员 + */ + public boolean aitTeamMember = true; + + /** + * 支持在 IM 聊天中@机器人 + */ + public boolean aitIMRobot = true; + + /** + * 支持在 Chat Room 中@机器人 + */ + public boolean aitChatRoomRobot = true; + + /** + * UIKit 异步初始化 + * 使用异步方式构建能缩短初始化时间,但同时必须查看初始化状态或者监听初始化成功通知 + */ + public boolean initAsync = false; + + /** + * 使用云信托管账号体系,构建缓存 + */ + public boolean buildNimUserCache = true; + + /** + * 构建群缓存 + */ + public boolean buildTeamCache = true; + + /** + * 构建群好友关系缓存 + */ + public boolean buildFriendCache = true; + + /** + * 构建智能机器人缓存 + */ + public boolean buildRobotInfoCache = true; + + /** + * 构建聊天室成员缓存 + */ + public boolean buildChatRoomMemberCache = true; + + /** + * 消息列表每隔多久显示一条消息时间信息,默认五分钟 + */ + public long displayMsgTimeWithInterval = 5 * 60 * 1000; + + /** + * 单次抓取消息条数配置 + */ + public int messageCountLoadOnce = 20; + + /** + * IM 接收到的消息时,内容区域背景的drawable id + */ +// public int messageLeftBackground = R.drawable.nim_message_item_left_selector; + public int messageLeftBackground = R.drawable.ic_message_alice; + public int messageLeftBackgroundVip = R.drawable.ic_message_alice_vip; + public int messageLeftBackgroundVipMan = R.drawable.ic_message_alice_vip_man; + + /** + * IM 发送出去的消息时,内容区域背景的drawable id + */ +// public int messageRightBackground = R.drawable.nim_message_item_right_selector; +// public int messageRightBackground = R.drawable.ic_message_me; + public int messageRightBackground = R.drawable.ic_huang; + public int messageRightBackgroundVIP = R.drawable.ic_huang_vip; + public int messageRightBackgroundVIPMan = R.drawable.ic_huang_vip_man; + + + /** + * chat room 接收到的消息时,内容区域背景的drawable id + */ + public int chatRoomMsgLeftBackground = 0; + + /** + * chat room 发送出去的消息时,内容区域背景的drawable id + */ + public int chatRoomMsgRightBackground = 0; + + /** + * 全局是否使用消息已读,如果设置为false,UIKit 组件将不会发送、接收已读回执 + */ + public boolean shouldHandleReceipt = true; + + /** + * 文本框最大输入字符数目 + */ + public int maxInputTextLength = 5000; + + /** + * 录音类型,默认aac + */ + public RecordType audioRecordType = RecordType.AAC; + + /** + * 录音时长限制,单位秒,默认最长120s + */ + public int audioRecordMaxTime = 120; + + /** + * 不显示语音消息未读红点 + */ + public boolean disableAudioPlayedStatusIcon = false; + + /** + * 禁止音频轮播 + */ + public boolean disableAutoPlayNextAudio = false; + + + /** + * 是否开启允许群管理员撤回他人消息 + */ + public boolean enableTeamManagerRevokeMsg = true; + + + /** + * 返回默认的针对独立模式聊天室的 UIKitOptions + * + * @return + */ + + public static UIKitOptions buildForIndependentChatRoom() { + UIKitOptions options = new UIKitOptions(); + options.buildFriendCache = false; + options.buildNimUserCache = false; + options.buildTeamCache = false; + options.buildRobotInfoCache = false; + options.loadSticker = false; + options.independentChatRoom = true; + return options; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/SimpleCallback.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/SimpleCallback.java new file mode 100644 index 0000000..8430ee2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/SimpleCallback.java @@ -0,0 +1,16 @@ +package com.fengliyan.tianlesue.im.uikit.api.model; + +/** + * 简单的回调接口 + */ +public interface SimpleCallback { + + /** + * 回调函数返回结果 + * + * @param success 是否成功,结果是否有效 + * @param result 结果 + * @param code 失败时错误码 + */ + void onResult(boolean success, T result, int code); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomMemberChangedObservable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomMemberChangedObservable.java new file mode 100644 index 0000000..47255e7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomMemberChangedObservable.java @@ -0,0 +1,51 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.chatroom; + +import android.content.Context; +import android.os.Handler; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +import java.util.ArrayList; +import java.util.List; + +/** + * UIKit 与 app 聊天室成员变化监听接口 + */ + +public class ChatRoomMemberChangedObservable { + + private List observers = new ArrayList<>(); + private Handler uiHandler; + + public ChatRoomMemberChangedObservable(Context context) { + uiHandler = new Handler(context.getMainLooper()); + } + + public synchronized void registerObserver(RoomMemberChangedObserver observer, boolean register) { + if (observer == null) { + return; + } + if (register) { + observers.add(observer); + } else { + observers.remove(observer); + } + } + + public synchronized void notifyMemberChange(final ChatRoomMember member, final boolean in) { + uiHandler.post(new Runnable() { + @Override + public void run() { + if (in) { + for (RoomMemberChangedObserver o : observers) { + o.onRoomMemberIn(member); + } + } else { + for (RoomMemberChangedObserver o : observers) { + o.onRoomMemberExit(member); + } + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomProvider.java new file mode 100644 index 0000000..1a6cef9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomProvider.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.chatroom; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.netease.nimlib.sdk.chatroom.constant.MemberQueryType; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +import java.util.List; + +/** + * 聊天室成员提供者 + */ + +public interface ChatRoomProvider { + + /** + * 获取聊天室成员 + * + * @param roomId 聊天室 + * @param account 账号 + * @return ChatRoomMember + */ + ChatRoomMember getChatRoomMember(String roomId, String account); + + /** + * 异步获取聊天室成员 + * + * @param roomId 聊天室 + * @param account 账号 + * @param callback 回调 + */ + void fetchMember(String roomId, String account, SimpleCallback callback); + + /** + * 异步获取聊天室成员列表 + * + * @param roomId 聊天室 + * @param memberQueryType 请求类型 + * @param time 时间 + * @param limit 条数限制 + * @param callback 回调 + */ + void fetchRoomMembers(String roomId, MemberQueryType memberQueryType, long time, int limit, SimpleCallback> callback); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomSessionCustomization.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomSessionCustomization.java new file mode 100644 index 0000000..00dd787 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/ChatRoomSessionCustomization.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.chatroom; + +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; + +import java.io.Serializable; +import java.util.ArrayList; + +/** + * 聊天室聊天界面定制化参数。 可定制:
+ * 1. 加号展开后的按钮和动作
+ */ +public class ChatRoomSessionCustomization implements Serializable { + + /** + * 加号展开后的action list。 + * 默认已包含图片,视频和地理位置 + */ + public ArrayList actions; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/RoomMemberChangedObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/RoomMemberChangedObserver.java new file mode 100644 index 0000000..b7e923e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/chatroom/RoomMemberChangedObserver.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.chatroom; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +/** + * UIKit 与 app 聊天室成员数据变更监听接口 + */ + +public interface RoomMemberChangedObserver { + + /** + * 聊天室新增成员 + * + * @param member 成员 + */ + void onRoomMemberIn(ChatRoomMember member); + + /** + * 聊天室退出成员 + * + * @param member 成员 + */ + void onRoomMemberExit(ChatRoomMember member); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactChangedObservable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactChangedObservable.java new file mode 100644 index 0000000..c9ec0e1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactChangedObservable.java @@ -0,0 +1,90 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.contact; + +import android.content.Context; +import android.os.Handler; + +import java.util.ArrayList; +import java.util.List; + +/** + * 好友关系变动观察者管理 + */ + +public class ContactChangedObservable { + + private List observers = new ArrayList<>(); + private Handler uiHandler; + + public ContactChangedObservable(Context context) { + if (context != null) { + uiHandler = new Handler(context.getMainLooper()); + } + } + + public synchronized void registerObserver(ContactChangedObserver observer, boolean register) { + if (observer == null) { + return; + } + if (register) { + observers.add(observer); + } else { + observers.remove(observer); + } + } + + public synchronized void notifyAddedOrUpdated(final List accounts) { + if (uiHandler == null) { + return; + } + uiHandler.post(new Runnable() { + @Override + public void run() { + for (ContactChangedObserver observer : observers) { + observer.onAddedOrUpdatedFriends(accounts); + } + } + }); + } + + public synchronized void notifyDelete(final List accounts) { + if (uiHandler == null) { + return; + } + uiHandler.post(new Runnable() { + @Override + public void run() { + for (ContactChangedObserver observer : observers) { + observer.onDeletedFriends(accounts); + } + } + }); + } + + public synchronized void notifyAddToBlackList(final List accounts) { + if (uiHandler == null) { + return; + } + uiHandler.post(new Runnable() { + @Override + public void run() { + for (ContactChangedObserver observer : observers) { + observer.onAddUserToBlackList(accounts); + } + } + }); + } + + public synchronized void notifyRemoveFromBlackList(final List accounts) { + if (uiHandler == null) { + return; + } + uiHandler.post(new Runnable() { + @Override + public void run() { + for (ContactChangedObserver observer : observers) { + observer.onRemoveUserFromBlackList(accounts); + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactChangedObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactChangedObserver.java new file mode 100644 index 0000000..3aa1044 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactChangedObserver.java @@ -0,0 +1,38 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.contact; + +import java.util.List; + +/** + * UIKit 与 app 好友关系变化监听接口 + */ + +public interface ContactChangedObserver { + + /** + * 增加或者更新好友 + * + * @param accounts 账号列表 + */ + void onAddedOrUpdatedFriends(List accounts); + + /** + * 删除好友 + * + * @param accounts 账号列表 + */ + void onDeletedFriends(List accounts); + + /** + * 增加到黑名单 + * + * @param accounts 账号列表 + */ + void onAddUserToBlackList(List accounts); + + /** + * 从黑名单移除 + * + * @param accounts 账号列表 + */ + void onRemoveUserFromBlackList(List accounts); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactEventListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactEventListener.java new file mode 100644 index 0000000..831f4d4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactEventListener.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.contact; + +import android.content.Context; + +/** + * 通讯录联系人列表一些点击事件的响应处理函数 + */ +public interface ContactEventListener { + /** + * 通讯录联系人项点击事件处理,一般打开会话窗口 + * + * @param account 点击的联系人帐号 + */ + void onItemClick(Context context, String account); + + /** + * 通讯录联系人项长按事件处理,一般弹出菜单:移除好友、添加到星标好友等 + * + * @param account 点击的联系人帐号 + */ + void onItemLongClick(Context context, String account); + + /** + * 联系人头像点击相应,一般跳转到用户资料页面 + * + * @param account 点击的联系人帐号 + */ + void onAvatarClick(Context context, String account); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactProvider.java new file mode 100644 index 0000000..e5727a3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactProvider.java @@ -0,0 +1,38 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.contact; + +import java.util.List; + +/** + * 通讯录(联系人)数据源提供者 + */ +public interface ContactProvider { + /** + * 返回本地所有好友用户信息(通讯录一般列出所有的好友) + * + * @return 用户信息集合 + */ + List getUserInfoOfMyFriends(); + + /** + * 返回我的好友数量,提供给通讯录显示所有联系人数量使用 + * + * @return 好友个数 + */ + int getMyFriendsCount(); + + /** + * 获取备注 + * + * @param account 账号 + * @return 备注 + */ + String getAlias(String account); + + /** + * 是否是自己的好友 + * + * @param account 账号 + * @return 结果 + */ + boolean isMyFriend(String account); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactsCustomization.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactsCustomization.java new file mode 100644 index 0000000..ba203b8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/contact/ContactsCustomization.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.contact; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder.AbsContactViewHolder; + +import java.util.List; + +/** + * 通讯录列表定制,目前支持: + * 1.在联系人列表上方加入功能项,并处理点击事件 + */ +public interface ContactsCustomization { + + /** + * 获取功能项ViewHolder的Class(第三方APP提供) + * + * @return 实现AbsContactViewHolder且Item数据实现AbsContactItem的自定义类 + */ + Class> onGetFuncViewHolderClass(); + + /** + * 获取所有功能项(第三方APP提供) + * + * @return 功能项集合 + */ + List onGetFuncItems(); + + /** + * 用户自定义的功能项(折叠群、黑名单、我的电脑等)点击事件处理,一般跳转到相应功能模块 + * + * @param item 自定义的功能项的基类,一般可以通过"=="、"instance of"来判断对应的具体功能 + */ + void onFuncItemClick(AbsContactItem item); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/location/LocationProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/location/LocationProvider.java new file mode 100644 index 0000000..66e3211 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/location/LocationProvider.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.location; + +import android.content.Context; + +/** + * 定位信息提供者类。用于提供地理位置消息,以及根据地理位置打开对应的地图。
+ * 第三方app可自由选择定位SDK + */ +public interface LocationProvider { + + // 请求定位信息,由callback返回当前地理位置信息 + // 定位成功后,请调用callback.onSuccess,如果取消定位或定位失败,无需调用 + void requestLocation(Context context, Callback callback); + + // 根据当前地理位置打开地图 + void openMap(Context context, double longitude, double latitude, String address); + + // 定位请求的回调函数。如果定位不成功,或者用户取消,不回调即可。 + interface Callback { + void onSuccess(double longitude, double latitude, String address); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/CustomPushContentProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/CustomPushContentProvider.java new file mode 100644 index 0000000..1d7446e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/CustomPushContentProvider.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.main; + +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.Map; + +/** + * 用户自定义推送 content 以及 payload 的接口 + */ + +public interface CustomPushContentProvider { + + /** + * 在消息发出去之前,回调此方法,用户需实现自定义的推送文案 + * + * @param message + */ + String getPushContent(IMMessage message); + + /** + * 在消息发出去之前,回调此方法,用户需实现自定义的推送payload,它可以被消息接受者在通知栏点击之后得到 + * + * @param message + */ + Map getPushPayload(IMMessage message); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/LoginSyncDataStatusObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/LoginSyncDataStatusObserver.java new file mode 100644 index 0000000..57ef766 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/LoginSyncDataStatusObserver.java @@ -0,0 +1,144 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.main; + +import android.os.Handler; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.auth.AuthServiceObserver; +import com.netease.nimlib.sdk.auth.constant.LoginSyncStatus; + +import java.util.ArrayList; +import java.util.List; + +/** + * 登录 + * Created by huangjun on 2015/10/9. + */ +public class LoginSyncDataStatusObserver { + + private static final String TAG = LoginSyncDataStatusObserver.class.getSimpleName(); + + private static final int TIME_OUT_SECONDS = 10; + + private Handler uiHandler; + + private Runnable timeoutRunnable; + + /** + * 状态 + */ + private LoginSyncStatus syncStatus = LoginSyncStatus.NO_BEGIN; + + /** + * 监听 + */ + private List> observers = new ArrayList<>(); + + /** + * 注销时清除状态&监听 + */ + public void reset() { + syncStatus = LoginSyncStatus.NO_BEGIN; + observers.clear(); + } + + /** + * 在App启动时向SDK注册登录后同步数据过程状态的通知 + * 调用时机:主进程Application onCreate中 + */ + public void registerLoginSyncDataStatus(boolean register) { + LogUtil.i(TAG, "observe login sync data completed event on Application create"); + NIMClient.getService(AuthServiceObserver.class).observeLoginSyncDataStatus(loginSyncStatusObserver, register); + } + + Observer loginSyncStatusObserver = new Observer() { + @Override + public void onEvent(LoginSyncStatus status) { + syncStatus = status; + if (status == LoginSyncStatus.BEGIN_SYNC) { + LogUtil.i(TAG, "login sync data begin"); + } else if (status == LoginSyncStatus.SYNC_COMPLETED) { + LogUtil.i(TAG, "login sync data completed"); + onLoginSyncDataCompleted(false); + } + } + }; + + /** + * 监听登录后同步数据完成事件,缓存构建完成后自动取消监听 + * 调用时机:登录成功后 + * + * @param observer 观察者 + * @return 返回true表示数据同步已经完成或者不进行同步,返回false表示正在同步数据 + */ + public boolean observeSyncDataCompletedEvent(Observer observer) { + if (syncStatus == LoginSyncStatus.NO_BEGIN || syncStatus == LoginSyncStatus.SYNC_COMPLETED) { + /* + * NO_BEGIN 如果登录后未开始同步数据,那么可能是自动登录的情况: + * PUSH进程已经登录同步数据完成了,此时UI进程启动后并不知道,这里直接视为同步完成 + */ + return true; + } + + // 正在同步 + if (!observers.contains(observer)) { + observers.add(observer); + } + + // 超时定时器 + if (uiHandler == null) { + uiHandler = new Handler(NimUIKit.getContext().getMainLooper()); + } + + if (timeoutRunnable == null) { + timeoutRunnable = new Runnable() { + @Override + public void run() { + // 如果超时还处于开始同步的状态,模拟结束 + if (syncStatus == LoginSyncStatus.BEGIN_SYNC) { + onLoginSyncDataCompleted(true); + } + } + }; + } + + uiHandler.removeCallbacks(timeoutRunnable); + uiHandler.postDelayed(timeoutRunnable, TIME_OUT_SECONDS * 1000); + + return false; + } + + /** + * 登录同步数据完成处理 + */ + private void onLoginSyncDataCompleted(boolean timeout) { + LogUtil.i(TAG, "onLoginSyncDataCompleted, timeout=" + timeout); + + // 移除超时任务(有可能完成包到来的时候,超时任务都还没创建) + if (timeoutRunnable != null) { + uiHandler.removeCallbacks(timeoutRunnable); + } + + // 通知上层 + for (Observer o : observers) { + o.onEvent(null); + } + + // 重置状态 + reset(); + } + + + /** + * 单例 + */ + public static LoginSyncDataStatusObserver getInstance() { + return InstanceHolder.instance; + } + + static class InstanceHolder { + final static LoginSyncDataStatusObserver instance = new LoginSyncDataStatusObserver(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateChangeObservable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateChangeObservable.java new file mode 100644 index 0000000..a5de8cf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateChangeObservable.java @@ -0,0 +1,45 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.main; + +import android.content.Context; +import android.os.Handler; + +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + * 在线状态事件变更通知接口 + */ + +public class OnlineStateChangeObservable { + + // 在线状态变化监听 + private List onlineStateChangeObservers; + private Handler uiHandler; + + public OnlineStateChangeObservable(Context context) { + onlineStateChangeObservers = new LinkedList<>(); + uiHandler = new Handler(context.getMainLooper()); + } + + public synchronized void registerOnlineStateChangeListeners(OnlineStateChangeObserver onlineStateChangeObserver, boolean register) { + if (register) { + onlineStateChangeObservers.add(onlineStateChangeObserver); + }else { + onlineStateChangeObservers.remove(onlineStateChangeObserver); + } + } + + public synchronized void notifyOnlineStateChange(final Set accounts) { + uiHandler.post(new Runnable() { + @Override + public void run() { + if (onlineStateChangeObservers != null) { + for (OnlineStateChangeObserver listener : onlineStateChangeObservers) { + listener.onlineStateChange(accounts); + } + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateChangeObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateChangeObserver.java new file mode 100644 index 0000000..bcb234c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateChangeObserver.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.main; + +import java.util.Set; + +/** + * Created by hzchenkang on 2017/4/5. + */ + +public interface OnlineStateChangeObserver { + + /** + * 通知在线状态事件变化 + * + * @param account 在线状态事件发生变化的账号 + */ + void onlineStateChange(Set account); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateContentProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateContentProvider.java new file mode 100644 index 0000000..b3f08c4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/main/OnlineStateContentProvider.java @@ -0,0 +1,14 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.main; + +/** + * Created by hzchenkang on 2017/3/31. + */ + +public interface OnlineStateContentProvider { + + // 用于展示最近联系人界面的在线状态 + String getSimpleDisplay(String account); + + // 用于展示聊天界面的在线状态 + String getDetailDisplay(String account); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/recent/RecentCustomization.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/recent/RecentCustomization.java new file mode 100644 index 0000000..3339045 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/recent/RecentCustomization.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.recent; + +import com.netease.nimlib.sdk.msg.model.RecentContact; + +import java.io.Serializable; + +/** + * 会话界面定制 + * 1. 会话项默认文案定制  + * Created by huangjun on 2017/9/29. + */ + +public class RecentCustomization implements Serializable { + public String getDefaultDigest(RecentContact recent) { + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/robot/RobotInfoProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/robot/RobotInfoProvider.java new file mode 100644 index 0000000..356b7f5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/robot/RobotInfoProvider.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.robot; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; + +import java.util.List; + +/** + * 智能机器人信息提供者 + */ + +public interface RobotInfoProvider { + + /** + * 根据 id 获取智能机器人 + * + * @param account 智能机器人id + * @return NimRobotInfo + */ + NimRobotInfo getRobotByAccount(String account); + + /** + * 获取所有的智能机器人 + * + * @return 智能机器人列表 + */ + List getAllRobotAccounts(); + + /** + * IM 模式下,获取(异步)智能机器人 + */ + void fetchRobotList(SimpleCallback> callback); + + /** + * 独立聊天室模式下,获取(异步)智能机器人 + * + * @param roomId 聊天室id + */ + void fetchRobotListIndependent(String roomId, SimpleCallback> callback); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/session/SessionCustomization.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/session/SessionCustomization.java new file mode 100644 index 0000000..cee96c1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/session/SessionCustomization.java @@ -0,0 +1,77 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.session; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.Serializable; +import java.util.ArrayList; + +/** + * 聊天界面定制化参数。 可定制:
+ * 1. 聊天背景
+ * 2. 加号展开后的按钮和动作
+ * 3. ActionBar右侧按钮。 + */ +public class SessionCustomization implements Serializable { + + /** + * 聊天背景。优先使用uri,如果没有提供uri,使用color。如果没有color,使用默认。uri暂时支持以下格式:
+ * drawable: android.resource://包名/drawable/资源名 + * assets: file:///android_asset/{asset文件路径} + * file: file:///文件绝对路径 + */ + public String backgroundUri; + public int backgroundColor; + + // UIKit + public boolean withSticker; + + /** + * 加号展开后的action list。 + */ + public ArrayList actions; + + /** + * ActionBar右侧可定制按钮。默认为空。 + */ + public ArrayList buttons; + + /** + * 如果OptionsButton的点击响应中需要startActivityForResult,可在此函数中处理结果。 + * 需要注意的是,由于加号中的Action的限制,RequestCode只能使用int的最低8位。 + * + * @param activity 当前的聊天Activity + * @param requestCode 请求码 + * @param resultCode 结果码 + * @param data 返回的结果数据 + */ + public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { + } + + public boolean isAllowSendMessage(IMMessage message) { + return true; + } + + // uikit内建了对贴图消息的输入和管理展示,并和emoji表情整合在了一起,但贴图消息的附件定义开发者需要根据自己的扩展 + public MsgAttachment createStickerAttachment(String category, String item) { + return null; + } + + /** + * ActionBar 右侧按钮,可定制icon和点击事件 + */ + public static abstract class OptionsButton implements Serializable { + + // 图标drawable id + public int iconId; + + // 响应事件 + public abstract void onClick(Context context, View view, String sessionId); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/session/SessionEventListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/session/SessionEventListener.java new file mode 100644 index 0000000..6dc36f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/session/SessionEventListener.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.session; + +import android.content.Context; + +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * 会话窗口消息列表一些点击事件的响应处理函数 + */ +public interface SessionEventListener { + + // 头像点击事件处理,一般用于打开用户资料页面 + void onAvatarClicked(Context context, IMMessage message); + + void onAvatarRightClicked(Context context, IMMessage message); + + // 头像长按事件处理,一般用于群组@功能,或者弹出菜单,做拉黑,加好友等功能 + void onAvatarLongClicked(Context context, IMMessage message); + + // 已读回执事件处理,用于群组的已读回执事件的响应,弹出消息已读详情 + void onAckMsgClicked(Context context, IMMessage message); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamChangedObservable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamChangedObservable.java new file mode 100644 index 0000000..b66f1a8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamChangedObservable.java @@ -0,0 +1,93 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.team; + +import android.content.Context; +import android.os.Handler; + +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.List; + +/** + * 群、群成员变更通知接口 + */ + +public class TeamChangedObservable { + + private List teamObservers = new ArrayList<>(); + private List memberObservers = new ArrayList<>(); + + private Handler uiHandler; + + public TeamChangedObservable(Context context) { + uiHandler = new Handler(context.getMainLooper()); + } + + public synchronized void registerTeamDataChangedObserver(TeamDataChangedObserver o, boolean register) { + if (register) { + if (teamObservers.contains(o)) { + return; + } + teamObservers.add(o); + } else { + teamObservers.remove(o); + } + } + + public synchronized void registerTeamMemberDataChangedObserver(TeamMemberDataChangedObserver o, boolean register) { + if (register) { + if (memberObservers.contains(o)) { + return; + } + memberObservers.add(o); + } else { + memberObservers.remove(o); + } + } + + public synchronized void notifyTeamDataUpdate(final List teams) { + uiHandler.post(new Runnable() { + @Override + public void run() { + for (TeamDataChangedObserver o : teamObservers) { + o.onUpdateTeams(teams); + } + } + }); + } + + public synchronized void notifyTeamDataRemove(final Team team) { + uiHandler.post(new Runnable() { + @Override + public void run() { + for (TeamDataChangedObserver o : teamObservers) { + o.onRemoveTeam(team); + } + } + }); + + } + + public synchronized void notifyTeamMemberDataUpdate(final List members) { + uiHandler.post(new Runnable() { + @Override + public void run() { + for (TeamMemberDataChangedObserver o : memberObservers) { + o.onUpdateTeamMember(members); + } + } + }); + } + + public synchronized void notifyTeamMemberRemove(final List members) { + uiHandler.post(new Runnable() { + @Override + public void run() { + for (TeamMemberDataChangedObserver o : memberObservers) { + o.onRemoveTeamMember(members); + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamDataChangedObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamDataChangedObserver.java new file mode 100644 index 0000000..27618e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamDataChangedObserver.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.team; + +import com.netease.nimlib.sdk.team.model.Team; + +import java.util.List; + +/** + * UIKit 与 app 群数据变更监听接口 + */ + +public interface TeamDataChangedObserver { + + /** + * 群更新 + * + * @param teams 群列表 + */ + void onUpdateTeams(List teams); + + /** + * 群删除 + * + * @param team) 群 + */ + void onRemoveTeam(Team team); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamMemberDataChangedObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamMemberDataChangedObserver.java new file mode 100644 index 0000000..fa83c65 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamMemberDataChangedObserver.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.team; + +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.List; + +/** + * UIKit 与 app 群成员数据变更监听接口 + */ + +public interface TeamMemberDataChangedObserver { + + /** + * 成员更新 + * + * @param members 成员列表 + */ + void onUpdateTeamMember(List members); + + /** + * 成员删除 + * + * @param members 成员列表 + */ + void onRemoveTeamMember(List members); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamProvider.java new file mode 100644 index 0000000..14da24b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/team/TeamProvider.java @@ -0,0 +1,74 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.team; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.List; + +/** + * 群、群成员信息提供者 + */ + +public interface TeamProvider { + /** + * 根据teamId 异步获取群信息 + * + * @param teamId 群id + * @param callback 回调 + */ + void fetchTeamById(String teamId, SimpleCallback callback); + + /** + * 根据teamId 同步获取群信息 + * + * @param teamId 群id + * @return 群信息Team + */ + Team getTeamById(String teamId); + + /** + * 获取当前账号所有的群 + * + * @return 群列表 + */ + List getAllTeams(); + + /** + * 获取当前账号所有的指定类型的群 + * + * @return 群列表 + */ + List getAllTeamsByType(TeamTypeEnum teamTypeEnum); + + /** + * 根据群id异步获取当前群所有的群成员信息 + * + * @param teamId 群id + * @param callback 回调 + */ + void fetchTeamMemberList(String teamId, SimpleCallback> callback); + + /** + * 根据群id、账号(异步)查询群成员资料 + */ + void fetchTeamMember(String teamId, String account, SimpleCallback callback); + + /** + * 根据群id 同步获取当前群所有的群成员信息 + * + * @param teamId 群id + * @return 群成员信息列表 + */ + List getTeamMemberList(String teamId); + + /** + * 获取群成员资料 + * + * @param teamId 群id + * @param account 成员账号 + * @return TeamMember + */ + TeamMember getTeamMember(String teamId, String account); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/IUserInfoProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/IUserInfoProvider.java new file mode 100644 index 0000000..8359868 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/IUserInfoProvider.java @@ -0,0 +1,45 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.user; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +import java.util.List; + +/** + * Created by hzchenkang on 2017/10/24. + */ + +public interface IUserInfoProvider { + + /** + * 同步获取userInfo + * + * @param account 账号 + * @return userInfo + */ + T getUserInfo(String account); + + /** + * 同步获取userInfo列表 + * + * @param accounts 账号 + * @return userInfo + */ + List getUserInfo(List accounts); + + /** + * 异步获取userInfo + * + * @param account 账号id + * @param callback 回调 + */ + void getUserInfoAsync(String account, SimpleCallback callback); + + /** + * 异步获取userInfo列表 + * + * @param accounts 账号id 集合 + * @param callback 回调 + */ + void getUserInfoAsync(List accounts, final SimpleCallback> callback); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/UserInfoObservable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/UserInfoObservable.java new file mode 100644 index 0000000..86a36cf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/UserInfoObservable.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.user; + +import android.content.Context; +import android.os.Handler; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用户资料变动观察者管理 + */ +public class UserInfoObservable { + + private List observers = new ArrayList<>(); + private Handler uiHandler; + + public UserInfoObservable(Context context) { + uiHandler = new Handler(context.getMainLooper()); + } + + synchronized public void registerObserver(UserInfoObserver observer, boolean register) { + if (observer == null) { + return; + } + if (register) { + observers.add(observer); + } else { + observers.remove(observer); + } + } + + synchronized public void notifyUserInfoChanged(final List accounts) { + uiHandler.post(new Runnable() { + @Override + public void run() { + for (UserInfoObserver observer : observers) { + observer.onUserInfoChanged(accounts); + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/UserInfoObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/UserInfoObserver.java new file mode 100644 index 0000000..6cc7f11 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/model/user/UserInfoObserver.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.im.uikit.api.model.user; + +import java.util.List; + +/** + * UIKit 与 app 好友关系变化监听接口 + */ + +public interface UserInfoObserver { + + /** + * 用户信息变更 + * + * @param accounts 账号列表 + */ + void onUserInfoChanged(List accounts); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/MessageRevokeTip.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/MessageRevokeTip.java new file mode 100644 index 0000000..d10ef6e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/MessageRevokeTip.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.im.uikit.api.wrapper; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.model.TeamMember; + +/** + * 消息撤回通知文案 + */ + +public class MessageRevokeTip { + + public static String getRevokeTipContent(IMMessage item, String revokeAccount) { + + String fromAccount = item.getFromAccount(); + if (item.getMsgType() == MsgTypeEnum.robot) { + RobotAttachment robotAttachment = (RobotAttachment) item.getAttachment(); + if (robotAttachment.isRobotSend()) { + fromAccount = robotAttachment.getFromRobotAccount(); + } + } + + if (!TextUtils.isEmpty( + revokeAccount) && !revokeAccount.equals(fromAccount)) { + return getRevokeTipOfOther(item.getSessionId(), item.getSessionType(), revokeAccount); + } else { + String revokeNick = ""; // 撤回者 + if (item.getSessionType() == SessionTypeEnum.Team) { + revokeNick = TeamHelper.getTeamMemberDisplayNameYou(item.getSessionId(), item.getFromAccount()); + } else if (item.getSessionType() == SessionTypeEnum.P2P) { + revokeNick = item.getFromAccount().equals(NimUIKit.getAccount()) ? "你" : "对方"; + } + return revokeNick + "撤回了一条消息"; + } + } + + // 撤回其他人的消息时,获取tip + public static String getRevokeTipOfOther(String sessionID, SessionTypeEnum sessionType, String revokeAccount) { + if (sessionType == SessionTypeEnum.Team) { + String revokeNick = ""; // 撤回者 + + if (NimUIKit.getAccount().equals(revokeAccount)) { + revokeNick = "你"; + } else { + TeamMember member = NimUIKit.getTeamProvider().getTeamMember(sessionID, revokeAccount); + + String revoker = TeamHelper.getDisplayNameWithoutMe(sessionID, revokeAccount); + + if (member == null || member.getType() == TeamMemberType.Manager) { + revokeNick = "管理员 " + revoker + " "; + } else if (member.getType() == TeamMemberType.Owner) { + revokeNick = "群主 " + revoker + " "; + } + } + return revokeNick + "撤回了一条成员消息"; + } else { + return "撤回了一条消息"; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimMessageRevokeObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimMessageRevokeObserver.java new file mode 100644 index 0000000..4e2d347 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimMessageRevokeObserver.java @@ -0,0 +1,21 @@ +package com.fengliyan.tianlesue.im.uikit.api.wrapper; + +import com.fengliyan.tianlesue.im.uikit.business.session.helper.MessageHelper; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.model.RevokeMsgNotification; + +/** + * 云信消息撤回观察者 + */ + +public class NimMessageRevokeObserver implements Observer { + + @Override + public void onEvent(RevokeMsgNotification notification) { + if (notification == null || notification.getMessage() == null) { + return; + } + + MessageHelper.getInstance().onRevokeMessage(notification.getMessage(), notification.getRevokeAccount()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimToolBarOptions.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimToolBarOptions.java new file mode 100644 index 0000000..4b4431d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimToolBarOptions.java @@ -0,0 +1,16 @@ +package com.fengliyan.tianlesue.im.uikit.api.wrapper; + +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.netease.nim.uikit.R; + +/** + * Created by hzxuwen on 2016/6/16. + */ +public class NimToolBarOptions extends ToolBarOptions { + + public NimToolBarOptions() { + logoId = R.drawable.nim_actionbar_nest_dark_logo; + navigateId = R.drawable.ic_return; + isNeedNavigate = true; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimUserInfoProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimUserInfoProvider.java new file mode 100644 index 0000000..1f5e5cc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/api/wrapper/NimUserInfoProvider.java @@ -0,0 +1,88 @@ +package com.fengliyan.tianlesue.im.uikit.api.wrapper; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.uinfo.UserInfoProvider; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +/** + * 初始化sdk 需要的用户信息提供者,现主要用于内置通知提醒获取昵称和头像 + *

+ * 注意不要与 IUserInfoProvider 混淆,后者是 UIKit 与 demo 之间的数据共享接口 + *

+ */ + +public class NimUserInfoProvider implements UserInfoProvider { + + private Context context; + + public NimUserInfoProvider(Context context) { + this.context = context; + } + + @Override + public UserInfo getUserInfo(String account) { + return NimUIKit.getUserInfoProvider().getUserInfo(account); + } + + @Override + public Bitmap getAvatarForMessageNotifier(SessionTypeEnum sessionType, String sessionId) { + /* + * 注意:这里最好从缓存里拿,如果加载时间过长会导致通知栏延迟弹出!该函数在后台线程执行! + */ + Bitmap bm = null; + int defResId = R.drawable.nim_avatar_default; + + if (SessionTypeEnum.P2P == sessionType) { + UserInfo user = getUserInfo(sessionId); + bm = (user != null) ? NimUIKit.getImageLoaderKit().getNotificationBitmapFromCache(user.getAvatar()) : null; + } else if (SessionTypeEnum.Team == sessionType) { + Team team = NimUIKit.getTeamProvider().getTeamById(sessionId); + bm = (team != null) ? NimUIKit.getImageLoaderKit().getNotificationBitmapFromCache(team.getIcon()) : null; + defResId = R.drawable.nim_avatar_group; + } + + if (bm == null) { + Drawable drawable = context.getResources().getDrawable(defResId); + if (drawable instanceof BitmapDrawable) { + bm = ((BitmapDrawable) drawable).getBitmap(); + } + } + + return bm; + } + + @Override + public String getDisplayTitleForMessageNotifier(IMMessage message) { + return null; + } + + @Override + public String getDisplayNameForMessageNotifier(String account, String sessionId, SessionTypeEnum sessionType) { + String nick = null; + if (sessionType == SessionTypeEnum.P2P) { + nick = NimUIKit.getContactProvider().getAlias(account); + } else if (sessionType == SessionTypeEnum.Team) { + nick = NimUIKit.getContactProvider().getAlias(account); + if (TextUtils.isEmpty(nick)) { + nick = TeamHelper.getTeamNick(sessionId, account); + } + } + + if (TextUtils.isEmpty(nick)) { + return null; // 返回null,交给sdk处理。如果对方有设置nick,sdk会显示nick + } + + return nick; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitBlock.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitBlock.java new file mode 100644 index 0000000..0a1be1d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitBlock.java @@ -0,0 +1,148 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Created by hzchenkang on 2017/7/7. + * 表示一个@块 + */ + +public class AitBlock { + + /** + * text = "@" + name + */ + public String text; + + /** + * 类型,群成员/机器人 + */ + public int aitType; + + /** + * 在文本中的位置 + */ + public List segments = new ArrayList<>(); + + public AitBlock(String name, int aitType) { + this.text = "@" + name; + this.aitType = aitType; + } + + // 新增 segment + public AitSegment addSegment(int start) { + int end = start + text.length() - 1; + AitSegment segment = new AitSegment(start, end); + segments.add(segment); + return segment; + } + + /** + * @param start 起始光标位置 + * @param changeText 插入文本 + */ + public void moveRight(int start, String changeText) { + if (changeText == null) { + return; + } + int length = changeText.length(); + Iterator iterator = segments.iterator(); + while (iterator.hasNext()) { + AitSegment segment = iterator.next(); + // 从已有的一个@块中插入 + if (start > segment.start && start <= segment.end) { + segment.end += length; + segment.broken = true; + } else if (start <= segment.start) { + segment.start += length; + segment.end += length; + } + } + } + + /** + * @param start 删除前光标位置 + * @param length 删除块的长度 + */ + public void moveLeft(int start, int length) { + int after = start - length; + Iterator iterator = segments.iterator(); + + while (iterator.hasNext()) { + AitSegment segment = iterator.next(); + // 从已有@块中删除 + if (start > segment.start) { + // @被删除掉 + if (after <= segment.start) { + iterator.remove(); + } else if (after <= segment.end) { + segment.broken = true; + segment.end -= length; + } + } else if (start <= segment.start) { + segment.start -= length; + segment.end -= length; + } + } + } + + // 获取该账号所有有效的@块最靠前的start + public int getFirstSegmentStart() { + int start = -1; + for (AitSegment segment : segments) { + if (segment.broken) { + continue; + } + if (start == -1 || segment.start < start) { + start = segment.start; + } + } + return start; + } + + public AitSegment findLastSegmentByEnd(int end) { + int pos = end - 1; + for (AitSegment segment : segments) { + if (!segment.broken && segment.end == pos) { + return segment; + } + } + return null; + } + + public boolean valid() { + if (segments.size() == 0) { + return false; + } + for (AitSegment segment : segments) { + if (!segment.broken) { + return true; + } + } + return false; + } + + public static class AitSegment { + /** + * 位于文本起始位置(include) + */ + public int start; + + /** + * 位于文本结束位置(include) + */ + public int end; + + /** + * 是否坏掉 + */ + public boolean broken = false; + + public AitSegment(int start, int end) { + this.start = start; + this.end = end; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitContactType.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitContactType.java new file mode 100644 index 0000000..4945b5b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitContactType.java @@ -0,0 +1,10 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait; + +/** + * Created by hzchenkang on 2017/6/21. + */ + +public interface AitContactType { + int ROBOT = 1; + int TEAM_MEMBER = 2; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitContactsModel.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitContactsModel.java new file mode 100644 index 0000000..c65ee99 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitContactsModel.java @@ -0,0 +1,114 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Created by hzchenkang on 2017/7/7. + * + * @ 联系人数据 + */ + +public class AitContactsModel { + + // 已@ 的成员 + private Map aitBlocks = new HashMap<>(); + + // 清除所有的@块 + public void reset() { + aitBlocks.clear(); + } + + public void addAitMember(String account, String name, int type, int start) { + AitBlock aitBlock = aitBlocks.get(account); + if (aitBlock == null) { + aitBlock = new AitBlock(name, type); + aitBlocks.put(account, aitBlock); + } + aitBlock.addSegment(start); + } + + // 查所有被@的群成员 + public List getAitTeamMember() { + List teamMembers = new ArrayList<>(); + Iterator iterator = aitBlocks.keySet().iterator(); + while (iterator.hasNext()) { + String account = iterator.next(); + AitBlock block = aitBlocks.get(account); + if (block.aitType == AitContactType.TEAM_MEMBER && block.valid()) { + teamMembers.add(account); + } + } + return teamMembers; + } + + public AitBlock getAitBlock(String account) { + return aitBlocks.get(account); + } + + // 查第一个被@ 的机器人 + public String getFirstAitRobot() { + int start = -1; + String robotAccount = null; + + Iterator iterator = aitBlocks.keySet().iterator(); + while (iterator.hasNext()) { + String account = iterator.next(); + AitBlock block = aitBlocks.get(account); + if (block.valid() && block.aitType == AitContactType.ROBOT) { + int blockStart = block.getFirstSegmentStart(); + if (blockStart == -1) { + continue; + } + if (start == -1 || blockStart < start) { + start = blockStart; + robotAccount = account; + } + } + } + return robotAccount; + } + + // 找到 curPos 恰好命中 end 的segment + public AitBlock.AitSegment findAitSegmentByEndPos(int start) { + Iterator iterator = aitBlocks.keySet().iterator(); + while (iterator.hasNext()) { + String account = iterator.next(); + AitBlock block = aitBlocks.get(account); + AitBlock.AitSegment segment = block.findLastSegmentByEnd(start); + if (segment != null) { + return segment; + } + } + return null; + } + + // 文本插入后更新@块的起止位置 + public void onInsertText(int start, String changeText) { + Iterator iterator = aitBlocks.keySet().iterator(); + while (iterator.hasNext()) { + String account = iterator.next(); + AitBlock block = aitBlocks.get(account); + block.moveRight(start, changeText); + if (!block.valid()) { + iterator.remove(); + } + } + } + + // 文本删除后更新@块的起止位置 + public void onDeleteText(int start, int length) { + Iterator iterator = aitBlocks.keySet().iterator(); + while (iterator.hasNext()) { + String account = iterator.next(); + AitBlock block = aitBlocks.get(account); + block.moveLeft(start, length); + if (!block.valid()) { + iterator.remove(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitManager.java new file mode 100644 index 0000000..3d5e164 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitManager.java @@ -0,0 +1,210 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; + +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.AitContactSelectorActivity; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.List; + +/** + * Created by hzchenkang on 2017/7/10. + */ + +public class AitManager implements TextWatcher { + + private Context context; + + private String tid; + + private boolean robot; + + private AitContactsModel aitContactsModel; + + private int curPos; + + private boolean ignoreTextChange = false; + + private AitTextChangeListener listener; + + public AitManager(Context context, String tid, boolean robot) { + this.context = context; + this.tid = tid; + this.robot = robot; + aitContactsModel = new AitContactsModel(); + } + + public void setTextChangeListener(AitTextChangeListener listener) { + this.listener = listener; + } + + public List getAitTeamMember() { + return aitContactsModel.getAitTeamMember(); + } + + public String getAitRobot() { + return aitContactsModel.getFirstAitRobot(); + } + + public String removeRobotAitString(String text, String robotAccount) { + AitBlock block = aitContactsModel.getAitBlock(robotAccount); + if (block != null) { + return text.replaceAll(block.text, ""); + } else { + return text; + } + } + + public void reset() { + aitContactsModel.reset(); + ignoreTextChange = false; + curPos = 0; + } + + /** + * ------------------------------ 增加@成员 -------------------------------------- + */ + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == AitContactSelectorActivity.REQUEST_CODE && resultCode == Activity.RESULT_OK) { + int type = data.getIntExtra(AitContactSelectorActivity.RESULT_TYPE, -1); + String account = ""; + String name = ""; + if (type == AitContactType.TEAM_MEMBER) { + TeamMember member = (TeamMember) data.getSerializableExtra(AitContactSelectorActivity.RESULT_DATA); + account = member.getAccount(); + name = getAitTeamMemberName(member); + } else if (type == AitContactType.ROBOT) { + NimRobotInfo robotInfo = (NimRobotInfo) data.getSerializableExtra(AitContactSelectorActivity.RESULT_DATA); + account = robotInfo.getAccount(); + name = robotInfo.getName(); + } + insertAitMemberInner(account, name, type, curPos, false); + } + } + + // 群昵称 > 用户昵称 > 账号 + private static String getAitTeamMemberName(TeamMember member) { + if (member == null) { + return ""; + } + String memberNick = member.getTeamNick(); + if (!TextUtils.isEmpty(memberNick)) { + return memberNick; + } + return UserInfoHelper.getUserName(member.getAccount()); + } + + public void insertAitRobot(String account, String name, int start) { + insertAitMemberInner(account, name, AitContactType.ROBOT, start, true); + } + + private void insertAitMemberInner(String account, String name, int type, int start, boolean needInsertAitInText) { + name = name + " "; + String content = needInsertAitInText ? "@" + name : name; + if (listener != null) { + // 关闭监听 + ignoreTextChange = true; + // insert 文本到editText + listener.onTextAdd(content, start, content.length()); + // 开启监听 + ignoreTextChange = false; + } + + // update 已有的 aitBlock + aitContactsModel.onInsertText(start, content); + + int index = needInsertAitInText ? start : start - 1; + // 添加当前到 aitBlock + aitContactsModel.addAitMember(account, name, type, index); + } + + /** + * ------------------------------ editText 监听 -------------------------------------- + */ + + // 当删除尾部空格时,删除一整个segment,包含界面上也删除 + private boolean deleteSegment(int start, int count) { + if (count != 1) { + return false; + } + boolean result = false; + AitBlock.AitSegment segment = aitContactsModel.findAitSegmentByEndPos(start); + if (segment != null) { + int length = start - segment.start; + if (listener != null) { + ignoreTextChange = true; + listener.onTextDelete(segment.start, length); + ignoreTextChange = false; + } + aitContactsModel.onDeleteText(start, length); + result = true; + } + return result; + } + + /** + * @param editable 变化后的Editable + * @param start text 变化区块的起始index + * @param count text 变化区块的大小 + * @param delete 是否是删除 + */ + private void afterTextChanged(Editable editable, int start, int count, boolean delete) { + curPos = delete ? start : count + start; + if (ignoreTextChange) { + return; + } + if (delete) { + int before = start + count; + if (deleteSegment(before, count)) { + return; + } + aitContactsModel.onDeleteText(before, count); + + } else { + if (count <= 0 || editable.length() < start + count) { + return; + } + CharSequence s = editable.subSequence(start, start + count); + if (s == null) { + return; + } + if (s.toString().equals("@")) { + // 启动@联系人界面 + if (!TextUtils.isEmpty(tid) || robot) { + AitContactSelectorActivity.start(context, tid, robot); + } + } + aitContactsModel.onInsertText(start, s.toString()); + } + } + + private int editTextStart; + private int editTextCount; + private int editTextBefore; + private boolean delete; + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + delete = count > after; + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + this.editTextStart = start; + this.editTextCount = count; + this.editTextBefore = before; + } + + @Override + public void afterTextChanged(Editable s) { + afterTextChanged(s, editTextStart, delete ? editTextBefore : editTextCount, delete); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitTextChangeListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitTextChangeListener.java new file mode 100644 index 0000000..a53cc2a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/AitTextChangeListener.java @@ -0,0 +1,12 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait; + +/** + * Created by hzchenkang on 2017/7/10. + */ + +public interface AitTextChangeListener { + + void onTextAdd(String content, int start, int length); + + void onTextDelete(int start, int length); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/AitContactDecoration.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/AitContactDecoration.java new file mode 100644 index 0000000..465292d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/AitContactDecoration.java @@ -0,0 +1,38 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector; + +import android.content.Context; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.decoration.DividerItemDecoration; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Created by hzchenkang on 2017/6/22. + */ + +public class AitContactDecoration extends DividerItemDecoration { + + // 不需要分割线 + private Set ignoreDecorations; + + public AitContactDecoration(Context context, int orientation, List ignoreDecorations) { + super(context, orientation); + if (ignoreDecorations != null) { + this.ignoreDecorations = new HashSet<>(ignoreDecorations); + } + } + + @Override + protected boolean needDrawDecoration(RecyclerView parent, int position) { + if (ignoreDecorations != null) { + int viewType = parent.getAdapter().getItemViewType(position); + if (ignoreDecorations.contains(viewType)) { + return false; + } + } + return true; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/AitContactSelectorActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/AitContactSelectorActivity.java new file mode 100644 index 0000000..6fad098 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/AitContactSelectorActivity.java @@ -0,0 +1,181 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.adapter.AitContactAdapter; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.model.AitContactItem; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.model.ItemType; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener.OnItemClickListener; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by hzchenkang on 2017/6/21. + */ + +public class AitContactSelectorActivity extends UI { + private static final String EXTRA_ID = "EXTRA_ID"; + private static final String EXTRA_ROBOT = "EXTRA_ROBOT"; + + public static final int REQUEST_CODE = 0x10; + public static final String RESULT_TYPE = "type"; + public static final String RESULT_DATA = "data"; + + private AitContactAdapter adapter; + + private String teamId; + + private boolean addRobot; + + private List items; + + public static void start(Context context, String tid, boolean addRobot) { + Intent intent = new Intent(); + if (tid != null) { + intent.putExtra(EXTRA_ID, tid); + } + if (addRobot) { + intent.putExtra(EXTRA_ROBOT, true); + } + intent.setClass(context, AitContactSelectorActivity.class); + + ((Activity) context).startActivityForResult(intent, REQUEST_CODE); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_team_member_list_layout); + parseIntent(); + initViews(); + initData(); + } + + private void initViews() { + RecyclerView recyclerView = findViewById(R.id.member_list); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + initAdapter(recyclerView); + ToolBarOptions options = new NimToolBarOptions(); + options.titleString = "选择提醒的人"; + setToolBar(R.id.toolbar, options); + } + + private void initAdapter(RecyclerView recyclerView) { + items = new ArrayList<>(); + adapter = new AitContactAdapter(recyclerView, items); + recyclerView.setAdapter(adapter); + + List noDividerViewTypes = new ArrayList<>(1); + noDividerViewTypes.add(ItemType.SIMPLE_LABEL); + recyclerView.addItemDecoration(new AitContactDecoration(this, LinearLayoutManager.VERTICAL, noDividerViewTypes)); + + recyclerView.addOnItemTouchListener(new OnItemClickListener() { + + @Override + public void onItemClick(AitContactAdapter adapter, View view, int position) { + AitContactItem item = adapter.getItem(position); + Intent intent = new Intent(); + intent.putExtra(RESULT_TYPE, item.getViewType()); + if (item.getViewType() == ItemType.TEAM_MEMBER) { + intent.putExtra(RESULT_DATA, (TeamMember) item.getModel()); + } else if (item.getViewType() == ItemType.ROBOT) { + intent.putExtra(RESULT_DATA, (NimRobotInfo) item.getModel()); + } + setResult(RESULT_OK, intent); + finish(); + } + }); + } + + private void parseIntent() { + Intent intent = getIntent(); + teamId = intent.getStringExtra(EXTRA_ID); + addRobot = intent.getBooleanExtra(EXTRA_ROBOT, false); + } + + private void initData() { + items = new ArrayList(); + if (addRobot) { + initRobot(); + } + if (teamId != null) { + initTeamMemberAsync(); + } else { + //data 加载结束,通知更新 + adapter.setNewData(items); + } + } + + private void initRobot() { + List robots = NimUIKit.getRobotInfoProvider().getAllRobotAccounts(); + if (robots != null && !robots.isEmpty()) { + items.add(0, new AitContactItem(ItemType.SIMPLE_LABEL, "机器人")); + for (NimRobotInfo robot : robots) { + items.add(new AitContactItem(ItemType.ROBOT, robot)); + } + } + } + + private void initTeamMemberAsync() { + Team t = NimUIKit.getTeamProvider().getTeamById(teamId); + if (t != null) { + updateTeamMember(t); + } else { + NimUIKit.getTeamProvider().fetchTeamById(teamId, new SimpleCallback() { + @Override + public void onResult(boolean success, Team result, int code) { + if (success && result != null) { + // 继续加载群成员 + updateTeamMember(result); + } else { + //data 加载结束,通知更新 + adapter.setNewData(items); + } + } + }); + } + } + + private void updateTeamMember(Team team) { + NimUIKit.getTeamProvider().fetchTeamMemberList(teamId, new SimpleCallback>() { + @Override + public void onResult(boolean success, List members, int code) { + if (success && members != null && !members.isEmpty()) { + // filter self + for (TeamMember member : members) { + if (member.getAccount().equals(NimUIKit.getAccount())) { + members.remove(member); + break; + } + } + + if (!members.isEmpty()) { + items.add(new AitContactItem(ItemType.SIMPLE_LABEL, "群成员")); + for (TeamMember member : members) { + items.add(new AitContactItem(ItemType.TEAM_MEMBER, member)); + } + } + } + //data 加载结束,通知更新 + adapter.setNewData(items); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/adapter/AitContactAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/adapter/AitContactAdapter.java new file mode 100644 index 0000000..8bb57c0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/adapter/AitContactAdapter.java @@ -0,0 +1,38 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector.adapter; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.holder.RobotViewHolder; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.holder.SimpleLabelViewHolder; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.holder.TeamMemberViewHolder; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.model.AitContactItem; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.model.ItemType; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; + +import java.util.List; + +/** + * Created by hzchenkang on 2017/6/21. + */ + +public class AitContactAdapter extends BaseMultiItemQuickAdapter { + + public AitContactAdapter(RecyclerView recyclerView, List data) { + super(recyclerView, data); + addItemType(ItemType.SIMPLE_LABEL, R.layout.nim_ait_contact_label_item, SimpleLabelViewHolder.class); + addItemType(ItemType.ROBOT, R.layout.nim_ait_contact_robot_item, RobotViewHolder.class); + addItemType(ItemType.TEAM_MEMBER, R.layout.nim_ait_contact_team_member_item, TeamMemberViewHolder.class); + } + + @Override + protected int getViewType(AitContactItem item) { + return item.getViewType(); + } + + @Override + protected String getItemKey(AitContactItem item) { + return "" + item.getViewType() + item.hashCode(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/RobotViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/RobotViewHolder.java new file mode 100644 index 0000000..076129c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/RobotViewHolder.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector.holder; + +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.model.AitContactItem; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; + +/** + * Created by hzchenkang on 2017/6/21. + */ + +public class RobotViewHolder extends RecyclerViewHolder> { + + private HeadImageView headImageView; + private TextView nameTextView; + + public RobotViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + @Override + public void convert(BaseViewHolder holder, AitContactItem data, int position, boolean isScrolling) { + inflate(holder); + refresh(data.getModel()); + } + + public void inflate(BaseViewHolder holder) { + headImageView = holder.getView(R.id.imageViewHeader); + nameTextView = holder.getView(R.id.textViewName); + } + + public void refresh(NimRobotInfo robot) { + headImageView.resetImageView(); + nameTextView.setText(robot.getName()); + headImageView.loadAvatar(robot.getAvatar()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/SimpleLabelViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/SimpleLabelViewHolder.java new file mode 100644 index 0000000..9397f06 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/SimpleLabelViewHolder.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector.holder; + +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.model.AitContactItem; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; +import com.netease.nim.uikit.R; + +/** + * Created by hzchenkang on 2017/6/21. + */ + +public class SimpleLabelViewHolder extends RecyclerViewHolder> { + + private TextView textView; + + public SimpleLabelViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + @Override + public void convert(BaseViewHolder holder, AitContactItem data, int position, boolean isScrolling) { + inflate(holder); + refresh(data.getModel()); + } + + public void inflate(BaseViewHolder holder) { + textView = holder.getView(R.id.tv_label); + } + + public void refresh(String label) { + textView.setText(label); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/TeamMemberViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/TeamMemberViewHolder.java new file mode 100644 index 0000000..27e6ece --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/holder/TeamMemberViewHolder.java @@ -0,0 +1,44 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector.holder; + +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.ait.selector.model.AitContactItem; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; +import com.netease.nimlib.sdk.team.model.TeamMember; + +/** + * Created by hzchenkang on 2017/6/21. + */ + +public class TeamMemberViewHolder extends RecyclerViewHolder> { + + private HeadImageView headImageView; + + private TextView nameTextView; + + public TeamMemberViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + @Override + public void convert(BaseViewHolder holder, AitContactItem data, int position, boolean isScrolling) { + inflate(holder); + refresh(data.getModel()); + } + + public void inflate(BaseViewHolder holder) { + headImageView = holder.getView(R.id.imageViewHeader); + nameTextView = holder.getView(R.id.textViewName); + } + + public void refresh(TeamMember member) { + headImageView.resetImageView(); + nameTextView.setText(TeamHelper.getTeamMemberDisplayName(member.getTid(), member.getAccount())); + headImageView.loadBuddyAvatar(member.getAccount()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/model/AitContactItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/model/AitContactItem.java new file mode 100644 index 0000000..89e271f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/model/AitContactItem.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector.model; + +/** + * Created by hzchenkang on 2017/6/21. + */ + +public class AitContactItem { + + // view type + private int viewType; + + // data + private T model; + + public AitContactItem(int viewType, T model) { + this.viewType = viewType; + this.model = model; + } + + public T getModel() { + return model; + } + + public int getViewType() { + return viewType; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/model/ItemType.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/model/ItemType.java new file mode 100644 index 0000000..ea0fb25 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/ait/selector/model/ItemType.java @@ -0,0 +1,11 @@ +package com.fengliyan.tianlesue.im.uikit.business.ait.selector.model; + +import com.fengliyan.tianlesue.im.uikit.business.ait.AitContactType; + +/** + * Created by hzchenkang on 2017/7/13. + */ + +public interface ItemType extends AitContactType { + int SIMPLE_LABEL = 0; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/adapter/ChatRoomMsgAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/adapter/ChatRoomMsgAdapter.java new file mode 100644 index 0000000..28becf6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/adapter/ChatRoomMsgAdapter.java @@ -0,0 +1,246 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.adapter; + +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder.ChatRoomMsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder.ChatRoomMsgViewHolderFactory; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by huangjun on 2016/12/21. + */ +public class ChatRoomMsgAdapter extends BaseMultiItemFetchLoadAdapter { + + private Map, Integer> holder2ViewType; + + private ViewHolderEventListener eventListener; + private Map progresses; // 有文件传输,需要显示进度条的消息ID map + private String messageId; + private Container container; + + public ChatRoomMsgAdapter(RecyclerView recyclerView, List data, Container container) { + super(recyclerView, data); + + timedItems = new HashSet<>(); + progresses = new HashMap<>(); + + // view type, view holder + holder2ViewType = new HashMap<>(); + List> holders = ChatRoomMsgViewHolderFactory.getAllViewHolders(); + int viewType = 0; + for (Class holder : holders) { + viewType++; + addItemType(viewType, R.layout.nim_message_item, holder); + holder2ViewType.put(holder, viewType); + } + + this.container = container; + } + + @Override + protected int getViewType(ChatRoomMessage message) { + return holder2ViewType.get(ChatRoomMsgViewHolderFactory.getViewHolderByType(message)); + } + + @Override + protected String getItemKey(ChatRoomMessage item) { + return item.getUuid(); + } + + public void setEventListener(ViewHolderEventListener eventListener) { + this.eventListener = eventListener; + } + + public ViewHolderEventListener getEventListener() { + return eventListener; + } + + public void deleteItem(IMMessage message, boolean isRelocateTime) { + if (message == null) { + return; + } + + int index = 0; + for (IMMessage item : getData()) { + if (item.isTheSame(message)) { + break; + } + ++index; + } + + if (index < getDataSize()) { + remove(index); + if (isRelocateTime) { + relocateShowTimeItemAfterDelete(message, index); + } + notifyDataSetChanged(); // 可以不要!!! + } + } + + public float getProgress(IMMessage message) { + Float progress = progresses.get(message.getUuid()); + return progress == null ? 0 : progress; + } + + public void putProgress(IMMessage message, float progress) { + progresses.put(message.getUuid(), progress); + } + + /** + * *********************** 时间显示处理 *********************** + */ + + private Set timedItems; // 需要显示消息时间的消息ID + private IMMessage lastShowTimeItem; // 用于消息时间显示,判断和上条消息间的时间间隔 + + public boolean needShowTime(IMMessage message) { + return timedItems.contains(message.getUuid()); + } + + /** + * 列表加入新消息时,更新时间显示 + */ + public void updateShowTimeItem(List items, boolean fromStart, boolean update) { + IMMessage anchor = fromStart ? null : lastShowTimeItem; + for (IMMessage message : items) { + if (setShowTimeFlag(message, anchor)) { + anchor = message; + } + } + + if (update) { + lastShowTimeItem = anchor; + } + } + + /** + * 是否显示时间item + */ + private boolean setShowTimeFlag(IMMessage message, IMMessage anchor) { + boolean update = false; + + if (hideTimeAlways(message)) { + setShowTime(message, false); + } else { + if (anchor == null) { + setShowTime(message, true); + update = true; + } else { + long time = anchor.getTime(); + long now = message.getTime(); + + if (now - time == 0) { + // 消息撤回时使用 + setShowTime(message, true); + lastShowTimeItem = message; + update = true; + } else if (now - time < (long) (5 * 60 * 1000)) { + setShowTime(message, false); + } else { + setShowTime(message, true); + update = true; + } + } + } + + return update; + } + + private void setShowTime(IMMessage message, boolean show) { + if (show) { + timedItems.add(message.getUuid()); + } else { + timedItems.remove(message.getUuid()); + } + } + + private void relocateShowTimeItemAfterDelete(IMMessage messageItem, int index) { + // 如果被删的项显示了时间,需要继承 + if (needShowTime(messageItem)) { + setShowTime(messageItem, false); + if (getDataSize() > 0) { + IMMessage nextItem; + if (index == getDataSize()) { + //删除的是最后一项 + nextItem = getItem(index - 1); + } else { + //删除的不是最后一项 + nextItem = getItem(index); + } + + // 增加其他不需要显示时间的消息类型判断 + if (hideTimeAlways(nextItem)) { + setShowTime(nextItem, false); + if (lastShowTimeItem != null && lastShowTimeItem != null + && lastShowTimeItem.isTheSame(messageItem)) { + lastShowTimeItem = null; + for (int i = getDataSize() - 1; i >= 0; i--) { + IMMessage item = getItem(i); + if (needShowTime(item)) { + lastShowTimeItem = item; + break; + } + } + } + } else { + setShowTime(nextItem, true); + if (lastShowTimeItem == null + || (lastShowTimeItem != null && lastShowTimeItem.isTheSame(messageItem))) { + lastShowTimeItem = nextItem; + } + } + } else { + lastShowTimeItem = null; + } + } + } + + private boolean hideTimeAlways(IMMessage message) { + if (message.getSessionType() == SessionTypeEnum.ChatRoom) { + return true; + } + switch (message.getMsgType()) { + case notification: + return true; + default: + return false; + } + } + + public interface ViewHolderEventListener { + // 长按事件响应处理 + boolean onViewHolderLongClick(View clickView, View viewHolderView, IMMessage item); + + // 发送失败或者多媒体文件下载失败指示按钮点击响应处理 + void onFailedBtnClick(IMMessage resendMessage); + + // viewholder footer按钮点击,如机器人继续会话 + void onFooterClick(ChatRoomMsgViewHolderBase holderBase, IMMessage message); + } + + public void setUuid(String messageId) { + this.messageId = messageId; + } + + public String getUuid() { + return messageId; + } + + public Container getContainer() { + return container; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/fragment/ChatRoomMessageFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/fragment/ChatRoomMessageFragment.java new file mode 100644 index 0000000..28ec31d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/fragment/ChatRoomMessageFragment.java @@ -0,0 +1,265 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.fragment; + +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomSessionCustomization; +import com.fengliyan.tianlesue.im.uikit.business.ait.AitManager; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.helper.ChatRoomHelper; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.module.ChatRoomInputPanel; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.module.ChatRoomMsgListPanel; +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.business.session.module.ModuleProxy; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.fragment.TFragment; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.ChatRoomService; +import com.netease.nimlib.sdk.chatroom.ChatRoomServiceObserver; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.robot.model.RobotMsgType; + +import java.util.ArrayList; +import java.util.List; + +/** + * 聊天室直播互动fragment + * 可以直接集成到应用中 + */ +public class ChatRoomMessageFragment extends TFragment implements ModuleProxy { + private String roomId; + protected View rootView; + private static ChatRoomSessionCustomization sCustomization; + + // modules + protected ChatRoomInputPanel inputPanel; + protected ChatRoomMsgListPanel messageListPanel; + protected AitManager aitManager; + + public static void setChatRoomSessionCustomization(ChatRoomSessionCustomization roomSessionCustomization) { + sCustomization = roomSessionCustomization; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + rootView = inflater.inflate(R.layout.nim_chat_room_message_fragment, container, false); + return rootView; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void onPause() { + super.onPause(); + if (inputPanel != null) { + inputPanel.onPause(); + } + if (messageListPanel != null) { + messageListPanel.onPause(); + } + } + + @Override + public void onResume() { + super.onResume(); + if (messageListPanel != null) { + messageListPanel.onResume(); + } + } + + public boolean onBackPressed() { + if (inputPanel != null && inputPanel.collapse(true)) { + return true; + } + + if (messageListPanel != null && messageListPanel.onBackPressed()) { + return true; + } + return false; + } + + @Override + public void onDestroy() { + super.onDestroy(); + registerObservers(false); + + if (messageListPanel != null) { + messageListPanel.onDestroy(); + } + if (aitManager != null) { + aitManager.reset(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (aitManager != null) { + aitManager.onActivityResult(requestCode, resultCode, data); + } + + inputPanel.onActivityResult(requestCode, resultCode, data); + } + + public void onLeave() { + if (inputPanel != null) { + inputPanel.collapse(false); + } + } + + public void init(String roomId) { + this.roomId = roomId; + registerObservers(true); + findViews(); + } + + private void findViews() { + Container container = new Container(getActivity(), roomId, SessionTypeEnum.ChatRoom, this); + if (messageListPanel == null) { + messageListPanel = new ChatRoomMsgListPanel(container, rootView); + } else { + messageListPanel.reload(container); + } + + if (inputPanel == null) { + inputPanel = new ChatRoomInputPanel(container, rootView, getActionList(), false); + } else { + inputPanel.reload(container, null); + } + + if (NimUIKitImpl.getOptions().aitEnable && NimUIKitImpl.getOptions().aitChatRoomRobot) { + if (aitManager == null) { + aitManager = new AitManager(getContext(), null, true); + } + inputPanel.addAitTextWatcher(aitManager); + aitManager.setTextChangeListener(inputPanel); + } + } + + private void registerObservers(boolean register) { + NIMClient.getService(ChatRoomServiceObserver.class).observeReceiveMessage(incomingChatRoomMsg, register); + } + + Observer> incomingChatRoomMsg = new Observer>() { + @Override + public void onEvent(List messages) { + if (messages == null || messages.isEmpty()) { + return; + } + + messageListPanel.onIncomingMessage(messages); + } + }; + + /************************** Module proxy ***************************/ + + @Override + public boolean sendMessage(IMMessage msg) { + ChatRoomMessage message = (ChatRoomMessage) msg; + + // 检查是否转换成机器人消息 + message = changeToRobotMsg(message); + + ChatRoomHelper.buildMemberTypeInRemoteExt(message, roomId); + + NIMClient.getService(ChatRoomService.class).sendMessage(message, false) + .setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + } + + @Override + public void onFailed(int code) { + if (code == ResponseCode.RES_CHATROOM_MUTED) { + ToastHelper.showToast(NimUIKit.getContext(), "用户被禁言"); + } else if (code == ResponseCode.RES_CHATROOM_ROOM_MUTED) { + ToastHelper.showToast(NimUIKit.getContext(), "全体禁言"); + } else { + ToastHelper.showToast(NimUIKit.getContext(), "消息发送失败:code:" + code); + } + } + + @Override + public void onException(Throwable exception) { + ToastHelper.showToast(NimUIKit.getContext(), "消息发送失败!"); + } + }); + messageListPanel.onMsgSend(message); + if (aitManager != null) { + aitManager.reset(); + } + return true; + } + + private ChatRoomMessage changeToRobotMsg(ChatRoomMessage message) { + if (aitManager == null) { + return message; + } + if (message.getMsgType() == MsgTypeEnum.robot) { + return message; + } + String robotAccount = aitManager.getAitRobot(); + if (TextUtils.isEmpty(robotAccount)) { + return message; + } + String text = message.getContent(); + String content = aitManager.removeRobotAitString(text, robotAccount); + content = content.equals("") ? " " : content; + message = ChatRoomMessageBuilder.createRobotMessage(roomId, robotAccount, text, RobotMsgType.TEXT, content, null, null); + + return message; + } + + @Override + public void onInputPanelExpand() { + messageListPanel.scrollToBottom(); + } + + @Override + public void shouldCollapseInputPanel() { + inputPanel.collapse(false); + } + + @Override + public void onItemFooterClick(IMMessage message) { + if (aitManager != null) { + RobotAttachment attachment = (RobotAttachment) message.getAttachment(); + NimRobotInfo robot = NimUIKit.getRobotInfoProvider().getRobotByAccount(attachment.getFromRobotAccount()); + aitManager.insertAitRobot(robot.getAccount(), robot.getName(), inputPanel.getEditSelectionStart()); + } + } + + @Override + public boolean isLongClickEnabled() { + return !inputPanel.isRecording(); + } + + // 操作面板集合 + private List getActionList() { + List actions = new ArrayList<>(); + if (sCustomization != null) { + actions.addAll(sCustomization.actions); + } + + return actions; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/helper/ChatRoomHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/helper/ChatRoomHelper.java new file mode 100644 index 0000000..7bece5c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/helper/ChatRoomHelper.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.helper; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.netease.nimlib.sdk.chatroom.constant.MemberType; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by huangjun on 2017/9/18. + */ +public class ChatRoomHelper { + public static void buildMemberTypeInRemoteExt(ChatRoomMessage message, String roomId) { + Map ext = new HashMap<>(); + ChatRoomMember chatRoomMember = NimUIKit.getChatRoomProvider().getChatRoomMember(roomId, NimUIKit.getAccount()); + if (chatRoomMember != null && chatRoomMember.getMemberType() != null) { + ext.put("type", chatRoomMember.getMemberType().getValue()); + message.setRemoteExtension(ext); + } + } + + public static MemberType getMemberTypeByRemoteExt(ChatRoomMessage message) { + final String KEY = "type"; + Map ext = message.getRemoteExtension(); + + if (ext == null || !ext.containsKey(KEY)) { + return MemberType.UNKNOWN; + } + + return MemberType.typeOfValue((Integer) ext.get(KEY)); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/helper/ChatRoomNotificationHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/helper/ChatRoomNotificationHelper.java new file mode 100644 index 0000000..fe1fab5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/helper/ChatRoomNotificationHelper.java @@ -0,0 +1,129 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.helper; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomNotificationAttachment; + +import java.util.List; + +/** + * Created by huangjun on 2016/1/13. + */ +public class ChatRoomNotificationHelper { + public static String getNotificationText(ChatRoomNotificationAttachment attachment) { + if (attachment == null) { + return ""; + } + + String targets = getTargetNicks(attachment); + String text; + switch (attachment.getType()) { + case ChatRoomMemberIn: + text = buildText("欢迎", targets, "进入直播间"); + break; + case ChatRoomMemberExit: + text = buildText(targets, "离开了直播间"); + break; + case ChatRoomMemberBlackAdd: + text = buildText(targets, "被管理员拉入黑名单"); + break; + case ChatRoomMemberBlackRemove: + text = buildText(targets, "被管理员解除拉黑"); + break; + case ChatRoomMemberMuteAdd: + text = buildText(targets, "被管理员禁言"); + break; + case ChatRoomMemberMuteRemove: + text = buildText(targets, "被管理员解除禁言"); + break; + case ChatRoomManagerAdd: + text = buildText(targets, "被任命管理员身份"); + break; + case ChatRoomManagerRemove: + text = buildText(targets, "被解除管理员身份"); + break; + case ChatRoomCommonAdd: + text = buildText(targets, "被设为普通成员"); + break; + case ChatRoomCommonRemove: + text = buildText(targets, "被取消普通成员"); + break; + case ChatRoomClose: + text = buildText("直播间被关闭"); + break; + case ChatRoomInfoUpdated: + text = buildText("直播间信息已更新"); + break; + case ChatRoomMemberKicked: + text = buildText(targets, "被踢出直播间"); + break; + case ChatRoomMemberTempMuteAdd: + text = buildText(targets, "被临时禁言"); + break; + case ChatRoomMemberTempMuteRemove: + text = buildText(targets, "被解除临时禁言"); + break; + case ChatRoomMyRoomRoleUpdated: + text = buildText(targets, "更新了自己的角色信息"); + break; + case ChatRoomQueueChange: + text = buildText(targets, "麦序队列中有变更"); + break; + case ChatRoomRoomMuted: + text = buildText("全体禁言,管理员可发言"); + break; + case ChatRoomRoomDeMuted: + text = buildText("解除全体禁言"); + break; + case ChatRoomQueueBatchChange: + text = buildText("批量变更"); + break; + default: + text = attachment.toString(); + break; + } + + return text; + } + + private static String getTargetNicks(final ChatRoomNotificationAttachment attachment) { + StringBuilder sb = new StringBuilder(); + List accounts = attachment.getTargets(); + List targets = attachment.getTargetNicks(); + if (attachment.getTargetNicks() != null) { + for (int i = 0; i < targets.size(); i++) { + sb.append(NimUIKit.getAccount().equals(accounts.get(i)) ? "你" : targets.get(i)); + sb.append(","); + } + sb.deleteCharAt(sb.length() - 1); + } + + return sb.toString(); + } + + private static String buildText(String pre, String targets, String operate) { + StringBuilder sb = new StringBuilder(); + if (!TextUtils.isEmpty(pre)) { + sb.append(pre); + } + + if (!TextUtils.isEmpty(targets)) { + sb.append(targets); + } + + if (!TextUtils.isEmpty(operate)) { + sb.append(operate); + } + + return sb.toString(); + } + + private static String buildText(String targets, String operate) { + return buildText(null, targets, operate); + } + + private static String buildText(String operate) { + return buildText(null, operate); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/module/ChatRoomInputPanel.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/module/ChatRoomInputPanel.java new file mode 100644 index 0000000..4d73607 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/module/ChatRoomInputPanel.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.module; + +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.business.session.module.input.InputPanel; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.List; + +/** + * Created by huangjun on 2017/9/18. + */ +public class ChatRoomInputPanel extends InputPanel { + + public ChatRoomInputPanel(Container container, View view, List actions, boolean isTextAudioSwitchShow) { + super(container, view, actions, isTextAudioSwitchShow, false, false, null); + } + + @Override + protected IMMessage createTextMessage(String text) { + return ChatRoomMessageBuilder.createChatRoomTextMessage(container.account, text); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/module/ChatRoomMsgListPanel.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/module/ChatRoomMsgListPanel.java new file mode 100644 index 0000000..1ba15a1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/module/ChatRoomMsgListPanel.java @@ -0,0 +1,491 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.module; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.text.TextUtils; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.adapter.ChatRoomMsgAdapter; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder.ChatRoomMsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.business.preference.UserPreferences; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.LinkElement; +import com.fengliyan.tianlesue.im.uikit.business.session.audio.MessageAudioControl; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot.RobotLinkView; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialogHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.IRecyclerView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener.OnItemClickListener; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore.MsgListFetchLoadMoreView; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.ChatRoomService; +import com.netease.nimlib.sdk.chatroom.ChatRoomServiceObserver; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.AttachmentProgress; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.robot.model.RobotMsgType; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * 聊天室消息收发模块 + * Created by huangjun on 2016/1/27. + */ +public class ChatRoomMsgListPanel { + private static final int MESSAGE_CAPACITY = 500; + + // container + private Container container; + private View rootView; + private Handler uiHandler; + + // message list view + private RecyclerView messageListView; + private LinkedList items; + private ChatRoomMsgAdapter adapter; + + public ChatRoomMsgListPanel(Container container, View rootView) { + this.container = container; + this.rootView = rootView; + + init(); + } + + public void onResume() { + setEarPhoneMode(UserPreferences.isEarPhoneModeEnable(), false); + } + + public void onPause() { + MessageAudioControl.getInstance(container.activity).stopAudio(); + } + + public void onDestroy() { + registerObservers(false); + } + + public boolean onBackPressed() { + uiHandler.removeCallbacks(null); + MessageAudioControl.getInstance(container.activity).stopAudio(); // 界面返回,停止语音播放 + return false; + } + + public void reload(Container container) { + this.container = container; + if (adapter != null) { + adapter.clearData(); + } + } + + private void init() { + initListView(); + this.uiHandler = new Handler(NimUIKit.getContext().getMainLooper()); + registerObservers(true); + } + + private void initListView() { + // RecyclerView + messageListView = (RecyclerView) rootView.findViewById(R.id.messageListView); + messageListView.setLayoutManager(new LinearLayoutManager(container.activity)); + messageListView.requestDisallowInterceptTouchEvent(true); + messageListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState != RecyclerView.SCROLL_STATE_IDLE) { + container.proxy.shouldCollapseInputPanel(); + } + } + }); + messageListView.setOverScrollMode(View.OVER_SCROLL_NEVER); + + // adapter + items = new LinkedList<>(); + adapter = new ChatRoomMsgAdapter(messageListView, items, container); + adapter.closeLoadAnimation(); + adapter.setFetchMoreView(new MsgListFetchLoadMoreView()); + adapter.setLoadMoreView(new MsgListFetchLoadMoreView()); + adapter.setEventListener(new MsgItemEventListener()); + adapter.setOnFetchMoreListener(new MessageLoader()); // load from start + messageListView.setAdapter(adapter); + + messageListView.addOnItemTouchListener(listener); + } + + public void onIncomingMessage(List messages) { + boolean needScrollToBottom = isLastMessageVisible(); + boolean needRefresh = false; + List addedListItems = new ArrayList<>(messages.size()); + for (ChatRoomMessage message : messages) { + // 保证显示到界面上的消息,来自同一个聊天室 + if (isMyMessage(message)) { + saveMessage(message); + addedListItems.add(message); + needRefresh = true; + } + } + if (needRefresh) { + adapter.notifyDataSetChanged(); + } + + // incoming messages tip + ChatRoomMessage lastMsg = messages.get(messages.size() - 1); + if (isMyMessage(lastMsg) && needScrollToBottom) { + doScrollToBottom(); + } + } + + private boolean isLastMessageVisible() { + LinearLayoutManager layoutManager = (LinearLayoutManager) messageListView.getLayoutManager(); + int lastVisiblePosition = layoutManager.findLastCompletelyVisibleItemPosition(); + return lastVisiblePosition >= adapter.getBottomDataPosition(); + } + + + // 发送消息后,更新本地消息列表 + public void onMsgSend(ChatRoomMessage message) { + saveMessage(message); + + adapter.notifyDataSetChanged(); + doScrollToBottom(); + } + + public void saveMessage(final ChatRoomMessage message) { + if (message == null) { + return; + } + + if (items.size() >= MESSAGE_CAPACITY) { + items.poll(); + } + + items.add(message); + } + + /** + * *************** MessageLoader *************** + */ + private class MessageLoader implements BaseFetchLoadAdapter.RequestLoadMoreListener, BaseFetchLoadAdapter.RequestFetchMoreListener { + + private static final int LOAD_MESSAGE_COUNT = 10; + + private IMMessage anchor; + + private boolean firstLoad = true; + + private boolean fetching = false; + + public MessageLoader() { + anchor = null; + loadFromLocal(); + } + + private RequestCallback> callback = new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List messages, Throwable exception) { + if (code == ResponseCode.RES_SUCCESS && messages != null) { + onMessageLoaded(messages); + } + + fetching = false; + } + }; + + private void loadFromLocal() { + if (fetching) { + return; + } + + fetching = true; + NIMClient.getService(ChatRoomService.class).pullMessageHistoryEx(container.account, anchor().getTime(), LOAD_MESSAGE_COUNT, QueryDirectionEnum.QUERY_OLD) + .setCallback(callback); + } + + private IMMessage anchor() { + if (items.size() == 0) { + return (anchor == null ? ChatRoomMessageBuilder.createEmptyChatRoomMessage(container.account, 0) : anchor); + } else { + return items.get(0); + } + } + + /** + * 历史消息加载处理 + */ + private void onMessageLoaded(List messages) { + int count = messages.size(); + + // 逆序 + Collections.reverse(messages); + // 加入到列表中 + if (count < LOAD_MESSAGE_COUNT) { + adapter.fetchMoreEnd(messages, true); + } else { + adapter.fetchMoreComplete(messages); + } + + // 如果是第一次加载,updateShowTimeItem返回的就是lastShowTimeItem + if (firstLoad) { + doScrollToBottom(); + } + + firstLoad = false; + } + + @Override + public void onFetchMoreRequested() { + loadFromLocal(); + } + + @Override + public void onLoadMoreRequested() { + + } + } + + /** + * ************************* 观察者 ******************************** + */ + + private void registerObservers(boolean register) { + ChatRoomServiceObserver service = NIMClient.getService(ChatRoomServiceObserver.class); + service.observeMsgStatus(messageStatusObserver, register); + service.observeAttachmentProgress(attachmentProgressObserver, register); + } + + /** + * 消息状态变化观察者 + */ + private Observer messageStatusObserver = new Observer() { + @Override + public void onEvent(ChatRoomMessage message) { + if (isMyMessage(message)) { + onMessageStatusChange(message); + } + } + }; + + /** + * 消息附件上传/下载进度观察者 + */ + private Observer attachmentProgressObserver = new Observer() { + @Override + public void onEvent(AttachmentProgress progress) { + onAttachmentProgressChange(progress); + } + }; + + private void onMessageStatusChange(IMMessage message) { + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + item.setStatus(message.getStatus()); + item.setAttachStatus(message.getAttachStatus()); + // 处理语音、音视频通话 + if (item.getMsgType() == MsgTypeEnum.audio || item.getMsgType() == MsgTypeEnum.avchat) { + item.setAttachment(message.getAttachment()); // 附件可能更新了 + } + + refreshViewHolderByIndex(index); + } + } + + private void onAttachmentProgressChange(AttachmentProgress progress) { + int index = getItemIndex(progress.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + float value = (float) progress.getTransferred() / (float) progress.getTotal(); + adapter.putProgress(item, value); + refreshViewHolderByIndex(index); + } + } + + public boolean isMyMessage(ChatRoomMessage message) { + return message.getSessionType() == container.sessionType + && message.getSessionId() != null + && message.getSessionId().equals(container.account); + } + + /** + * 刷新单条消息 + */ + private void refreshViewHolderByIndex(final int index) { + container.activity.runOnUiThread(new Runnable() { + + @Override + public void run() { + if (index < 0) { + return; + } + + adapter.notifyDataItemChanged(index); + } + }); + } + + private int getItemIndex(String uuid) { + for (int i = 0; i < items.size(); i++) { + IMMessage message = items.get(i); + if (TextUtils.equals(message.getUuid(), uuid)) { + return i; + } + } + + return -1; + } + + private OnItemClickListener listener = new OnItemClickListener() { + @Override + public void onItemClick(IRecyclerView adapter, View view, int position) { + + } + + @Override + public void onItemLongClick(IRecyclerView adapter, View view, int position) { + } + + @Override + public void onItemChildClick(IRecyclerView adapter2, View view, int position) { + if (view != null && view instanceof RobotLinkView) { + RobotLinkView robotLinkView = (RobotLinkView) view; + LinkElement element = robotLinkView.getElement(); + if (element != null) { + element.getTarget(); + if (LinkElement.TYPE_URL.equals(element.getType())) { + Intent intent = new Intent(); + intent.setAction("android.intent.action.VIEW"); + Uri content_url = Uri.parse(element.getTarget()); + intent.setData(content_url); + try { + container.activity.startActivity(intent); + } catch (ActivityNotFoundException e) { + ToastHelper.showToast(container.activity, "路径错误"); + } + + } else if (LinkElement.TYPE_BLOCK.equals(element.getType())) { + // 发送点击的block + ChatRoomMessage message = adapter.getItem(position); + if (message != null) { + String robotAccount = ((RobotAttachment) message.getAttachment()).getFromRobotAccount(); + ChatRoomMessage robotMsg = ChatRoomMessageBuilder.createRobotMessage(container.account, robotAccount, + robotLinkView.getShowContent(), RobotMsgType.LINK, "", element.getTarget(), element.getParams()); + container.proxy.sendMessage(robotMsg); + } + } + } + } + } + }; + + private class MsgItemEventListener implements ChatRoomMsgAdapter.ViewHolderEventListener { + + @Override + public void onFailedBtnClick(IMMessage message) { + if (message.getDirect() == MsgDirectionEnum.Out) { + // 发出的消息,如果是发送失败,直接重发,否则有可能是漫游到的多媒体消息,但文件下载 + if (message.getStatus() == MsgStatusEnum.fail) { + resendMessage(message); // 重发 + } else { + if (message.getAttachment() instanceof FileAttachment) { + FileAttachment attachment = (FileAttachment) message.getAttachment(); + if (TextUtils.isEmpty(attachment.getPath()) + && TextUtils.isEmpty(attachment.getThumbPath())) { + showReDownloadConfirmDlg(message); + } + } else { + resendMessage(message); + } + } + } else { + showReDownloadConfirmDlg(message); + } + } + + @Override + public boolean onViewHolderLongClick(View clickView, View viewHolderView, IMMessage item) { + return true; + } + + @Override + public void onFooterClick(ChatRoomMsgViewHolderBase viewHolderBase, IMMessage message) { + // 与 robot 对话 + container.proxy.onItemFooterClick(message); + } + + // 重新下载(对话框提示) + private void showReDownloadConfirmDlg(final IMMessage message) { + EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() { + + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + // 正常情况收到消息后附件会自动下载。如果下载失败,可调用该接口重新下载 + if (message.getAttachment() != null && message.getAttachment() instanceof FileAttachment) + NIMClient.getService(ChatRoomService.class).downloadAttachment((ChatRoomMessage) message, true); + } + }; + + final EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(container.activity, null, + container.activity.getString(R.string.repeat_download_message), true, listener); + dialog.show(); + } + + // 重发消息到服务器 + private void resendMessage(IMMessage message) { + // 重置状态为unsent + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + item.setStatus(MsgStatusEnum.sending); + refreshViewHolderByIndex(index); + } + + NIMClient.getService(ChatRoomService.class).sendMessage((ChatRoomMessage) message, true); + } + } + + private void setEarPhoneMode(boolean earPhoneMode, boolean update) { + if (update) { + UserPreferences.setEarPhoneModeEnable(earPhoneMode); + } + MessageAudioControl.getInstance(container.activity).setEarPhoneModeEnable(earPhoneMode); + } + + public void scrollToBottom() { + uiHandler.postDelayed(new Runnable() { + @Override + public void run() { + doScrollToBottom(); + } + }, 200); + } + + private void doScrollToBottom() { + messageListView.scrollToPosition(adapter.getBottomDataPosition()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderBase.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderBase.java new file mode 100644 index 0000000..56b5c99 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderBase.java @@ -0,0 +1,384 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import android.content.Context; +import android.text.TextUtils; +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.ProgressBar; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.adapter.ChatRoomMsgAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; + +/** + * 会话窗口消息列表项的ViewHolder基类,负责每个消息项的外层框架,包括头像,昵称,发送/接收进度条,重发按钮等。
+ * 具体的消息展示项可继承该基类,然后完成具体消息内容展示即可。 + */ +public abstract class ChatRoomMsgViewHolderBase extends RecyclerViewHolder { + + public ChatRoomMsgViewHolderBase(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + this.adapter = adapter; + } + + // basic + protected View view; + protected Context context; + protected BaseMultiItemFetchLoadAdapter adapter; + + // data + protected ChatRoomMessage message; + + // view + protected View alertButton; + protected TextView timeTextView; + protected ProgressBar progressBar; + protected TextView nameTextView; + protected FrameLayout contentContainer; + protected LinearLayout nameContainer; + protected TextView readReceiptTextView; + + private HeadImageView avatarLeft; + private HeadImageView avatarRight; + + public ImageView nameIconView; + + // contentContainerView的默认长按事件。如果子类需要不同的处理,可覆盖onItemLongClick方法 + // 但如果某些子控件会拦截触摸消息,导致contentContainer收不到长按事件,子控件也可在inflate时重新设置 + protected View.OnLongClickListener longClickListener; + + /// -- 以下接口可由子类覆盖或实现 + // 返回具体消息类型内容展示区域的layout res id + abstract protected int getContentResId(); + + // 在该接口中根据layout对各控件成员变量赋值 + abstract protected void inflateContentView(); + + // 将消息数据项与内容的view进行绑定 + abstract protected void bindContentView(); + + // 在该接口操作BaseViewHolder中的数据,进行事件绑定,可选 + protected void bindHolder(BaseViewHolder holder) { + + } + + // 内容区域点击事件响应处理。 + protected void onItemClick() { + } + + // 内容区域长按事件响应处理。该接口的优先级比adapter中有长按事件的处理监听高,当该接口返回为true时,adapter的长按事件监听不会被调用到。 + protected boolean onItemLongClick() { + return false; + } + + // 当是接收到的消息时,内容区域背景的drawable id + protected int leftBackground() { + return NimUIKitImpl.getOptions().chatRoomMsgLeftBackground; + } + + // 当是发送出去的消息时,内容区域背景的drawable id + protected int rightBackground() { + return NimUIKitImpl.getOptions().chatRoomMsgRightBackground; + } + + // 返回该消息是不是居中显示 + protected boolean isMiddleItem() { + return false; + } + + // 是否显示头像,默认为不显示 + protected boolean isShowHeadImage() { + return false; + } + + // 是否显示气泡背景,默认为不显示 + protected boolean isShowBubble() { + return false; + } + + // 是否显示昵称 + protected boolean shouldDisplayNick() { + return !isMiddleItem(); + } + + /// -- 以下接口可由子类调用 + protected final ChatRoomMsgAdapter getMsgAdapter() { + return (ChatRoomMsgAdapter) adapter; + } + + /** + * 下载附件/缩略图 + */ + protected void downloadAttachment() { + if (message.getAttachment() != null && message.getAttachment() instanceof FileAttachment) + NIMClient.getService(MsgService.class).downloadAttachment(message, true); + } + + // 设置FrameLayout子控件的gravity参数 + protected final void setGravity(View view, int gravity) { + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams(); + params.gravity = gravity; + } + + // 设置控件的长宽 + protected void setLayoutParams(int width, int height, View... views) { + for (View view : views) { + ViewGroup.LayoutParams maskParams = view.getLayoutParams(); + maskParams.width = width; + maskParams.height = height; + view.setLayoutParams(maskParams); + } + } + + // 根据layout id查找对应的控件 + protected T findViewById(int id) { + return (T) view.findViewById(id); + } + + // 判断消息方向,是否是接收到的消息 + protected boolean isReceivedMessage() { + return message.getDirect() == MsgDirectionEnum.In; + } + + /// -- 以下是基类实现代码 + @Override + public void convert(BaseViewHolder holder, ChatRoomMessage data, int position, boolean isScrolling) { + view = holder.getConvertView(); + context = holder.getContext(); + message = data; + + inflate(); + refresh(); + bindHolder(holder); + } + + protected final void inflate() { + timeTextView = findViewById(R.id.message_item_time); + avatarLeft = findViewById(R.id.message_item_portrait_left); + avatarRight = findViewById(R.id.message_item_portrait_right); + alertButton = findViewById(R.id.message_item_alert); + progressBar = findViewById(R.id.message_item_progress); + nameTextView = findViewById(R.id.message_item_nickname); + contentContainer = findViewById(R.id.message_item_content); + nameIconView = findViewById(R.id.message_item_name_icon); + nameContainer = findViewById(R.id.message_item_name_layout); + readReceiptTextView = findViewById(R.id.textViewAlreadyRead); + + // 这里只要inflate出来后加入一次即可 + if (contentContainer.getChildCount() == 0) { + View.inflate(view.getContext(), getContentResId(), contentContainer); + } + inflateContentView(); + } + + protected final void refresh() { + setHeadImageView(); + setNameTextView(); + setTimeTextView(); + setStatus(); + setOnClickListener(); + setLongClickListener(); + setContent(); + + bindContentView(); + } + + public void refreshCurrentItem() { + if (message != null) { + refresh(); + } + } + + /** + * 设置时间显示 + */ + private void setTimeTextView() { + if (getMsgAdapter().needShowTime(message)) { + timeTextView.setVisibility(View.VISIBLE); + } else { + timeTextView.setVisibility(View.GONE); + return; + } + + String text = TimeUtil.getTimeShowString(message.getTime(), false); + timeTextView.setText(text); + } + + /** + * 设置消息发送状态 + */ + private void setStatus() { + MsgStatusEnum status = message.getStatus(); + switch (status) { + case fail: + progressBar.setVisibility(View.GONE); + alertButton.setVisibility(View.VISIBLE); + break; + case sending: + progressBar.setVisibility(View.VISIBLE); + alertButton.setVisibility(View.GONE); + break; + default: + progressBar.setVisibility(View.GONE); + alertButton.setVisibility(View.GONE); + break; + } + } + + private void setHeadImageView() { + HeadImageView show = isReceivedMessage() ? avatarLeft : avatarRight; + HeadImageView hide = isReceivedMessage() ? avatarRight : avatarLeft; + hide.setVisibility(View.GONE); + if (!isShowHeadImage()) { + show.setVisibility(View.GONE); + return; + } + if (isMiddleItem()) { + show.setVisibility(View.GONE); + } else { + show.setVisibility(View.VISIBLE); + show.loadBuddyAvatar(message.getFromAccount()); + } + + } + + private void setOnClickListener() { + // 重发/重收按钮响应事件 + if (getMsgAdapter().getEventListener() != null) { + alertButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + getMsgAdapter().getEventListener().onFailedBtnClick(message); + } + }); + } + + // 内容区域点击事件响应, 相当于点击了整项 + contentContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onItemClick(); + } + }); + + // 头像点击事件响应 + if (NimUIKitImpl.getSessionListener() != null) { + View.OnClickListener portraitListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + NimUIKitImpl.getSessionListener().onAvatarClicked(context, message); + } + }; + avatarLeft.setOnClickListener(portraitListener); + avatarRight.setOnClickListener(portraitListener); + } + } + + /** + * item长按事件监听 + */ + private void setLongClickListener() { + longClickListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + // 优先派发给自己处理, + if (!onItemLongClick()) { + if (getMsgAdapter().getEventListener() != null) { + getMsgAdapter().getEventListener().onViewHolderLongClick(contentContainer, view, message); + return true; + } + } + return false; + } + }; + // 消息长按事件响应处理 + contentContainer.setOnLongClickListener(longClickListener); + + // 头像长按事件响应处理 + if (NimUIKitImpl.getSessionListener() != null) { + View.OnLongClickListener longClickListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + NimUIKitImpl.getSessionListener().onAvatarLongClicked(context, message); + return true; + } + }; + avatarLeft.setOnLongClickListener(longClickListener); + avatarRight.setOnLongClickListener(longClickListener); + } + } + + private void setNameTextView() { + if (!shouldDisplayNick()) { + nameTextView.setVisibility(View.GONE); + return; + } + + nameContainer.setPadding(ScreenUtil.dip2px(6), 0, 0, 0); + nameTextView.setVisibility(View.VISIBLE); + nameTextView.setText(getNameText()); + setStyleOfNameTextView(nameTextView, nameIconView); + } + + protected String getNameText() { + return ChatRoomViewHolderHelper.getNameText(message); + } + + protected void setStyleOfNameTextView(TextView nameTextView, ImageView nameIconView) { + ChatRoomViewHolderHelper.setStyleOfNameTextView(message, nameTextView, nameIconView); + } + + private void setContent() { + if (!isShowBubble() && !isMiddleItem()) { + return; + } + + LinearLayout bodyContainer = (LinearLayout) view.findViewById(R.id.message_item_body); + + // 调整container的位置 + int index = isReceivedMessage() ? 0 : 3; + if (bodyContainer.getChildAt(index) != contentContainer) { + bodyContainer.removeView(contentContainer); + bodyContainer.addView(contentContainer, index); + } + + if (isMiddleItem()) { + setGravity(bodyContainer, Gravity.CENTER); + } else { + if (isReceivedMessage()) { + setGravity(bodyContainer, Gravity.LEFT); + contentContainer.setBackgroundResource(leftBackground()); + } else { + setGravity(bodyContainer, Gravity.RIGHT); + contentContainer.setBackgroundResource(rightBackground()); + } + } + } + + private void setReadReceipt() { + if (!TextUtils.isEmpty(getMsgAdapter().getUuid()) && message.getUuid().equals(getMsgAdapter().getUuid())) { + readReceiptTextView.setVisibility(View.VISIBLE); + } else { + readReceiptTextView.setVisibility(View.GONE); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderFactory.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderFactory.java new file mode 100644 index 0000000..a0e3948 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderFactory.java @@ -0,0 +1,74 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomNotificationAttachment; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * 聊天室消息项展示ViewHolder工厂类。 + */ +public class ChatRoomMsgViewHolderFactory { + + private static HashMap, Class> viewHolders = + new HashMap<>(); + + static { + // built in + register(ChatRoomNotificationAttachment.class, ChatRoomMsgViewHolderNotification.class); + register(RobotAttachment.class, ChatRoomMsgViewHolderRobot.class); + register(ImageAttachment.class, ChatRoomMsgViewHolderPicture.class); + } + + public static void register(Class attach, Class viewHolder) { + viewHolders.put(attach, viewHolder); + } + + public static Class getViewHolderByType(ChatRoomMessage message) { + if (message.getMsgType() == MsgTypeEnum.text) { + return ChatRoomMsgViewHolderText.class; + } else { + Class viewHolder = null; + if (message.getAttachment() != null) { + Class clazz = message.getAttachment().getClass(); + while (viewHolder == null && clazz != null) { + viewHolder = viewHolders.get(clazz); + if (viewHolder == null) { + clazz = getSuperClass(clazz); + } + } + } + return viewHolder == null ? ChatRoomMsgViewHolderUnknown.class : viewHolder; + } + } + + private static Class getSuperClass(Class derived) { + Class sup = derived.getSuperclass(); + if (sup != null && MsgAttachment.class.isAssignableFrom(sup)) { + return sup; + } else { + for (Class itf : derived.getInterfaces()) { + if (MsgAttachment.class.isAssignableFrom(itf)) { + return itf; + } + } + } + return null; + } + + public static List> getAllViewHolders() { + List> list = new ArrayList<>(); + list.addAll(viewHolders.values()); + list.add(ChatRoomMsgViewHolderUnknown.class); + list.add(ChatRoomMsgViewHolderText.class); + list.add(ChatRoomMsgViewHolderPicture.class); + + return list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderNotification.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderNotification.java new file mode 100644 index 0000000..a37b308 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderNotification.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.chatroom.helper.ChatRoomNotificationHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomNotificationAttachment; + +public class ChatRoomMsgViewHolderNotification extends ChatRoomMsgViewHolderBase { + + protected TextView notificationTextView; + + public ChatRoomMsgViewHolderNotification(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_notification; + } + + @Override + protected boolean shouldDisplayNick() { + return false; + } + + @Override + protected void inflateContentView() { + notificationTextView = (TextView) view.findViewById(R.id.message_item_notification_label); + } + + @Override + protected void bindContentView() { + notificationTextView.setText(ChatRoomNotificationHelper.getNotificationText((ChatRoomNotificationAttachment) message.getAttachment())); + } + + @Override + protected boolean isMiddleItem() { + return true; + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderPicture.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderPicture.java new file mode 100644 index 0000000..9e7040c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderPicture.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.WatchMessagePictureActivity; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; + + +public class ChatRoomMsgViewHolderPicture extends ChatRoomMsgViewHolderThumbBase { + + public ChatRoomMsgViewHolderPicture(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_picture; + } + + @Override + protected void onItemClick() { + WatchMessagePictureActivity.start(context, message); + } + + @Override + protected String thumbFromSourceFile(String path) { + return path; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderRobot.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderRobot.java new file mode 100644 index 0000000..972dc15 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderRobot.java @@ -0,0 +1,105 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.robot.model.RobotResponseContent; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot.RobotContentLinearLayout; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot.RobotLinkViewStyle; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; + +import java.util.HashSet; +import java.util.Set; + +/** + * Created by hzchenkang on 2017/8/24. + */ + +public class ChatRoomMsgViewHolderRobot extends ChatRoomMsgViewHolderText implements RobotContentLinearLayout.ClickableChildView { + + private android.widget.LinearLayout containerIn; + private RobotContentLinearLayout robotContent; + private TextView holderFooterButton; + private Set onClickIds; + + + public ChatRoomMsgViewHolderRobot(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_robot; + } + + @Override + protected void inflateContentView() { + containerIn = findViewById(R.id.robot_in); + bodyTextView = containerIn.findViewById(R.id.nim_message_item_text_body); + robotContent = findViewById(R.id.robot_out); + int dp6 = ScreenUtil.dip2px(6); + robotContent.setPadding(dp6, 0, 0, 0); + RobotLinkViewStyle linkStyle = new RobotLinkViewStyle(); + linkStyle.setRobotTextColor(R.color.black); + linkStyle.setBackground(R.drawable.nim_chatroom_robot_link_view_selector); + robotContent.setLinkStyle(linkStyle); + holderFooterButton = findViewById(R.id.tv_robot_session_continue); + holderFooterButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (getMsgAdapter().getEventListener() != null) { + getMsgAdapter().getEventListener().onFooterClick(ChatRoomMsgViewHolderRobot.this, ChatRoomMsgViewHolderRobot.this.message); + } + } + }); + } + + @Override + protected void bindContentView() { + onClickIds = new HashSet<>(); // for child to add + RobotAttachment attachment = (RobotAttachment) message.getAttachment(); + + if (attachment.isRobotSend()) { + // 下行 + containerIn.setVisibility(View.GONE); + robotContent.setVisibility(View.VISIBLE); + holderFooterButton.setVisibility(View.VISIBLE); + nameIconView.setVisibility(View.GONE); + NimRobotInfo robotInfo = NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(attachment.getFromRobotAccount()); + if (robotInfo != null) { + nameTextView.setText(robotInfo.getName()); + } else { + nameTextView.setText(attachment.getFromRobotAccount()); + } + + robotContent.bindContentView(this, new RobotResponseContent(attachment.getResponse())); + } else { + // 上行 + containerIn.setVisibility(View.VISIBLE); + robotContent.setVisibility(View.GONE); + holderFooterButton.setVisibility(View.GONE); + super.bindContentView(); + } + } + + @Override + protected void bindHolder(BaseViewHolder holder) { + holder.getChildClickViewIds().clear(); + for (int id : onClickIds) { + holder.addOnClickListener(id); + } + + onClickIds.clear(); + } + + @Override + public void addClickableChildView(Class clazz, int id) { + onClickIds.add(id); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderText.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderText.java new file mode 100644 index 0000000..c360a6b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderText.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import android.graphics.Color; +import android.text.method.LinkMovementMethod; +import android.text.style.ImageSpan; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.MoonUtil; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +/** + * Created by hzxuwen on 2016/1/18. + */ +public class ChatRoomMsgViewHolderText extends ChatRoomMsgViewHolderBase { + + protected TextView bodyTextView; + + + public ChatRoomMsgViewHolderText(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_text; + } + + @Override + protected void inflateContentView() { + bodyTextView = findViewById(R.id.nim_message_item_text_body); + } + + protected String getDisplayText() { + return message.getContent(); + } + + @Override + protected boolean isShowBubble() { + return false; + } + + @Override + protected boolean isShowHeadImage() { + return false; + } + + @Override + protected void bindContentView() { + bodyTextView.setTextColor(Color.BLACK); + bodyTextView.setPadding(ScreenUtil.dip2px(6), 0, 0, 0); + MoonUtil.identifyFaceExpression(NimUIKit.getContext(), bodyTextView, getDisplayText(), ImageSpan.ALIGN_BOTTOM); + bodyTextView.setMovementMethod(LinkMovementMethod.getInstance()); + bodyTextView.setOnLongClickListener(longClickListener); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderThumbBase.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderThumbBase.java new file mode 100644 index 0000000..2db90f7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderThumbBase.java @@ -0,0 +1,138 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.MsgThumbImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.attachment.VideoAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; + +import java.io.File; + +public abstract class ChatRoomMsgViewHolderThumbBase extends ChatRoomMsgViewHolderBase { + + public ChatRoomMsgViewHolderThumbBase(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + protected MsgThumbImageView thumbnail; + protected View progressCover; + protected TextView progressLabel; + + @Override + protected boolean isShowBubble() { + return false; + } + + @Override + protected boolean isShowHeadImage() { + return false; + } + + @Override + protected void inflateContentView() { + thumbnail = findViewById(R.id.message_item_thumb_thumbnail); + progressBar = findViewById(R.id.message_item_thumb_progress_bar); // 覆盖掉 + progressCover = findViewById(R.id.message_item_thumb_progress_cover); + progressLabel = findViewById(R.id.message_item_thumb_progress_text); + } + + @Override + protected void bindContentView() { + FileAttachment msgAttachment = (FileAttachment) message.getAttachment(); + String path = msgAttachment.getPath(); + String thumbPath = msgAttachment.getThumbPath(); + if (!TextUtils.isEmpty(thumbPath)) { + loadThumbnailImage(thumbPath, false, msgAttachment.getExtension()); + } else if (!TextUtils.isEmpty(path)) { + loadThumbnailImage(thumbFromSourceFile(path), true, msgAttachment.getExtension()); + } else { + loadThumbnailImage(null, false, msgAttachment.getExtension()); + if (message.getAttachStatus() == AttachStatusEnum.transferred + || message.getAttachStatus() == AttachStatusEnum.def) { + downloadAttachment(); + } + } + + refreshStatus(); + } + + private void refreshStatus() { + FileAttachment attachment = (FileAttachment) message.getAttachment(); + if (TextUtils.isEmpty(attachment.getPath()) && TextUtils.isEmpty(attachment.getThumbPath())) { + if (message.getAttachStatus() == AttachStatusEnum.fail || message.getStatus() == MsgStatusEnum.fail) { + alertButton.setVisibility(View.VISIBLE); + } else { + alertButton.setVisibility(View.GONE); + } + } + + if (message.getStatus() == MsgStatusEnum.sending + || (isReceivedMessage() && message.getAttachStatus() == AttachStatusEnum.transferring)) { + progressCover.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.VISIBLE); + progressLabel.setVisibility(View.VISIBLE); + progressLabel.setText(StringUtil.getPercentString(getMsgAdapter().getProgress(message))); + } else { + progressCover.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + progressLabel.setVisibility(View.GONE); + } + } + + private void loadThumbnailImage(String path, boolean isOriginal, String ext) { + setImageSize(path); + if (path != null) { + //thumbnail.loadAsPath(thumbPath, getImageMaxEdge(), getImageMaxEdge(), maskBg()); + thumbnail.loadAsPath(path, getImageMaxEdge(), getImageMaxEdge(), maskBg(), ext); + } else { + thumbnail.loadAsResource(R.drawable.nim_image_default, maskBg()); + } + } + + private void setImageSize(String thumbPath) { + int[] bounds = null; + if (thumbPath != null) { + bounds = BitmapDecoder.decodeBound(new File(thumbPath)); + } + if (bounds == null) { + if (message.getMsgType() == MsgTypeEnum.image) { + ImageAttachment attachment = (ImageAttachment) message.getAttachment(); + bounds = new int[]{attachment.getWidth(), attachment.getHeight()}; + } else if (message.getMsgType() == MsgTypeEnum.video) { + VideoAttachment attachment = (VideoAttachment) message.getAttachment(); + bounds = new int[]{attachment.getWidth(), attachment.getHeight()}; + } + } + + if (bounds != null) { + ImageUtil.ImageSize imageSize = ImageUtil.getThumbnailDisplaySize(bounds[0], bounds[1], getImageMaxEdge(), getImageMinEdge()); + setLayoutParams(imageSize.width, imageSize.height, thumbnail); + } + } + + private int maskBg() { + return R.drawable.nim_message_item_round_bg; + } + + public static int getImageMaxEdge() { + return (int) (165.0 / 320.0 * ScreenUtil.screenWidth); + } + + public static int getImageMinEdge() { + return (int) (76.0 / 320.0 * ScreenUtil.screenWidth); + } + + protected abstract String thumbFromSourceFile(String path); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderUnknown.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderUnknown.java new file mode 100644 index 0000000..af8f371 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomMsgViewHolderUnknown.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +/** + * Created by huangjun on 2016/12/27. + */ +public class ChatRoomMsgViewHolderUnknown extends ChatRoomMsgViewHolderBase { + + public ChatRoomMsgViewHolderUnknown(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_unknown; + } + + @Override + protected boolean isShowHeadImage() { + if (message.getSessionType() == SessionTypeEnum.ChatRoom) { + return false; + } + return true; + } + + @Override + protected void inflateContentView() { + } + + @Override + protected void bindContentView() { + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomViewHolderHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomViewHolderHelper.java new file mode 100644 index 0000000..7591e20 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/chatroom/viewholder/ChatRoomViewHolderHelper.java @@ -0,0 +1,45 @@ +package com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.chatroom.helper.ChatRoomHelper; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.chatroom.constant.MemberType; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; + + +/** + * 聊天室成员姓名 + * Created by hzxuwen on 2016/1/20. + */ +public class ChatRoomViewHolderHelper { + + public static String getNameText(ChatRoomMessage message) { + // 聊天室中显示姓名 + if (message.getChatRoomMessageExtension() != null) { + return message.getChatRoomMessageExtension().getSenderNick(); + } else { + ChatRoomMember member = NimUIKitImpl.getChatRoomProvider().getChatRoomMember(message.getSessionId(), message.getFromAccount()); + return member == null ? UserInfoHelper.getUserName(message.getFromAccount()) : member.getNick(); + } + } + + public static void setStyleOfNameTextView(ChatRoomMessage message, TextView nameTextView, ImageView nameIconView) { + nameTextView.setTextColor(NimUIKitImpl.getContext().getResources().getColor(R.color.color_black_ff999999)); + MemberType type = ChatRoomHelper.getMemberTypeByRemoteExt(message); + if (type == MemberType.ADMIN) { + nameIconView.setImageResource(R.drawable.nim_admin_icon); + nameIconView.setVisibility(View.VISIBLE); + } else if (type == MemberType.CREATOR) { + nameIconView.setImageResource(R.drawable.nim_master_icon); + nameIconView.setVisibility(View.VISIBLE); + } else { + nameIconView.setVisibility(View.GONE); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/ContactsFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/ContactsFragment.java new file mode 100644 index 0000000..a68bb5c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/ContactsFragment.java @@ -0,0 +1,444 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactsCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.main.LoginSyncDataStatusObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.main.OnlineStateChangeObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ItemTypes; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactGroupStrategy; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.provider.ContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.IContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder.LabelHolder; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder.OnlineStateContactHolder; +import com.fengliyan.tianlesue.im.uikit.common.fragment.TFragment; +import com.fengliyan.tianlesue.im.uikit.common.ui.liv.LetterIndexView; +import com.fengliyan.tianlesue.im.uikit.common.ui.liv.LivIndex; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.im.uikit.impl.cache.UIKitLogTag; +import com.netease.nimlib.sdk.Observer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import me.everything.android.ui.overscroll.OverScrollDecoratorHelper; + + +/** + * 通讯录Fragment + *

+ * Created by huangjun on 2015/9/7. + */ +public class ContactsFragment extends TFragment { + + private ContactDataAdapter adapter; + + private ListView listView; + + private TextView countText; + + private LivIndex litterIdx; + + private View loadingFrame; + + private ContactsCustomization customization; + + private ReloadFrequencyControl reloadControl = new ReloadFrequencyControl(); + + public void setContactsCustomization(ContactsCustomization customization) { + this.customization = customization; + } + + private static final class ContactsGroupStrategy extends ContactGroupStrategy { + public ContactsGroupStrategy() { + add(ContactGroupStrategy.GROUP_NULL, -1, ""); + addABC(0); + } + } + + /** + * ***************************************** 生命周期 ***************************************** + */ + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.nim_contacts, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // 界面初始化 + initAdapter(); + findViews(); + buildLitterIdx(getView()); + + // 注册观察者 + registerObserver(true); + registerOnlineStateChangeListener(true); + // 加载本地数据 + reload(false); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + registerObserver(false); + registerOnlineStateChangeListener(false); + } + + private void initAdapter() { + IContactDataProvider dataProvider = new ContactDataProvider(ItemTypes.FRIEND); + + adapter = new ContactDataAdapter(getActivity(), new ContactsGroupStrategy(), dataProvider) { + @Override + protected List onNonDataItems() { + if (customization != null) { + return customization.onGetFuncItems(); + } + + return new ArrayList<>(); + } + + @Override + protected void onPreReady() { + loadingFrame.setVisibility(View.VISIBLE); + } + + @Override + protected void onPostLoad(boolean empty, String queryText, boolean all) { + loadingFrame.setVisibility(View.GONE); + int userCount = NimUIKit.getContactProvider().getMyFriendsCount(); + countText.setText("共有好友" + userCount + "名"); + + onReloadCompleted(); + } + }; + + adapter.addViewHolder(ItemTypes.LABEL, LabelHolder.class); + if (customization != null) { + adapter.addViewHolder(ItemTypes.FUNC, customization.onGetFuncViewHolderClass()); + } + adapter.addViewHolder(ItemTypes.FRIEND, OnlineStateContactHolder.class); + } + + private void findViews() { + // loading + loadingFrame = findView(R.id.contact_loading_frame); + + // count + View countLayout = View.inflate(getView().getContext(), R.layout.nim_contacts_count_item, null); + countLayout.setClickable(false); + countText = countLayout.findViewById(R.id.contactCountText); + + // ListView + listView = findView(R.id.contact_list_view); + listView.addFooterView(countLayout); // 注意:addFooter要放在setAdapter之前,否则旧版本手机可能会add不上 + listView.setAdapter(adapter); + listView.setOnScrollListener(new AbsListView.OnScrollListener() { + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }); + + ContactItemClickListener listener = new ContactItemClickListener(); + listView.setOnItemClickListener(listener); + listView.setOnItemLongClickListener(listener); + + // ios style + OverScrollDecoratorHelper.setUpOverScroll(listView); + } + + private void buildLitterIdx(View view) { + LetterIndexView livIndex = view.findViewById(R.id.liv_index); + livIndex.setNormalColor(getResources().getColor(R.color.contacts_letters_color)); + ImageView imgBackLetter = view.findViewById(R.id.img_hit_letter); + TextView litterHit = view.findViewById(R.id.tv_hit_letter); + litterIdx = adapter.createLivIndex(listView, livIndex, litterHit, imgBackLetter); + + litterIdx.show(); + } + + private final class ContactItemClickListener implements OnItemClickListener, OnItemLongClickListener { + + @Override + public void onItemClick(AdapterView parent, View view, int position, + long id) { + AbsContactItem item = (AbsContactItem) adapter.getItem(position); + if (item == null) { + return; + } + + int type = item.getItemType(); + + if (type == ItemTypes.FUNC && customization != null) { + customization.onFuncItemClick(item); + return; + } + + if (type == ItemTypes.FRIEND && item instanceof ContactItem && NimUIKitImpl.getContactEventListener() != null) { + NimUIKitImpl.getContactEventListener().onItemClick(getActivity(), (((ContactItem) item).getContact()).getContactId()); + } + } + + @Override + public boolean onItemLongClick(AdapterView parent, View view, + int position, long id) { + AbsContactItem item = (AbsContactItem) adapter.getItem(position); + if (item == null) { + return false; + } + + if (item instanceof ContactItem && NimUIKitImpl.getContactEventListener() != null) { + NimUIKitImpl.getContactEventListener().onItemLongClick(getActivity(), (((ContactItem) item).getContact()).getContactId()); + } + + return true; + } + } + + public void scrollToTop() { + if (listView != null) { + int top = listView.getFirstVisiblePosition(); + int bottom = listView.getLastVisiblePosition(); + if (top >= (bottom - top)) { + listView.setSelection(bottom - top); + listView.smoothScrollToPosition(0); + } else { + listView.smoothScrollToPosition(0); + } + } + } + + /** + * *********************************** 通讯录加载控制 ******************************* + */ + + /** + * 加载通讯录数据并刷新 + * + * @param reload true则重新加载数据;false则判断当前数据源是否空,若空则重新加载,不空则不加载 + */ + private void reload(boolean reload) { + if (!reloadControl.canDoReload(reload)) { + return; + } + + if (adapter == null) { + if (getActivity() == null) { + return; + } + + initAdapter(); + } + + // 开始加载 + if (!adapter.load(reload)) { + // 如果不需要加载,则直接当完成处理 + onReloadCompleted(); + } + } + + private void onReloadCompleted() { + if (reloadControl.continueDoReloadWhenCompleted()) { + // 计划下次加载,稍有延迟 + getHandler().postDelayed(new Runnable() { + @Override + public void run() { + boolean reloadParam = reloadControl.getReloadParam(); + Log.i(UIKitLogTag.CONTACT, "continue reload " + reloadParam); + reloadControl.resetStatus(); + reload(reloadParam); + } + }, 50); + } else { + // 本次加载完成 + reloadControl.resetStatus(); + } + + LogUtil.i(UIKitLogTag.CONTACT, "contact load completed"); + } + + /** + * 通讯录加载频率控制 + */ + class ReloadFrequencyControl { + boolean isReloading = false; + boolean needReload = false; + boolean reloadParam = false; + + boolean canDoReload(boolean param) { + if (isReloading) { + // 正在加载,那么计划加载完后重载 + needReload = true; + if (param) { + // 如果加载过程中又有多次reload请求,多次参数只要有true,那么下次加载就是reload(true); + reloadParam = true; + } + LogUtil.i(UIKitLogTag.CONTACT, "pending reload task"); + + return false; + } else { + // 如果当前空闲,那么立即开始加载 + isReloading = true; + return true; + } + } + + boolean continueDoReloadWhenCompleted() { + return needReload; + } + + void resetStatus() { + isReloading = false; + needReload = false; + reloadParam = false; + } + + boolean getReloadParam() { + return reloadParam; + } + } + + /** + * *********************************** 用户资料、好友关系变更、登录数据同步完成观察者 ******************************* + */ + + private void registerObserver(boolean register) { + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, register); + NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + LoginSyncDataStatusObserver.getInstance().observeSyncDataCompletedEvent(loginSyncCompletedObserver); + } + + ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + reloadWhenDataChanged(accounts, "onAddedOrUpdatedFriends", true); + } + + @Override + public void onDeletedFriends(List accounts) { + reloadWhenDataChanged(accounts, "onDeletedFriends", true); + } + + @Override + public void onAddUserToBlackList(List accounts) { + reloadWhenDataChanged(accounts, "onAddUserToBlackList", true); + } + + @Override + public void onRemoveUserFromBlackList(List accounts) { + reloadWhenDataChanged(accounts, "onRemoveUserFromBlackList", true); + } + }; + + private UserInfoObserver userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + reloadWhenDataChanged(accounts, "onUserInfoChanged", true, false); // 非好友资料变更,不用刷新界面 + } + }; + + private Observer loginSyncCompletedObserver = new Observer() { + @Override + public void onEvent(Void aVoid) { + getHandler().postDelayed(new Runnable() { + @Override + public void run() { + reloadWhenDataChanged(null, "onLoginSyncCompleted", false); + } + }, 50); + } + }; + + private void reloadWhenDataChanged(List accounts, String reason, boolean reload) { + reloadWhenDataChanged(accounts, reason, reload, true); + } + + private void reloadWhenDataChanged(List accounts, String reason, boolean reload, boolean force) { + if (accounts == null || accounts.isEmpty()) { + return; + } + + boolean needReload = false; + if (!force) { + // 非force:与通讯录无关的(非好友)变更通知,去掉 + for (String account : accounts) { + if (NimUIKit.getContactProvider().isMyFriend(account)) { + needReload = true; + break; + } + } + } else { + needReload = true; + } + + if (!needReload) { + Log.d(UIKitLogTag.CONTACT, "no need to reload contact"); + return; + } + + // log + StringBuilder sb = new StringBuilder(); + sb.append("ContactFragment received data changed as [" + reason + "] : "); + if (accounts != null && !accounts.isEmpty()) { + for (String account : accounts) { + sb.append(account); + sb.append(" "); + } + sb.append(", changed size=" + accounts.size()); + } + Log.i(UIKitLogTag.CONTACT, sb.toString()); + + // reload + reload(reload); + } + + /** + * *********************************** 在线状态 ******************************* + */ + + OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() { + @Override + public void onlineStateChange(Set accounts) { + // 更新 + adapter.notifyDataSetChanged(); + } + }; + + private void registerOnlineStateChangeListener(boolean register) { + if (!NimUIKitImpl.enableOnlineState()) { + return; + } + NimUIKitImpl.getOnlineStateChangeObservable().registerOnlineStateChangeListeners(onlineStateChangeObserver, register); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/AbsContactItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/AbsContactItem.java new file mode 100644 index 0000000..b704de1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/AbsContactItem.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +/** + * 通讯录数据项抽象类 + * Created by huangjun on 2015/2/10. + */ +public abstract class AbsContactItem { + /** + * 所属的类型 + * + * @see ItemTypes + */ + public abstract int getItemType(); + + /** + * 所属的分组 + */ + public abstract String belongsGroup(); + + protected final int compareType(AbsContactItem item) { + return compareType(getItemType(), item.getItemType()); + } + + public static int compareType(int lhs, int rhs) { + return lhs - rhs; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactIdFilter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactIdFilter.java new file mode 100644 index 0000000..efe4d2a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactIdFilter.java @@ -0,0 +1,33 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; + +import java.util.Collection; + +public class ContactIdFilter implements ContactItemFilter { + private static final long serialVersionUID = -6813849507791265300L; + + private final Collection ids; + + private boolean exclude = true; // false means include + + public ContactIdFilter(Collection ids) { + this.ids = ids; + } + + public ContactIdFilter(Collection ids, boolean exclude) { + this.ids = ids; + this.exclude = exclude; + } + + @Override + public boolean filter(AbsContactItem item) { + if (item instanceof ContactItem) { + IContact contact = ((ContactItem) item).getContact(); + boolean contains = ids.contains(contact.getContactId()); + return exclude ? contains : !contains; + } + + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactItem.java new file mode 100644 index 0000000..85a5888 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactItem.java @@ -0,0 +1,54 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactGroupStrategy; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextComparator; + +public class ContactItem extends AbsContactItem implements Comparable { + private final IContact contact; + + private final int dataItemType; + + public ContactItem(IContact contact, int type) { + this.contact = contact; + this.dataItemType = type; + } + + public IContact getContact() { + return contact; + } + + @Override + public int getItemType() { + return dataItemType; + } + + @Override + public int compareTo(ContactItem item) { + // TYPE + int compare = compareType(item); + if (compare != 0) { + return compare; + } else { + return TextComparator.compareIgnoreCase(getCompare(), item.getCompare()); + } + } + + @Override + public String belongsGroup() { + IContact contact = getContact(); + if (contact == null) { + return ContactGroupStrategy.GROUP_NULL; + } + + String group = TextComparator.getLeadingUp(getCompare()); + return !TextUtils.isEmpty(group) ? group : ContactGroupStrategy.GROUP_SHARP; + } + + private String getCompare() { + IContact contact = getContact(); + return contact != null ? contact.getDisplayName() : null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactItemFilter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactItemFilter.java new file mode 100644 index 0000000..3e57d59 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ContactItemFilter.java @@ -0,0 +1,7 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +import java.io.Serializable; + +public interface ContactItemFilter extends Serializable { + boolean filter(AbsContactItem item); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ItemTypes.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ItemTypes.java new file mode 100644 index 0000000..60084fd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/ItemTypes.java @@ -0,0 +1,39 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +/** + * 通讯录列表项类型 + * Created by huangjun on 2015/2/10. + */ +public interface ItemTypes { + + /** + * 基础类型 + */ + int TEXT = -2; + + int LABEL = -1; + + /** + * 扩展类型 + */ + int FUNC = 0; // 功能项 + + int FRIEND = 1; // 好友项 + + int TEAM = 2; // 群组项 + + int TEAM_MEMBER = 3; // 群成员 + + int MSG = 4; // 消息 + + /** + * 子类型 + */ + interface TEAMS { + int BASE = ItemTypes.TEAM << 16; + + int NORMAL_TEAM = BASE + 1; // 普通群 + + int ADVANCED_TEAM = BASE + 2; // 高级群 + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/LabelItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/LabelItem.java new file mode 100644 index 0000000..5bccf29 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/LabelItem.java @@ -0,0 +1,23 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +public class LabelItem extends AbsContactItem { + private final String text; + + public LabelItem(String text) { + this.text = text; + } + + @Override + public int getItemType() { + return ItemTypes.LABEL; + } + + @Override + public String belongsGroup() { + return null; + } + + public final String getText() { + return text; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/MsgItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/MsgItem.java new file mode 100644 index 0000000..d28c049 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/MsgItem.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.netease.nimlib.sdk.search.model.MsgIndexRecord; + +public class MsgItem extends AbsContactItem { + private final IContact contact; + + private final MsgIndexRecord record; + + private final boolean querySession; + + public MsgItem(IContact contact, MsgIndexRecord record, boolean querySession) { + this.contact = contact; + this.record = record; + this.querySession = querySession; + } + + public IContact getContact() { + return contact; + } + + public MsgIndexRecord getRecord() { + return record; + } + + public boolean isQuerySession() { + return querySession; + } + + @Override + public int getItemType() { + return ItemTypes.MSG; + } + + @Override + public String belongsGroup() { + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/TextItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/TextItem.java new file mode 100644 index 0000000..782f751 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/item/TextItem.java @@ -0,0 +1,35 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.item; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactGroupStrategy; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextComparator; + +public class TextItem extends AbsContactItem implements Comparable { + private final String text; + + public TextItem(String text) { + this.text = text != null ? text : ""; + } + + public final String getText() { + return text; + } + + @Override + public int getItemType() { + return ItemTypes.TEXT; + } + + @Override + public String belongsGroup() { + String group = TextComparator.getLeadingUp(text); + + return !TextUtils.isEmpty(group) ? group : ContactGroupStrategy.GROUP_SHARP; + } + + @Override + public int compareTo(TextItem item) { + return TextComparator.compareIgnoreCase(text, item.text); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/AbsContact.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/AbsContact.java new file mode 100644 index 0000000..324c96a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/AbsContact.java @@ -0,0 +1,5 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +public abstract class AbsContact implements IContact { + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/AbsContactDataList.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/AbsContactDataList.java new file mode 100644 index 0000000..7b1518e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/AbsContactDataList.java @@ -0,0 +1,192 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.LabelItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 通讯录列表数据抽象类 + * Group定义 + *

+ * Created by huangjun on 2015/2/10. + */ +public abstract class AbsContactDataList { + protected final ContactGroupStrategy groupStrategy; + + protected final Map groupMap = new HashMap<>(); + + protected final Group groupNull = new Group(null, null); + + private TextQuery query; + + private static final class NoneGroupStrategy extends ContactGroupStrategy { + @Override + public String belongs(AbsContactItem item) { + return null; + } + + @Override + public int compare(String lhs, String rhs) { + return 0; + } + } + + public AbsContactDataList(ContactGroupStrategy groupStrategy) { + if (groupStrategy == null) { + groupStrategy = new NoneGroupStrategy(); + } + + this.groupStrategy = groupStrategy; + } + + // + // ACCESS + // + + public abstract int getCount(); + + public abstract boolean isEmpty(); + + public abstract AbsContactItem getItem(int index); + + public abstract List getItems(); + + public abstract Map getIndexes(); + + public final TextQuery getQuery() { + return query; + } + + public final String getQueryText() { + return query != null ? query.text : null; + } + + public final void setQuery(TextQuery query) { + this.query = query; + } + + // + // BUILD + // + + public abstract void build(); + + public final void add(AbsContactItem item) { + if (item == null) { + return; + } + + Group group; + + String id = groupStrategy.belongs(item); + if (id == null) { + group = groupNull; + } else { + group = groupMap.get(id); + if (group == null) { + group = new Group(id, groupStrategy.getName(id)); + groupMap.put(id, group); + } + } + + group.add(item); + } + + protected final void sortGroups(List groups) { + Collections.sort(groups, new Comparator() { + @Override + public int compare(Group lhs, Group rhs) { + return groupStrategy.compare(lhs.id, rhs.id); + } + }); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected static final class Group { + final String id; + + final String title; + + final boolean hasHead; + + final List items = new ArrayList(); + + Group(String id, String title) { + this.id = id; + this.title = title; + this.hasHead = !TextUtils.isEmpty(title); + } + + int getCount() { + return items.size() + (hasHead ? 1 : 0); + } + + AbsContactItem getItem(int index) { + if (hasHead) { + if (index == 0) { + return getHead(); + } else { + index--; + return (AbsContactItem) (index >= 0 && index < items.size() ? items.get(index) : null); + } + } else { + return (AbsContactItem) (index >= 0 && index < items.size() ? items.get(index) : null); + } + } + + AbsContactItem getHead() { + return hasHead ? new LabelItem(title) : null; + } + + List getItems() { + return items; + } + + void add(AbsContactItem add) { + if (add instanceof Comparable) { + addComparable((Comparable) add); + } else { + items.add(add); + } + } + + void merge(Group group) { + for (Object item : group.items) { + add((AbsContactItem) item); + } + } + + void addComparable(Comparable add) { + if (items.size() < 8) { + for (int index = 0; index < items.size(); index++) { + Comparable item = (Comparable) items.get(index); + if ((item.compareTo((AbsContactItem) add)) > 0) { + items.add(index, add); + return; + } + } + items.add(add); + } else { + int index = Collections.binarySearch(items, add); + if (index < 0) { + index = -index; + --index; + } + if (index >= items.size()) { + items.add(add); + } else { + items.add(index, add); + } + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataAdapter.java new file mode 100644 index 0000000..db0c85b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataAdapter.java @@ -0,0 +1,313 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +import android.content.Context; +import android.os.AsyncTask; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItemFilter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.IContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder.AbsContactViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.liv.LetterIndexView; +import com.fengliyan.tianlesue.im.uikit.common.ui.liv.LivIndex; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.impl.cache.UIKitLogTag; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * 通讯录数据适配器 + *

+ * Created by huangjun on 2015/2/10. + */ +public class ContactDataAdapter extends BaseAdapter { + + private final Context context; + + private final SparseArray>> viewHolderMap; + + private final ContactGroupStrategy groupStrategy; + + private final IContactDataProvider dataProvider; + + private AbsContactDataList datas; + + private final HashMap indexes = new HashMap<>(); + + private ContactItemFilter filter; + + private ContactItemFilter disableFilter; + + public ContactDataAdapter(Context context, ContactGroupStrategy groupStrategy, IContactDataProvider dataProvider) { + this.context = context; + this.groupStrategy = groupStrategy; + this.dataProvider = dataProvider; + this.viewHolderMap = new SparseArray<>(6); + } + + public void addViewHolder(int itemDataType, Class> viewHolder) { + this.viewHolderMap.put(itemDataType, viewHolder); + } + + public final void setFilter(ContactItemFilter filter) { + this.filter = filter; + } + + public final void setDisableFilter(ContactItemFilter disableFilter) { + this.disableFilter = disableFilter; + } + + public final LivIndex createLivIndex(ListView lv, LetterIndexView liv, TextView tvHit, ImageView ivBk) { + return new LivIndex(lv, liv, tvHit, ivBk, getIndexes()); + } + + @Override + public int getCount() { + return datas != null ? datas.getCount() : 0; + } + + @Override + public Object getItem(int position) { + return datas != null ? datas.getItem(position) : null; + } + + @Override + public boolean isEmpty() { + return datas != null ? datas.isEmpty() : true; + } + + public final TextQuery getQuery() { + return datas != null ? datas.getQuery() : null; + } + + private void updateData(AbsContactDataList datas) { + this.datas = datas; + + updateIndexes(datas.getIndexes()); + + notifyDataSetChanged(); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public int getItemViewType(int position) { + Object obj = getItem(position); + if (obj == null) { + return -1; + } + AbsContactItem item = (AbsContactItem) obj; + int type = item.getItemType(); + return viewHolderMap.indexOfKey(type); + } + + @Override + public int getViewTypeCount() { + return viewHolderMap.size(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + AbsContactItem item = (AbsContactItem) getItem(position); + if (item == null) { + return null; + } + AbsContactViewHolder holder = null; + try { + if (convertView == null || (holder = (AbsContactViewHolder) convertView.getTag()) == null) { + holder = (AbsContactViewHolder) viewHolderMap.get(item.getItemType()).newInstance(); + if (holder != null) { + holder.create(context); + + + + + } + } + } catch (Exception e) { + e.printStackTrace(); + } + if (holder == null) { + return null; + } + + holder.refresh(this, position, item); + convertView = holder.getView(); + if (convertView != null) { + convertView.setTag(holder); + } + + return convertView; + } + + @Override + public boolean isEnabled(int position) { + if (disableFilter != null) { + return !disableFilter.filter((AbsContactItem) getItem(position)); + } + + return true; + } + + public final void query(String query) { + startTask(new TextQuery(query), true); + } + + public final boolean load(boolean reload) { + if (!reload && !isEmpty()) { + return false; + } + + LogUtil.i(UIKitLogTag.CONTACT, "contact load data"); + + startTask(null, false); + + return true; + } + + public final void query(TextQuery query) { + startTask(query, true); + } + + private final List tasks = new ArrayList<>(); + + /** + * 启动搜索任务 + * + * @param query 要搜索的信息,填null表示查询所有数据 + * @param abort 是否终止:例如搜索的时候,第一个搜索词还未搜索完成,第二个搜索词已生成,那么取消之前的搜索任务 + */ + private void startTask(TextQuery query, boolean abort) { + if (abort) { + for (Task task : tasks) { + task.cancel(false); // 设为true有风险! + } + } + + Task task = new Task(new ContactDataTask(query, dataProvider, filter) { + @Override + protected void onPreProvide(AbsContactDataList datas) { + List itemsND = onNonDataItems(); + + if (itemsND != null) { + for (AbsContactItem item : itemsND) { + datas.add(item); + } + } + } + }); + + tasks.add(task); + + task.execute(); + } + + private void onTaskFinish(Task task) { + tasks.remove(task); + } + + /** + * 搜索/查询数据异步任务 + */ + + private class Task extends AsyncTask implements ContactDataTask.Host { + final ContactDataTask task; + + Task(ContactDataTask task) { + task.setHost(this); + + this.task = task; + } + + @Override + public void onData(ContactDataTask task, AbsContactDataList datas, boolean all) { + publishProgress(datas, all); + } + + @Override + public boolean isCancelled(ContactDataTask task) { + return isCancelled(); + } + + @Override + protected void onPreExecute() { + onPreReady(); + } + + @Override + protected Void doInBackground(Void... params) { + task.run(new ContactDataList(groupStrategy)); + + return null; + } + + @Override + protected void onProgressUpdate(Object... values) { + AbsContactDataList datas = (AbsContactDataList) values[0]; + boolean all = (Boolean) values[1]; + + onPostLoad(datas.isEmpty(), datas.getQueryText(), all); + + updateData(datas); + } + + @Override + protected void onPostExecute(Void result) { + onTaskFinish(this); + } + + @Override + protected void onCancelled() { + onTaskFinish(this); + } + } + + + /** + * 数据未准备 + */ + protected void onPreReady() { + } + + /** + * 数据加载完成 + */ + protected void onPostLoad(boolean empty, String query, boolean all) { + } + + /** + * 加载完成后,加入非数据项 + * + * @return + */ + protected List onNonDataItems() { + return null; + } + + + private Map getIndexes() { + return this.indexes; + } + + private void updateIndexes(Map indexes) { + // CLEAR + this.indexes.clear(); + // SET + this.indexes.putAll(indexes); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataList.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataList.java new file mode 100644 index 0000000..7f9cca2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataList.java @@ -0,0 +1,110 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * 通讯录列表数据(分组、索引) + * Created by huangjun on 2015/2/10. + */ +public class ContactDataList extends AbsContactDataList { + // + // RESULT DATA + // + + private List groups; + + private Map indexes; + + public ContactDataList(ContactGroupStrategy groupStrategy) { + super(groupStrategy); + } + + @Override + public int getCount() { + int count = 0; + for (Group group : groups) { + count += group.getCount(); + } + return count; + } + + @Override + public AbsContactItem getItem(int index) { + int count = 0; + for (Group group : groups) { + int gIndex = index - count; + int gCount = group.getCount(); + + if (gIndex >= 0 && gIndex < gCount) { + return group.getItem(gIndex); + } + + count += gCount; + } + + return null; + } + + @Override + public boolean isEmpty() { + return groups.isEmpty() || indexes.isEmpty(); + } + + @Override + public List getItems() { + List items = new ArrayList(); + for (Group group : groups) { + AbsContactItem head = group.getHead(); + if (head != null) { + items.add(head); + } + items.addAll(group.getItems()); + } + + return items; + } + + @Override + public Map getIndexes() { + return indexes; + } + + @Override + public void build() { + // + // GROUPS + // + + List groups = new ArrayList(); + groups.add(groupNull); + groups.addAll(groupMap.values()); + sortGroups(groups); + + // + // INDEXES + // + + Map indexes = new HashMap(); + int count = 0; + for (Group group : groups) { + if (group.id != null) { + indexes.put(group.id, count); + } + + count += group.getCount(); + } + + // + // RESULT + // + + this.groups = groups; + this.indexes = indexes; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataTask.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataTask.java new file mode 100644 index 0000000..babf531 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactDataTask.java @@ -0,0 +1,90 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItemFilter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.IContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; + +import java.util.List; + +/** + * 通讯录获取数据任务 + * Created by huangjun on 2015/2/10. + */ +public class ContactDataTask { + + public interface Host { + public void onData(ContactDataTask task, AbsContactDataList datas, boolean all); // 搜索完成,返回数据给调用方 + + public boolean isCancelled(ContactDataTask task); // 判断调用放是否已经取消 + } + + private final IContactDataProvider dataProvider; // 数据源提供者 + + private final ContactItemFilter filter; // 项过滤器 + + private final TextQuery query; // 要搜索的信息,null为查询所有 + + private Host host; + + public ContactDataTask(TextQuery query, IContactDataProvider dataProvider, ContactItemFilter filter) { + this.query = query; + this.dataProvider = dataProvider; + this.filter = filter; + } + + public final void setHost(Host host) { + this.host = host; + } + + protected void onPreProvide(AbsContactDataList datas) { + + } + + public final void run(AbsContactDataList datas) { + // CANCELLED + if (isCancelled()) { + return; + } + + // PRE PROVIDE + onPreProvide(datas); + + // CANCELLED + if (isCancelled()) { + return; + } + + // PROVIDE + List items = dataProvider.provide(query); + + // ADD + add(datas, items, filter); + + // BUILD + datas.build(); + + // PUBLISH ALL + publish(datas, true); + } + + private void publish(AbsContactDataList datas, boolean all) { + if (host != null) { + datas.setQuery(query); + + host.onData(this, datas, all); + } + } + + private boolean isCancelled() { + return host != null && host.isCancelled(this); + } + + private static void add(AbsContactDataList datas, List items, ContactItemFilter filter) { + for (AbsContactItem item : items) { + if (filter == null || !filter.filter(item)) { + datas.add(item); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactGroupStrategy.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactGroupStrategy.java new file mode 100644 index 0000000..468b0f9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/ContactGroupStrategy.java @@ -0,0 +1,94 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; + +/** + * 通讯录分组策略 + * Created by huangjun on 2015/2/10. + */ + +public class ContactGroupStrategy implements Comparator { + public static final String GROUP_SHARP = "#"; + + public static final String GROUP_TEAM = "@"; + + public static final String GROUP_NULL = "?"; + + private static final class Group { + private final int order; + + private final String name; + + public Group(int order, String name) { + this.order = order; + this.name = name; + } + } + + private final Map groups = new HashMap(); + + public String belongs(AbsContactItem item) { + return item.belongsGroup(); + } + + protected final void add(String id, int order, String name) { + groups.put(id, new Group(order, name)); + } + + protected final int addABC(int order) { + String id = ContactGroupStrategy.GROUP_SHARP; + + add(id, order++, id); + + for (char i = 0; i < 26; i++) { + id = Character.toString((char) ('A' + i)); + + add(id, order++, id); + } + + return order; + } + + public final String getName(String id) { + Group group = groups.get(id); + String name = group != null ? group.name : null; + return name != null ? name : ""; + } + + private Integer toOrder(String id) { + Group group = groups.get(id); + return group != null ? group.order : null; + } + + @Override + public int compare(String lhs, String rhs) { + if (lhs == null) { + lhs = ContactGroupStrategy.GROUP_NULL; + } + + if (rhs == null) { + rhs = ContactGroupStrategy.GROUP_NULL; + } + + Integer lhsO = toOrder(lhs); + Integer rhsO = toOrder(rhs); + + if (lhsO == rhsO) { + return 0; + } + + if (lhsO == null) { + return -1; + } + + if (rhsO == null) { + return 1; + } + + return lhsO - rhsO; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/IContact.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/IContact.java new file mode 100644 index 0000000..a9de62a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/IContact.java @@ -0,0 +1,48 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +public interface IContact { + + interface Type { + + /** + * TYPE USER + */ + int Friend = 0x1; + + /** + * TYPE TEAM + */ + int Team = 0x2; + + /** + * TYPE TEAM MEMBER + */ + int TeamMember = 0x03; + + /** + * TYPE_MSG + */ + int Msg = 0x04; + } + + /** + * get contact id + * + * @return + */ + String getContactId(); + + /** + * get contact type {@link Type} + * + * @return + */ + int getContactType(); + + /** + * get contact's display name to show to user + * + * @return + */ + String getDisplayName(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/TeamContact.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/TeamContact.java new file mode 100644 index 0000000..ef9425a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/TeamContact.java @@ -0,0 +1,35 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +import android.text.TextUtils; + +import com.netease.nimlib.sdk.team.model.Team; + +public class TeamContact extends AbsContact { + + private Team team; + + public TeamContact(Team team) { + this.team = team; + } + + @Override + public String getContactId() { + return team == null ? "" : team.getId(); + } + + @Override + public int getContactType() { + return Type.Team; + } + + @Override + public String getDisplayName() { + String name = team.getName(); + + return TextUtils.isEmpty(name) ? team.getId() : name; + } + + public Team getTeam() { + return team; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/TeamMemberContact.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/TeamMemberContact.java new file mode 100644 index 0000000..b27019b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/model/TeamMemberContact.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.model; + +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.netease.nimlib.sdk.team.model.TeamMember; + +/** + * Created by huangjun on 2015/5/5. + */ +public class TeamMemberContact extends AbsContact { + + private TeamMember teamMember; + + public TeamMemberContact(TeamMember teamMember) { + this.teamMember = teamMember; + } + + @Override + public String getContactId() { + return teamMember.getAccount(); + } + + @Override + public int getContactType() { + return Type.TeamMember; + } + + @Override + public String getDisplayName() { + return TeamHelper.getTeamMemberDisplayName(teamMember.getTid(), teamMember.getAccount()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/ContactDataProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/ContactDataProvider.java new file mode 100644 index 0000000..9d30865 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/ContactDataProvider.java @@ -0,0 +1,44 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.provider; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ItemTypes; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.IContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; + +import java.util.ArrayList; +import java.util.List; + +public class ContactDataProvider implements IContactDataProvider { + + private int[] itemTypes; + + public ContactDataProvider(int... itemTypes) { + this.itemTypes = itemTypes; + } + + @Override + public List provide(TextQuery query) { + List data = new ArrayList<>(); + + for (int itemType : itemTypes) { + data.addAll(provide(itemType, query)); + } + + return data; + } + + private final List provide(int itemType, TextQuery query) { + switch (itemType) { + case ItemTypes.FRIEND: + return UserDataProvider.provide(query); + case ItemTypes.TEAM: + case ItemTypes.TEAMS.ADVANCED_TEAM: + case ItemTypes.TEAMS.NORMAL_TEAM: + return TeamDataProvider.provide(query, itemType); + case ItemTypes.MSG: + return MsgDataProvider.provide(query); + default: + return new ArrayList<>(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/ContactSearch.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/ContactSearch.java new file mode 100644 index 0000000..c31a298 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/ContactSearch.java @@ -0,0 +1,119 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.provider; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextSearcher; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +public class ContactSearch { + public static final class HitInfo { + public enum Type { + Account, Name, + } + + public final Type type; + + public final String text; + + public final int[] range; + + public HitInfo(Type type, String text, int[] range) { + this.type = type; + this.text = text; + this.range = range; + } + } + + /** + * 判断是否击中 + */ + + static boolean hitUser(UserInfo contact, TextQuery query) { + String account = contact.getAccount(); + String name = UserInfoHelper.getUserName(account); + + return TextSearcher.contains(query.t9, name, query.text) || TextSearcher.contains(query.t9, account, query.text); + } + + static boolean hitFriend(UserInfo contact, TextQuery query) { + String account = contact.getAccount(); + String alias = NimUIKit.getContactProvider().getAlias(account); + + return TextSearcher.contains(query.t9, account, query.text) || TextSearcher.contains(query.t9, alias, query.text); + } + + static boolean hitTeam(Team contact, TextQuery query) { + String name = contact.getName(); + String teamId = contact.getId(); + + return TextSearcher.contains(query.t9, name, query.text) || TextSearcher.contains(query.t9, teamId, query.text); + } + + public static final boolean hitTeamMember(TeamMember teamMember, TextQuery query) { + String name = TeamHelper.getTeamMemberDisplayName(teamMember.getTid(), teamMember.getAccount()); + + return TextSearcher.contains(query.t9, name, query.text); + } + + /** + * 返回击中信息(可进行击中文本高亮显示) + */ + + public static final HitInfo hitInfo(IContact contact, TextQuery query) { + if (contact.getContactType() == IContact.Type.Friend) { + return hitInfoFriend(contact, query); + } else if (contact.getContactType() == IContact.Type.Team) { + return hitInfoTeamContact(contact, query); + } + + return hitInfoContact(contact, query); + } + + public static final HitInfo hitInfoFriend(IContact contact, TextQuery query) { + String name = contact.getDisplayName(); + String account = contact.getContactId(); + + int[] range = TextSearcher.indexOf(query.t9, name, query.text); + + if (range != null) { + return new HitInfo(HitInfo.Type.Name, name, range); + } + + range = TextSearcher.indexOf(query.t9, account, query.text); + + if (range != null) { + return new HitInfo(HitInfo.Type.Account, account, range); + } + + return null; + } + + public static final HitInfo hitInfoTeamContact(IContact contact, TextQuery query) { + String name = contact.getDisplayName(); + + int[] range = TextSearcher.indexOf(query.t9, name, query.text); + + if (range != null) { + return new HitInfo(HitInfo.Type.Name, name, range); + } + + return null; + } + + public static final HitInfo hitInfoContact(IContact contact, TextQuery query) { + String name = contact.getDisplayName(); + + int[] range = TextSearcher.indexOf(query.t9, name, query.text); + + if (range != null) { + return new HitInfo(HitInfo.Type.Name, name, range); + } + + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/MsgDataProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/MsgDataProvider.java new file mode 100644 index 0000000..c2cf793 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/MsgDataProvider.java @@ -0,0 +1,86 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.provider; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.MsgItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.util.ContactHelper; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.lucene.LuceneService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.search.model.MsgIndexRecord; + +import java.util.ArrayList; +import java.util.List; + +/** + * 消息全文检索数据提供者 + */ +public final class MsgDataProvider { + + private static final String TAG = "MsgDataProvider"; + + public static final List provide(TextQuery query) { + if (TextUtils.isEmpty(query.text) || TextUtils.isEmpty(query.text.trim())) { + return new ArrayList<>(0); + } + + // fetch result + List sources; + boolean querySession; + if (query.extra != null) { + SessionTypeEnum sessionType = (SessionTypeEnum) query.extra[0]; + String sessionId = (String) query.extra[1]; + MsgIndexRecord anchor = null; + if (query.extra.length >= 3) { + anchor = (MsgIndexRecord) query.extra[2]; + } + sources = searchSession(query.text, sessionType, sessionId, anchor); + querySession = true; + } else { + sources = searchAllSession(query.text); + querySession = false; + } + + // build AbsContactItem + if (sources == null) { + return new ArrayList<>(0); + } + + List items = new ArrayList<>(sources.size()); + for (MsgIndexRecord r : sources) { + items.add(new MsgItem(ContactHelper.makeContactFromMsgIndexRecord(r), r, querySession)); + } + + return items; + } + + private static List searchSession(String query, SessionTypeEnum sessionType, String sessionId, MsgIndexRecord anchor) { + long startTime = System.currentTimeMillis(); + + List result; + if (anchor != null) { + result = NIMClient.getService(LuceneService.class).searchSessionNextPageBlock(query, sessionType, sessionId, anchor, 50); + } else { + result = NIMClient.getService(LuceneService.class).searchSessionBlock(query, sessionType, sessionId); + } + + log(true, result, System.currentTimeMillis() - startTime); + + return result; + } + + private static List searchAllSession(String query) { + long startTime = System.currentTimeMillis(); + List result = NIMClient.getService(LuceneService.class).searchAllSessionBlock(query, -1); + log(false, result, System.currentTimeMillis() - startTime); + + return result; + } + + private static void log(boolean searchSession, List result, long cost) { + LogUtil.d(TAG, (searchSession ? "search session" : "search all session") + ", result size=" + (result == null ? 0 : result.size()) + ", cost=" + cost); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/TeamDataProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/TeamDataProvider.java new file mode 100644 index 0000000..1cadf84 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/TeamDataProvider.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.provider; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ItemTypes; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactGroupStrategy; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.TeamContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextComparator; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; + +import java.util.ArrayList; +import java.util.List; + +/** + * 群数据源提供者 + *

+ * Created by huangjun on 2015/3/1. + */ +public class TeamDataProvider { + public static final List provide(TextQuery query, int itemType) { + List sources = query(query, itemType); + List items = new ArrayList<>(sources.size()); + for (TeamContact t : sources) { + items.add(createTeamItem(t)); + } + + return items; + } + + private static AbsContactItem createTeamItem(TeamContact team) { + return new ContactItem(team, ItemTypes.TEAM) { + @Override + public int compareTo(ContactItem item) { + return compareTeam((TeamContact) getContact(), (TeamContact) (item.getContact())); + } + + @Override + public String belongsGroup() { + return ContactGroupStrategy.GROUP_TEAM; + } + }; + } + + private static int compareTeam(TeamContact lhs, TeamContact rhs) { + return TextComparator.compareIgnoreCase(lhs.getDisplayName(), rhs.getDisplayName()); + } + + /** + * * 数据查询 + */ + private static final List query(TextQuery query, int itemType) { + List teams; + TeamProvider provider = NimUIKit.getTeamProvider(); + if (itemType == ItemTypes.TEAMS.ADVANCED_TEAM) { + teams = provider.getAllTeamsByType(TeamTypeEnum.Advanced); + } else if (itemType == ItemTypes.TEAMS.NORMAL_TEAM) { + teams = provider.getAllTeamsByType(TeamTypeEnum.Normal); + } else { + teams = provider.getAllTeams(); + } + + List contacts = new ArrayList<>(); + for (Team t : teams) { + if (query == null || ContactSearch.hitTeam(t, query)) { + contacts.add(new TeamContact(t)); + } + } + + return contacts; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/TeamMemberDataProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/TeamMemberDataProvider.java new file mode 100644 index 0000000..1ca157b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/TeamMemberDataProvider.java @@ -0,0 +1,96 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.provider; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ItemTypes; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactGroupStrategy; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.TeamMemberContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextComparator; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.List; + +/** + * 群成员数据源提供者 + *

+ * Created by huangjun on 2015/5/4. + */ +public class TeamMemberDataProvider { + public static final List provide(TextQuery query, String tid) { + List sources = query(query, tid); + List items = new ArrayList<>(sources.size()); + for (TeamMemberContact t : sources) { + items.add(createTeamMemberItem(t)); + } + + return items; + } + + private static AbsContactItem createTeamMemberItem(TeamMemberContact teamMember) { + return new ContactItem(teamMember, ItemTypes.TEAM_MEMBER) { + @Override + public int compareTo(ContactItem item) { + return compareTeamMember((TeamMemberContact) getContact(), (TeamMemberContact) (item.getContact())); + } + + @Override + public String belongsGroup() { + String group = TextComparator.getLeadingUp(getCompare()); + return !TextUtils.isEmpty(group) ? group : ContactGroupStrategy.GROUP_TEAM; + } + + private String getCompare() { + IContact contact = getContact(); + return contact != null ? contact.getDisplayName() : null; + } + }; + } + + private static int compareTeamMember(TeamMemberContact lhs, TeamMemberContact rhs) { + return TextComparator.compareIgnoreCase(lhs.getDisplayName(), rhs.getDisplayName()); + } + + /** + * * 数据查询 + */ + private static final List query(TextQuery query, String tid) { + List teamMembers = NimUIKit.getTeamProvider().getTeamMemberList(tid); + + List contacts = new ArrayList<>(); + for (TeamMember t : teamMembers) { + if (t != null && (query == null || ContactSearch.hitTeamMember(t, query))) { + contacts.add(new TeamMemberContact(t)); + } + } + + return contacts; + } + + /** + * 发起异步任务load群成员进入缓存 + * + * @param tid + * @param callback + */ + public static void loadTeamMemberDataAsync(String tid, final LoadTeamMemberCallback callback) { + NimUIKit.getTeamProvider().fetchTeamMemberList(tid, new SimpleCallback>() { + @Override + public void onResult(boolean success, List result, int code) { + if (callback != null) { + callback.onResult(success); + } + } + }); + } + + public interface LoadTeamMemberCallback { + void onResult(boolean success); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/UserDataProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/UserDataProvider.java new file mode 100644 index 0000000..a1ee657 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/provider/UserDataProvider.java @@ -0,0 +1,47 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.provider; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ItemTypes; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.util.ContactHelper; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.impl.cache.UIKitLogTag; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +final class UserDataProvider { + public static List provide(TextQuery query) { + List sources = query(query); + List items = new ArrayList<>(sources.size()); + for (UserInfo u : sources) { + items.add(new ContactItem(ContactHelper.makeContactFromUserInfo(u), ItemTypes.FRIEND)); + } + + LogUtil.i(UIKitLogTag.CONTACT, "contact provide data size =" + items.size()); + return items; + } + + private static final List query(TextQuery query) { + + List friends = NimUIKit.getContactProvider().getUserInfoOfMyFriends(); + List users = NimUIKit.getUserInfoProvider().getUserInfo(friends); + if (query == null) { + return users; + } + + UserInfo user; + for (Iterator iter = users.iterator(); iter.hasNext(); ) { + user = iter.next(); + boolean hit = ContactSearch.hitUser(user, query) || (ContactSearch.hitFriend(user, query)); + if (!hit) { + iter.remove(); + } + } + return users; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/IContactDataProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/IContactDataProvider.java new file mode 100644 index 0000000..28d2d56 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/IContactDataProvider.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.query; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; + +import java.util.List; + +/** + * 通讯录数据源提供者接口 + * Created by huangjun on 2015/4/2. + */ +public interface IContactDataProvider { + public List provide(TextQuery query); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/PinYin.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/PinYin.java new file mode 100644 index 0000000..0822c0c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/PinYin.java @@ -0,0 +1,532 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.query; + +import android.content.Context; +import android.text.TextUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class PinYin { + private static final String ASSET = "pinyin/index.dat"; + + private static final char START = 0x4e00; + + private static final char END = 0x9fa5; + + private static final String[] pinyin = {"a", "ai", "an", "ang", "ao", + "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", + "bian", "biao", "bie", "bin", "bing", "bo", "bu", "ca", "cai", + "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan", "chang", + "chao", "che", "chen", "cheng", "chi", "chong", "chou", "chu", + "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong", + "cou", "cu", "cuan", "cui", "cun", "cuo", "da", "dai", "dan", + "dang", "dao", "de", "deng", "di", "dian", "diao", "die", "ding", + "diu", "dong", "dou", "du", "duan", "dui", "dun", "duo", "e", "en", + "er", "fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu", + "ga", "gai", "gan", "gang", "gao", "ge", "gei", "gen", "geng", + "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun", + "guo", "ha", "hai", "han", "hang", "hao", "he", "hei", "hen", + "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", + "hun", "huo", "ji", "jia", "jian", "jiang", "jiao", "jie", "jin", + "jing", "jiong", "jiu", "ju", "juan", "jue", "jun", "ka", "kai", + "kan", "kang", "kao", "ke", "ken", "keng", "kong", "kou", "ku", + "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai", + "lan", "lang", "lao", "le", "lei", "leng", "li", "lia", "lian", + "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu", + "lv", "luan", "lue", "lun", "luo", "ma", "mai", "man", "mang", + "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", + "min", "ming", "miu", "mo", "mou", "mu", "na", "nai", "nan", + "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang", + "niao", "nie", "nin", "ning", "niu", "nong", "nu", "nv", "nuan", + "nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei", + "pen", "peng", "pi", "pian", "piao", "pie", "pin", "ping", "po", + "pu", "qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing", + "qiong", "qiu", "qu", "quan", "que", "qun", "ran", "rang", "rao", + "re", "ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", + "run", "ruo", "sa", "sai", "san", "sang", "sao", "se", "sen", + "seng", "sha", "shai", "shan", "shang", "shao", "she", "shen", + "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan", "shuang", + "shui", "shun", "shuo", "si", "song", "sou", "su", "suan", "sui", + "sun", "suo", "ta", "tai", "tan", "tang", "tao", "te", "teng", + "ti", "tian", "tiao", "tie", "ting", "tong", "tou", "tu", "tuan", + "tui", "tun", "tuo", "wa", "wai", "wan", "wang", "wei", "wen", + "weng", "wo", "wu", "xi", "xia", "xian", "xiang", "xiao", "xie", + "xin", "xing", "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", + "yan", "yang", "yao", "ye", "yi", "yin", "ying", "yo", "yong", + "you", "yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang", + "zao", "ze", "zei", "zen", "zeng", "zha", "zhai", "zhan", "zhang", + "zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", + "zhua", "zhuai", "zhuan", "zhuang", "zhui", "zhun", "zhuo", "zi", + "zong", "zou", "zu", "zuan", "zui", "zun", "zuo"}; + + private static final String[] pinyinT9 = {"2", "24", "26", "264", "26", + "22", "224", "226", "2264", "226", "234", "236", "2364", "24", + "2426", "2426", "243", "246", "2464", "26", "28", "22", "224", + "226", "2264", "226", "23", "2364", "242", "2424", "2426", "24264", + "2426", "243", "2436", "24364", "244", "24664", "2468", "248", + "24824", "24826", "248264", "2484", "2486", "2486", "24", "2664", + "268", "28", "2826", "284", "286", "286", "32", "324", "326", + "3264", "326", "33", "3364", "34", "3426", "3426", "343", "3464", + "348", "3664", "368", "38", "3826", "384", "386", "386", "3", "36", + "37", "32", "326", "3264", "334", "336", "3364", "36", "368", "38", + "42", "424", "426", "4264", "426", "43", "434", "436", "4364", + "4664", "468", "48", "482", "4824", "4826", "48264", "484", "486", + "486", "42", "424", "426", "4264", "426", "43", "434", "436", + "4364", "4664", "468", "48", "482", "4824", "4826", "48264", "484", + "486", "486", "54", "542", "5426", "54264", "5426", "543", "546", + "5464", "54664", "548", "58", "5826", "583", "586", "52", "524", + "526", "5264", "526", "53", "536", "5364", "5664", "568", "58", + "582", "5824", "5826", "58264", "584", "586", "586", "52", "524", + "526", "5264", "526", "53", "534", "5364", "54", "542", "5426", + "54264", "5426", "543", "546", "5464", "548", "5664", "568", "58", + "58", "5826", "583", "586", "586", "62", "624", "626", "6264", + "626", "63", "634", "636", "6364", "64", "6426", "6426", "643", + "646", "6464", "648", "66", "668", "68", "62", "624", "626", + "6264", "626", "63", "634", "636", "6364", "64", "6426", "64264", + "6426", "643", "646", "6464", "648", "6664", "68", "68", "6826", + "683", "686", "6", "68", "72", "724", "726", "7264", "726", "734", + "736", "7364", "74", "7426", "7426", "743", "746", "7464", "76", + "78", "74", "742", "7426", "74264", "7426", "743", "746", "7464", + "74664", "748", "78", "7826", "783", "786", "726", "7264", "726", + "73", "736", "7364", "74", "7664", "768", "78", "7826", "784", + "786", "786", "72", "724", "726", "7264", "726", "73", "736", + "7364", "742", "7424", "7426", "74264", "7426", "743", "7436", + "74364", "744", "7468", "748", "7482", "74824", "74826", "748264", + "7484", "7486", "7486", "74", "7664", "768", "78", "7826", "784", + "786", "786", "82", "824", "826", "8264", "826", "83", "8364", + "84", "8426", "8426", "843", "8464", "8664", "868", "88", "8826", + "884", "886", "886", "92", "924", "926", "9264", "934", "936", + "9364", "96", "98", "94", "942", "9426", "94264", "9426", "943", + "946", "9464", "94664", "948", "98", "9826", "983", "986", "92", + "926", "9264", "926", "93", "94", "946", "9464", "96", "9664", + "968", "98", "9826", "983", "986", "92", "924", "926", "9264", + "926", "93", "934", "936", "9364", "942", "9424", "9426", "94264", + "9426", "943", "9436", "94364", "944", "94664", "9468", "948", + "9482", "94824", "94826", "948264", "9484", "9486", "9486", "94", + "9664", "968", "98", "9826", "984", "986", "986"}; + + private static final char[] leadingCUp = new char[]{'A', 'A', 'A', 'A', 'A', + 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', + 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', + 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', + 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'D', 'D', 'D', + 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', + 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'F', 'F', 'F', 'F', 'F', 'F', + 'F', 'F', 'F', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', + 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'H', 'H', 'H', 'H', + 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', + 'H', 'H', 'J', 'J', 'J', 'J', 'J', 'J', 'J', 'J', 'J', 'J', 'J', + 'J', 'J', 'J', 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'K', + 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'M', 'M', 'M', 'M', 'M', 'M', + 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', + 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', + 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'O', 'O', 'P', + 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', + 'P', 'P', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', + 'Q', 'Q', 'Q', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', + 'R', 'R', 'R', 'R', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', + 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', + 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'T', + 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', + 'T', 'T', 'T', 'T', 'T', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', + 'W', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', + 'X', 'X', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', + 'Y', 'Y', 'Y', 'Y', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', + 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', + 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', + 'Z'}; + + private static final char[] leadingCLo = new char[]{'a', 'a', 'a', 'a', + 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', + 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', + 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', + 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'd', 'd', + 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', + 'd', 'd', 'd', 'd', 'd', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'f', + 'f', 'f', 'f', 'f', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', + 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'h', 'h', 'h', + 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', + 'h', 'h', 'h', 'j', 'j', 'j', 'j', 'j', 'j', 'j', 'j', 'j', 'j', + 'j', 'j', 'j', 'j', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', + 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'l', 'l', 'l', 'l', + 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'l', + 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'l', 'm', 'm', 'm', 'm', 'm', + 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', + 'm', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', + 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'o', 'o', + 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', + 'p', 'p', 'p', 'q', 'q', 'q', 'q', 'q', 'q', 'q', 'q', 'q', 'q', + 'q', 'q', 'q', 'q', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', + 'r', 'r', 'r', 'r', 'r', 's', 's', 's', 's', 's', 's', 's', 's', + 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', + 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', + 't', 't', 't', 't', 't', 't', 't', 't', 't', 't', 't', 't', 't', + 't', 't', 't', 't', 't', 't', 'w', 'w', 'w', 'w', 'w', 'w', 'w', + 'w', 'w', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', + 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', + 'y', 'y', 'y', 'y', 'y', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', + 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', + 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', + 'z', 'z',}; + + private static final String[] leadingSUp = new String[]{"A", "A", "A", + "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", + "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C", "C", "C", + "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", + "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "D", + "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", + "D", "D", "D", "D", "D", "D", "E", "E", "E", "F", "F", "F", "F", + "F", "F", "F", "F", "F", "G", "G", "G", "G", "G", "G", "G", "G", + "G", "G", "G", "G", "G", "G", "G", "G", "G", "G", "G", "H", "H", + "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", + "H", "H", "H", "H", "J", "J", "J", "J", "J", "J", "J", "J", "J", + "J", "J", "J", "J", "J", "K", "K", "K", "K", "K", "K", "K", "K", + "K", "K", "K", "K", "K", "K", "K", "K", "K", "K", "L", "L", "L", + "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", + "L", "L", "L", "L", "L", "L", "L", "L", "L", "M", "M", "M", "M", + "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", + "M", "M", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", + "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "O", + "O", "P", "P", "P", "P", "P", "P", "P", "P", "P", "P", "P", "P", + "P", "P", "P", "P", "Q", "Q", "Q", "Q", "Q", "Q", "Q", "Q", "Q", + "Q", "Q", "Q", "Q", "Q", "R", "R", "R", "R", "R", "R", "R", "R", + "R", "R", "R", "R", "R", "R", "S", "S", "S", "S", "S", "S", "S", + "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", + "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", + "S", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", + "T", "T", "T", "T", "T", "T", "T", "W", "W", "W", "W", "W", "W", + "W", "W", "W", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", + "X", "X", "X", "X", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", + "Y", "Y", "Y", "Y", "Y", "Y", "Z", "Z", "Z", "Z", "Z", "Z", "Z", + "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", + "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", + "Z", "Z", "Z"}; + + private static final String[] leadingSLo = new String[]{"a", "a", "a", + "a", "a", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", + "b", "b", "b", "b", "b", "c", "c", "c", "c", "c", "c", "c", "c", + "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", + "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "d", + "d", "d", "d", "d", "d", "d", "d", "d", "d", "d", "d", "d", "d", + "d", "d", "d", "d", "d", "d", "e", "e", "e", "f", "f", "f", "f", + "f", "f", "f", "f", "f", "g", "g", "g", "g", "g", "g", "g", "g", + "g", "g", "g", "g", "g", "g", "g", "g", "g", "g", "g", "h", "h", + "h", "h", "h", "h", "h", "h", "h", "h", "h", "h", "h", "h", "h", + "h", "h", "h", "h", "j", "j", "j", "j", "j", "j", "j", "j", "j", + "j", "j", "j", "j", "j", "k", "k", "k", "k", "k", "k", "k", "k", + "k", "k", "k", "k", "k", "k", "k", "k", "k", "k", "l", "l", "l", + "l", "l", "l", "l", "l", "l", "l", "l", "l", "l", "l", "l", "l", + "l", "l", "l", "l", "l", "l", "l", "l", "l", "m", "m", "m", "m", + "m", "m", "m", "m", "m", "m", "m", "m", "m", "m", "m", "m", "m", + "m", "m", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", + "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "o", + "o", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", + "p", "p", "p", "p", "q", "q", "q", "q", "q", "q", "q", "q", "q", + "q", "q", "q", "q", "q", "r", "r", "r", "r", "r", "r", "r", "r", + "r", "r", "r", "r", "r", "r", "s", "s", "s", "s", "s", "s", "s", + "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", + "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", "s", + "s", "t", "t", "t", "t", "t", "t", "t", "t", "t", "t", "t", "t", + "t", "t", "t", "t", "t", "t", "t", "w", "w", "w", "w", "w", "w", + "w", "w", "w", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", + "x", "x", "x", "x", "y", "y", "y", "y", "y", "y", "y", "y", "y", + "y", "y", "y", "y", "y", "y", "z", "z", "z", "z", "z", "z", "z", + "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", + "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", + "z", "z", "z",}; + + private static Context context; + + private static byte[] indexes; + + private static final Object lock = new Object(); + + private static byte[] loadIndexes(Context context) { + byte[] indexes = null; + + InputStream is = null; + try { + is = context.getAssets().open(ASSET); + + indexes = new byte[(END - START + 1) * 2]; + + is.read(indexes); + } catch (Throwable tr) { + tr.printStackTrace(); + + indexes = null; + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return indexes; + } + + private static void ensureIndexes() { + if (indexes != null) { + return; + } + + // + // usually not reach + // + + byte[] tIndexes = null; + + // protect + synchronized (lock) { + if (context != null) { + tIndexes = loadIndexes(context); + if (tIndexes != null) { + context = null; + } + } + } + + // may race + if (tIndexes != null) { + indexes = tIndexes; + } + } + + public static final void init(Context ctx) { + context = ctx.getApplicationContext(); + } + + public static final String validate() { + ensureIndexes(); + + StringBuilder invalid = new StringBuilder(); + StringBuilder miss = new StringBuilder(); + + for (char c = START; c <= END; c++) { + // offset + int offset = (c - START) * 2; + + // raw + int raw = indexes[offset] << 8 | 0xff & indexes[offset + 1]; + + if (raw < 0 || raw > pinyin.length) { + invalid.append(c); + } + + if (raw == 0) { + miss.append(c); + } + } + + boolean t9 = validatePinYinT9(); + + String result = "pinyin(" + pinyin.length + ") " + + "pinyinT9(" + t9 + ") " + + "leadingCUp(" + leadingCUp.length + ") " + + "leadingCLo(" + leadingCLo.length + ") " + + "leadingSUp(" + leadingSUp.length + ") " + + "leadingSLo(" + leadingSLo.length + ") " + + "invalid(" + invalid.toString() + ") " + + "miss(" + miss.toString() + ") "; + + return result; + } + + private static final char[] T9 = {'2', '2', '2', '3', '3', '3', '4', '4', + '4', '5', '5', '5', '6', '6', '6', '7', '7', '7', '7', '8', '8', + '8', '9', '9', '9', '9'}; + + private static final boolean validatePinYinT9() { + if (pinyin.length != pinyinT9.length) { + return false; + } + + for (int i = 0; i < pinyin.length; i++) { + String p = pinyin[i]; + String t = pinyinT9[i]; + + if (p.length() != t.length()) { + return false; + } + + for (int j = 0; j < p.length(); j++) { + if (T9[p.charAt(j) - 'a'] != t.charAt(j)) { + return false; + } + } + } + + return true; + } + + public static final int getIndex(char c) { + ensureIndexes(); + + if (indexes == null) { + return -1; + } + + // out of bound + if (c < START || c > END) { + return -1; + } + + // offset + int offset = (c - START) * 2; + + // raw + int raw = indexes[offset] << 8 | 0xff & indexes[offset + 1]; + + return raw - 1; + } + + public static final char getLeadingUp(char c, char d) { + int index = getIndex(c); + + return index != -1 ? leadingCUp[index] : d; + } + + public static final char getLeadingLo(char c, char d) { + int index = getIndex(c); + + return index != -1 ? leadingCLo[index] : d; + } + + public static final String getLeadingUp(char c) { + int index = getIndex(c); + + return index != -1 ? leadingSUp[index] : null; + } + + public static final String getLeadingLo(char c) { + int index = getIndex(c); + + return index != -1 ? leadingSLo[index] : null; + } + + public static final String getLeadingUp(String text) { + if (TextUtils.isEmpty(text)) { + return null; + } + + StringBuilder leadings = new StringBuilder(); + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + + int index = getIndex(c); + + if (index != -1) { + leadings.append(leadingCUp[index]); + } else { + leadings.append(c); + } + } + + return leadings.toString(); + } + + public static final String getLeadingLo(String text) { + if (TextUtils.isEmpty(text)) { + return null; + } + + StringBuilder leadings = new StringBuilder(); + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + + int index = getIndex(c); + + if (index != -1) { + leadings.append(leadingCLo[index]); + } else { + leadings.append(c); + } + } + + return leadings.toString(); + } + + public static final String getPinYin(char c) { + int index = getIndex(c); + + return index != -1 ? pinyin[index] : null; + } + + public static final String getPinYinT9(char c) { + int index = getIndex(c); + + return index != -1 ? pinyinT9[index] : null; + } + + public static final String getPinYin(String text) { + if (TextUtils.isEmpty(text)) { + return null; + } + + StringBuilder pinyins = new StringBuilder(); + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + + int index = getIndex(c); + + if (index != -1) { + pinyins.append(pinyin[index]); + } else { + pinyins.append(c); + } + } + + return pinyins.toString(); + } + + public static final String[] getPinYins(String text) { + if (TextUtils.isEmpty(text)) { + return null; + } + + StringBuilder pinyins = new StringBuilder(); + StringBuilder leadings = new StringBuilder(); + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + + int index = getIndex(c); + + if (index != -1) { + pinyins.append(pinyin[index]); + leadings.append(leadingCLo[index]); + } else { + pinyins.append(c); + leadings.append(c); + } + } + + String[] result = new String[]{pinyins.toString(), leadings.toString()}; + + return result; + } + + public static final List getPinYins(List texts) { + if (texts == null) { + return null; + } + + List results = new ArrayList(texts.size()); + + for (String text : texts) { + results.add(getPinYins(text)); + } + + return results; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/SimpleT9Matcher.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/SimpleT9Matcher.java new file mode 100644 index 0000000..76bbb57 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/SimpleT9Matcher.java @@ -0,0 +1,52 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.query; + +public class SimpleT9Matcher { + + private static final char[] LATIN_LETTERS_TO_DIGITS = { + '2', '2', '2', // A,B,C -> 2 + '3', '3', '3', // D,E,F -> 3 + '4', '4', '4', // G,H,I -> 4 + '5', '5', '5', // J,K,L -> 5 + '6', '6', '6', // M,N,O -> 6 + '7', '7', '7', '7', // P,Q,R,S -> 7 + '8', '8', '8', // T,U,V -> 8 + '9', '9', '9', '9' // W,X,Y,Z -> 9 + }; + + private static boolean isAlphaNumberString(String name) { + return name.matches("[0-9a-zA-Z]+"); + } + + private static char getDialpadNumericCharacter(char ch) { + if (ch >= 'A' && ch <= 'Z') { + ch = (char) (ch + ('a' - 'A')); + } + if (ch >= 'a' && ch <= 'z') { + return LATIN_LETTERS_TO_DIGITS[ch - 'a']; + } + return ch; + } + + /** + * 将仅包含数字和字母的字符串转化为数字串(对应T9) + * + * @param name + * @return + */ + private static String alphaNumberStringToNumbericString(String name) { + if (isAlphaNumberString(name)) { + final int length = name.length(); + StringBuilder builder = new StringBuilder(); + for (int index = 0; index < length; index++) { + builder.append(getDialpadNumericCharacter(name.charAt(index))); + } + return builder.toString(); + } + return ""; + } + + public static boolean hit(String text, String query) { + return alphaNumberStringToNumbericString(text).contains(query); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextComparator.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextComparator.java new file mode 100644 index 0000000..1e6fcef --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextComparator.java @@ -0,0 +1,221 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.query; + +import android.text.TextUtils; + +public class TextComparator { + public static final int compare(String a, String b) { + if (a == b) { + return 0; + } + + if (a == null) { + return -1; + } + + if (b == null) { + return 1; + } + + for (int index = 0; index < a.length() && index < b.length(); index++) { + int compare = compare(a.charAt(index), b.charAt(index)); + if (compare != 0) { + return compare; + } + } + + return a.length() - b.length(); + } + + public static final int compareIgnoreCase(String a, String b) { + if (a == b) { + return 0; + } + + if (a == null) { + return -1; + } + + if (b == null) { + return 1; + } + + for (int index = 0; index < a.length() && index < b.length(); index++) { + int compare = compareIgnoreCase(a.charAt(index), b.charAt(index)); + if (compare != 0) { + return compare; + } + } + + return a.length() - b.length(); + } + + public static final int compare(char a, char b) { + if (a == b) { + return 0; + } + + { + int ai = getAsciiIndex(a, false); + int bi = getAsciiIndex(b, false); + + if (ai != bi) { + if (ai == -1) { + return 1; + } else if (bi == -1) { + return -1; + } else { + return ai - bi; + } + } else { + if (ai != -1) { + return 0; + } + } + } + + { + int ai = PinYin.getIndex(a); + int bi = PinYin.getIndex(b); + + if (ai != bi) { + if (ai == -1) { + return 1; + } else if (bi == -1) { + return -1; + } else { + return ai - bi; + } + } + } + + return a - b; + } + + public static final int compareIgnoreCase(char a, char b) { + if (a == b) { + return 0; + } + + { + int ai = getAsciiIndex(a, true); + int bi = getAsciiIndex(b, true); + + if (ai != bi) { + if (ai == -1) { + return 1; + } else if (bi == -1) { + return -1; + } else { + return ai - bi; + } + } else { + if (ai != -1) { + return 0; + } + } + } + + { + int ai = PinYin.getIndex(a); + int bi = PinYin.getIndex(b); + + if (ai != bi) { + if (ai == -1) { + return 1; + } else if (bi == -1) { + return -1; + } else { + return ai - bi; + } + } + } + + return a - b; + } + + public static final String getLeadingUp(String s) { + if (TextUtils.isEmpty(s)) { + return null; + } + + char c = s.charAt(0); + + String leading = getAsciiLeadingUp(c); + if (leading == null) { + leading = PinYin.getLeadingUp(c); + } + + return leading; + } + + public static final String getLeadingLo(String s) { + if (TextUtils.isEmpty(s)) { + return null; + } + + char c = s.charAt(0); + + String leading = getAsciiLeadingLo(c); + if (leading == null) { + leading = PinYin.getLeadingLo(c); + } + + return leading; + } + + private static int getAsciiIndex(char c, boolean ignoreCase) { + // 0-9 0x0 + if (c >= 0x30 && c <= 0x39) { + return c - 0x30 + 0; + } + + // a-z 0xA + if (c >= 0x61 && c <= 0x7A) { + return c - 0x61 + 0xA; + } + + // A-Z 0x24 + if (c >= 0x41 && c <= 0x5A) { + return c - 0x41 + (ignoreCase ? 0xA : 0x24); + } + + return -1; + } + + private static final String[] leadingUp = new String[]{"A", "B", "C", "D", "E", + "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", + "S", "T", "U", "V", "W", "X", "Y", "Z" + }; + + private static final String[] leadingLo = new String[]{"a", "b", "c", + "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", + "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}; + + private static String getAsciiLeadingUp(char c) { + // a-z 0xA + if (c >= 0x61 && c <= 0x7A) { + return leadingUp[c - 0x61]; + } + + // A-Z 0x24 + if (c >= 0x41 && c <= 0x5A) { + return leadingUp[c - 0x41]; + } + + return null; + } + + private static String getAsciiLeadingLo(char c) { + // a-z 0xA + if (c >= 0x61 && c <= 0x7A) { + return leadingLo[c - 0x61]; + } + + // A-Z 0x24 + if (c >= 0x41 && c <= 0x5A) { + return leadingLo[c - 0x41]; + } + + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextQuery.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextQuery.java new file mode 100644 index 0000000..3e70325 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextQuery.java @@ -0,0 +1,56 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.query; + +import android.annotation.SuppressLint; +import android.text.TextUtils; + +@SuppressLint("DefaultLocale") +public final class TextQuery { + public final String text; + + public final boolean t9; + + public boolean digit; + + public boolean letter; + + public boolean pinyin; + + public Object[] extra; + + public TextQuery(String text) { + this(text, false); + } + + public TextQuery(String text, boolean t9) { + this.text = !TextUtils.isEmpty(text) ? text.toLowerCase() : text; + this.t9 = t9; + + init(); + } + + private void init() { + if (TextUtils.isEmpty(text)) { + return; + } + + int digits = 0; + int letters = 0; + int pinyins = 0; + + for (int i = 0; i < text.length(); i++) { + char chr = text.charAt(i); + + if ('0' <= chr && chr <= '9') { + digits++; + } else if ('a' <= chr && chr <= 'z') { + letters++; + } else if (PinYin.getIndex(chr) != -1) { + pinyins++; + } + } + + digit = digits == text.length(); + letter = letters == text.length(); + pinyin = pinyins == text.length(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextSearcher.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextSearcher.java new file mode 100644 index 0000000..6f0e2bf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/query/TextSearcher.java @@ -0,0 +1,300 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.query; + +import android.text.TextUtils; + +public final class TextSearcher { + /** + * T9 + */ + private boolean mT9; + + /** + * string + */ + private String mStr; + + // + // string state + // + + /** + * string index + */ + private int mIndex; + + /** + * eaten state + */ + private boolean mEaten; + + // + // PinYin state + // + + /** + * PinYin + */ + private String mPinyin; + + /** + * string index after PinYin + */ + private int mIndexP; + + /** + * PinYin sub index + */ + private int mIndexSub; + + /** + * T9 characters + */ + private static final char[] T9 = {'2', '2', '2', '3', '3', '3', '4', '4', + '4', '5', '5', '5', '6', '6', '6', '7', '7', '7', '7', '8', '8', + '8', '9', '9', '9', '9'}; + + /** + * searcher + */ + private static final ThreadLocal sSearcher = new ThreadLocal() { + protected TextSearcher initialValue() { + return new TextSearcher(); + } + }; + + /** + * @param t9 + * @return TextSearcher + */ + public static final TextSearcher obtain(boolean t9) { + TextSearcher searcher = sSearcher.get(); + + searcher.mT9 = t9; + + return searcher; + } + + /** + * @param s + * @param i + */ + public final void initialize(String s, int i) { + mStr = s; + + mIndex = i; + mEaten = true; + + mPinyin = null; + mIndexP = -1; + mIndexSub = -1; + } + + /** + * @return last index + */ + public final int index() { + return mIndex; + } + + /** + * @param eat assuming in lower case or [0-9] + * @return eaten + */ + public final boolean eat(char eat) { + // + // PinYin + // + + boolean pEaten = false; + boolean pEnd = false; + + // on + if (mPinyin != null) { + // compare then move + pEaten = mPinyin.charAt(mIndexSub++) == eat; + pEnd = mIndexSub == mPinyin.length(); + + // not eaten or reach the end + if (!pEaten || pEnd) { + // close + mPinyin = null; + } + } + + // + // string + // + + String pinyin = null; + boolean eaten = false; + + // on && in bound + if (mEaten && mIndex < mStr.length()) { + char chr = mStr.charAt(mIndex); + + if (mT9) { + if ('a' <= chr && chr <= 'z') { + eaten = T9[chr - 'a'] == eat; + } else if ('A' <= chr && chr <= 'Z') { + eaten = T9[chr - 'A'] == eat; + } else { + eaten = chr == eat; + } + } else { + if ('A' <= chr && chr <= 'Z') { + eaten = chr + 'a' - 'A' == eat; + } else { + eaten = chr == eat; + } + } + + // PinYin + if (!eaten) { + pinyin = mT9 ? PinYin.getPinYinT9(chr) : PinYin.getPinYin(chr); + + // has + if (pinyin != null) { + // equals + if (pinyin.charAt(0) == eat) { + eaten = true; + } else { + // clear + pinyin = null; + } + } + } + } + + // fail + if (!pEaten && !eaten) { + return false; + } + + // string + if (eaten) { + // next + mIndex++; + + // PinYin fail + if (!pEaten) { + // clear + mPinyin = null; + + // setup + if (pinyin != null && pinyin.length() > 1) { + mPinyin = pinyin; + // first has done + mIndexSub = 1; + + // at next + mIndexP = mIndex; + } + } + } else { + // + // PinYin here + // + + // reach the end + if (pEnd) { + // previous index done + eaten = true; + mIndex = mIndexP; + } + } + + // save last + mEaten = eaten; + + return true; + } + + /** + * @param t9 + * @param str + * @param query assuming in lower case or [0-9] + * @return range array or NULL + */ + public static final int[] indexOf(boolean t9, String str, String query) { + if (TextUtils.isEmpty(str) || TextUtils.isEmpty(query)) { + return null; + } + + TextSearcher searcher = TextSearcher.obtain(t9); + + // move + EAT: + for (int index = 0; index < str.length(); index++) { + searcher.initialize(str, index); + + for (int subIndex = 0; subIndex < query.length(); subIndex++) { + if (!searcher.eat(query.charAt(subIndex))) { + // next + continue EAT; + } + } + + // eaten + return new int[]{index, searcher.index()}; + } + + return null; + } + + /** + * @param t9 + * @param str + * @param query assuming in lower case or [0-9] + * @return contains + */ + public static final boolean contains(boolean t9, String str, String query) { + if (TextUtils.isEmpty(str) || TextUtils.isEmpty(query)) { + return false; + } + + TextSearcher searcher = TextSearcher.obtain(t9); + + // move + EAT: + for (int index = 0; index < str.length(); index++) { + searcher.initialize(str, index); + + for (int subIndex = 0; subIndex < query.length(); subIndex++) { + if (!searcher.eat(query.charAt(subIndex))) { + // next + continue EAT; + } + } + + // eaten + return true; + } + + return false; + } + + /** + * @param t9 + * @param str + * @param query assuming in lower case or [0-9] + * @return last index or -1 + */ + public static final int startsWith(boolean t9, String str, String query) { + if (TextUtils.isEmpty(str) || TextUtils.isEmpty(query)) { + return -1; + } + + TextSearcher searcher = TextSearcher.obtain(t9); + + searcher.initialize(str, 0); + + for (int subIndex = 0; subIndex < query.length(); subIndex++) { + if (!searcher.eat(query.charAt(subIndex))) { + // fail + return -1; + } + } + + return searcher.index(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/util/ContactHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/util/ContactHelper.java new file mode 100644 index 0000000..bb9ee9a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/util/ContactHelper.java @@ -0,0 +1,60 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.util; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.search.model.MsgIndexRecord; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +/** + * Created by huangjun on 2015/9/8. + */ +public class ContactHelper { + public static IContact makeContactFromUserInfo(final UserInfo userInfo) { + return new IContact() { + @Override + public String getContactId() { + return userInfo.getAccount(); + } + + @Override + public int getContactType() { + return Type.Friend; + } + + @Override + public String getDisplayName() { + return UserInfoHelper.getUserDisplayName(userInfo.getAccount()); + } + }; + } + + public static IContact makeContactFromMsgIndexRecord(final MsgIndexRecord record) { + return new IContact() { + @Override + public String getContactId() { + return record.getSessionId(); + } + + @Override + public int getContactType() { + return Type.Msg; + } + + @Override + public String getDisplayName() { + String sessionId = record.getSessionId(); + SessionTypeEnum sessionType = record.getSessionType(); + + if (sessionType == SessionTypeEnum.P2P) { + return UserInfoHelper.getUserDisplayName(sessionId); + } else if (sessionType == SessionTypeEnum.Team) { + return TeamHelper.getTeamName(sessionId); + } + + return ""; + } + }; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/AbsContactViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/AbsContactViewHolder.java new file mode 100644 index 0000000..cd936f4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/AbsContactViewHolder.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; + +public abstract class AbsContactViewHolder { + protected View view; + + protected Context context; + + public AbsContactViewHolder() { + + } + + public abstract void refresh(ContactDataAdapter adapter, int position, T item); + + public abstract View inflate(LayoutInflater inflater); + + public final View getView() { + return view; + } + + public void create(Context context) { + this.context = context; + this.view = inflate(LayoutInflater.from(context)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/ContactHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/ContactHolder.java new file mode 100644 index 0000000..18e3de2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/ContactHolder.java @@ -0,0 +1,73 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.team.model.Team; + +public class ContactHolder extends AbsContactViewHolder { + + protected HeadImageView head; + + protected TextView name; + + protected TextView desc; + + protected RelativeLayout headLayout; + + @Override + public void refresh(ContactDataAdapter adapter, int position, final ContactItem item) { + // contact info + final IContact contact = item.getContact(); + if (contact.getContactType() == IContact.Type.Friend) { + head.loadBuddyAvatar(contact.getContactId()); + } else { + Team team = NimUIKit.getTeamProvider().getTeamById(contact.getContactId()); + head.loadTeamIconByTeam(team); + } + name.setText(contact.getDisplayName()); + headLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (contact.getContactType() == IContact.Type.Friend) { + if (NimUIKitImpl.getContactEventListener() != null) { + NimUIKitImpl.getContactEventListener().onAvatarClick(context, item.getContact().getContactId()); + } + } + } + }); + + // query result + desc.setVisibility(View.GONE); + /* + TextQuery query = adapter.getQuery(); + HitInfo hitInfo = query != null ? ContactSearch.hitInfo(contact, query) : null; + if (hitInfo != null && !hitInfo.text.equals(contact.getDisplayName())) { + desc.setVisibility(View.VISIBLE); + } else { + desc.setVisibility(View.GONE); + } + */ + } + + @Override + public View inflate(LayoutInflater inflater) { + View view = inflater.inflate(R.layout.nim_contacts_item, null); + + headLayout = (RelativeLayout) view.findViewById(R.id.head_layout); + head = (HeadImageView) view.findViewById(R.id.contacts_item_head); + name = (TextView) view.findViewById(R.id.contacts_item_name); + desc = (TextView) view.findViewById(R.id.contacts_item_desc); + + return view; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/LabelHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/LabelHolder.java new file mode 100644 index 0000000..a739555 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/LabelHolder.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.LabelItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.netease.nim.uikit.R; + +public class LabelHolder extends AbsContactViewHolder { + + private TextView name; + + @Override + public void refresh(ContactDataAdapter contactAdapter, int position, LabelItem item) { + this.name.setText(item.getText()); + } + + @Override + public View inflate(LayoutInflater inflater) { + View view = inflater.inflate(R.layout.nim_contacts_abc_item, null); + this.name = view.findViewById(R.id.tv_nickname); + return view; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/MsgHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/MsgHolder.java new file mode 100644 index 0000000..dcf824b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/MsgHolder.java @@ -0,0 +1,180 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder; + +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.MsgItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.search.model.MsgIndexRecord; +import com.netease.nimlib.sdk.search.model.RecordHitInfo; +import com.netease.nimlib.sdk.team.model.Team; + +import java.util.List; + +public class MsgHolder extends AbsContactViewHolder { + + private static final String PREFIX = "..."; + + protected HeadImageView head; + + protected TextView name; + + protected TextView time; + + protected TextView desc; + + protected int descTextViewWidth; // 当前ViewHolder desc TextView 最大的宽度px + + @Override + public View inflate(LayoutInflater inflater) { + View view = inflater.inflate(R.layout.nim_contacts_item, null); + + head = (HeadImageView) view.findViewById(R.id.contacts_item_head); + name = (TextView) view.findViewById(R.id.contacts_item_name); + time = (TextView) view.findViewById(R.id.contacts_item_time); + desc = (TextView) view.findViewById(R.id.contacts_item_desc); + + // calculate + View parent = (View) desc.getParent(); + if (parent.getMeasuredWidth() == 0) { + // xml中:50dp,包括头像的长度还有左右间距大小 + parent.measure(View.MeasureSpec.makeMeasureSpec(ScreenUtil.getDisplayWidth() - ScreenUtil.dip2px(50.0f), View.MeasureSpec.EXACTLY), 0); + } + descTextViewWidth = (int) (parent.getMeasuredWidth() - desc.getPaint().measureText(PREFIX)); + + return view; + } + + @Override + public void refresh(ContactDataAdapter adapter, int position, final MsgItem item) { + // contact info + final IContact contact = item.getContact(); + final MsgIndexRecord record = item.getRecord(); + + if (record.getSessionType() == SessionTypeEnum.P2P) { + head.loadBuddyAvatar(contact.getContactId()); + } else { + Team team = NimUIKit.getTeamProvider().getTeamById(contact.getContactId()); + head.loadTeamIconByTeam(team); + } + name.setText(contact.getDisplayName()); + + if (item.isQuerySession()) { + time.setVisibility(View.VISIBLE); + time.setText(TimeUtil.getTimeShowString(record.getTime(), false)); + } else { + time.setVisibility(View.GONE); + } + + // query result + if (record.getCount() > 1) { + desc.setText(String.format("%d条相关聊天记录", record.getCount())); + } else { + String text = record.getText(); // 原串 + List clone = record.cloneHitInfo(); // 计算高亮区域并clone + + // 异常情况,没有高亮击中的区间,直接设置原串 + if (clone == null || clone.isEmpty()) { + desc.setText(text); + return; + } + + int firstIndex = clone.get(0).start; // 首个需要高亮的关键字的起始位置 + int firstHitInfoLength = clone.get(0).end - clone.get(0).start + 1; // 首个需要高亮的关键字的长度 + + // 判断是否需要截取 + Object[] result = needCutText(record.getText(), firstIndex, firstHitInfoLength); + Boolean needCut = (Boolean) result[0]; + int extractPreStrNum = (Integer) result[1]; + if (needCut) { + // 文本截取 + int newStartIndex = firstIndex - extractPreStrNum; + text = PREFIX + text.substring(newStartIndex); + + // 矫正hitInfo + int delta = newStartIndex - PREFIX.length(); + for (RecordHitInfo rh : clone) { + rh.start -= delta; + rh.end -= delta; + } + } + + display(desc, text, clone); + } + } + + /** + * 假如第一个索引之前的文字宽度>layout宽度,就需要把text截断 + * + * @param text 原文本 + * @param firstIndex 首个需要高亮的关键字的起始位置 + * @param firstHitInfoLength 首个需要高亮的关键字的长度 + * @return [0]是否需要截取字符串;[1]如果要截取,那么需要提取前面几个字符 + */ + private Object[] needCutText(String text, int firstIndex, int firstHitInfoLength) { + Boolean r0; + Integer r1; + float descLength = desc.getPaint().measureText(text.substring(0, firstIndex + firstHitInfoLength)); + float avg = descLength / (firstIndex + firstHitInfoLength); // 前firstIndex+firstHitInfoLength个字符,平均每个字符的长度 + + if (descLength >= descTextViewWidth) { + r0 = true; + int extractPreStrNum = (int) (1.0f * descTextViewWidth / avg); // 当前viewHolder desc TextView能容纳多少个字符(前firstIndex区间的字符) + extractPreStrNum = extractPreStrNum - PREFIX.length() - firstHitInfoLength; // 可以提取前面几个字符 + if (extractPreStrNum < 0) { + extractPreStrNum = 0; // 有可能为负数,例如firstHitInfo特别长 + } + + // 新的文本 + int newStartIndex = firstIndex - extractPreStrNum; + text = PREFIX + text.substring(newStartIndex, firstIndex + firstHitInfoLength); + + // extractPreStrNum 校准 + if (extractPreStrNum > 0) { + descLength = desc.getPaint().measureText(text); + if (descLength > descTextViewWidth) { + int delta = (int) ((descLength - descTextViewWidth) / (descLength / text.length())) + 1; + extractPreStrNum -= delta; // 減少提取的字符数 + } + + if (extractPreStrNum < 0) { + extractPreStrNum = 0; // 修正 + } + } + + r1 = extractPreStrNum; + } else { + r0 = false; + r1 = 0; + } + return new Object[]{r0, r1}; + } + + public static final void display(TextView tv, String text, List hitInfos) { + if (hitInfos == null || hitInfos.isEmpty()) { + tv.setText(text); + return; + } + + SpannableStringBuilder sb = new SpannableStringBuilder(); + SpannableString ss = new SpannableString(text); + for (RecordHitInfo r : hitInfos) { + ss.setSpan(new ForegroundColorSpan(tv.getResources().getColor(R.color.contact_search_hit)), r.start, r.end + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + + sb.append(ss); + tv.setText(sb); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/OnlineStateContactHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/OnlineStateContactHolder.java new file mode 100644 index 0000000..9fe08f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/OnlineStateContactHolder.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder; + +import android.text.TextUtils; +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; + +/** + * Created by hzchenkang on 2017/4/6. + */ + +public class OnlineStateContactHolder extends ContactHolder { + + @Override + public void refresh(ContactDataAdapter adapter, int position, ContactItem item) { + super.refresh(adapter, position, item); + IContact contact = item.getContact(); + // 在线状态 + if (contact.getContactType() != IContact.Type.Friend || !NimUIKitImpl.enableOnlineState()) { + desc.setVisibility(View.GONE); + } else { + String onlineStateContent = NimUIKitImpl.getOnlineStateContentProvider().getSimpleDisplay(contact.getContactId()); + if (TextUtils.isEmpty(onlineStateContent)) { + desc.setVisibility(View.GONE); + } else { + desc.setVisibility(View.VISIBLE); + desc.setText(onlineStateContent); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/TextHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/TextHolder.java new file mode 100644 index 0000000..52ac392 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/core/viewholder/TextHolder.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.TextItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.netease.nim.uikit.R; + +public class TextHolder extends AbsContactViewHolder { + private TextView textView; + + public void refresh(ContactDataAdapter contactAdapter, int position, TextItem item) { + textView.setText(item.getText()); + } + + @Override + public View inflate(LayoutInflater inflater) { + View view = inflater.inflate(R.layout.nim_contact_text_item, null); + textView = (TextView) view.findViewById(R.id.text); + return view; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/activity/ContactSelectActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/activity/ContactSelectActivity.java new file mode 100644 index 0000000..1b9ba24 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/activity/ContactSelectActivity.java @@ -0,0 +1,622 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.selector.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.GridView; +import android.widget.HorizontalScrollView; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.appcompat.widget.SearchView; +import androidx.core.view.MenuItemCompat; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItemFilter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ItemTypes; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactGroupStrategy; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.provider.ContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.provider.TeamMemberDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.IContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.TextQuery; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder.LabelHolder; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.adapter.ContactSelectAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.adapter.ContactSelectAvatarAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.viewholder.ContactsMultiSelectHolder; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.viewholder.ContactsSelectHolder; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.ui.liv.LetterIndexView; +import com.fengliyan.tianlesue.im.uikit.common.ui.liv.LivIndex; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 联系人选择器 + *

+ * Created by huangjun on 2015/3/3. + */ +public class ContactSelectActivity extends UI implements View.OnClickListener, SearchView.OnQueryTextListener { + + public static final String EXTRA_DATA = "EXTRA_DATA"; // 请求数据:Option + public static final String RESULT_DATA = "RESULT_DATA"; // 返回结果 + + // adapter + + private ContactSelectAdapter contactAdapter; + + private ContactSelectAvatarAdapter contactSelectedAdapter; + + // view + + private ListView listView; + + private LivIndex livIndex; + + private RelativeLayout bottomPanel; + + private HorizontalScrollView scrollViewSelected; + + private GridView imageSelectedGridView; + + private Button btnSelect; + + private SearchView searchView; + + // other + + private String queryText; + + private Option option; + + // class + + private static class ContactsSelectGroupStrategy extends ContactGroupStrategy { + public ContactsSelectGroupStrategy() { + add(ContactGroupStrategy.GROUP_NULL, -1, ""); + addABC(0); + } + } + + /** + * 联系人选择器配置可选项 + */ + public enum ContactSelectType { + BUDDY, + TEAM_MEMBER, + TEAM + } + + public static class Option implements Serializable { + + /** + * 联系人选择器中数据源类型:好友(默认)、群、群成员(需要设置teamId) + */ + public ContactSelectType type = ContactSelectType.BUDDY; + + /** + * 联系人选择器数据源类型为群成员时,需要设置群号 + */ + public String teamId = null; + + /** + * 联系人选择器标题 + */ + public String title = "联系人选择器"; + + /** + * 联系人单选/多选(默认) + */ + public boolean multi = true; + + /** + * 至少选择人数 + */ + public int minSelectNum = 1; + + /** + * 低于最少选择人数的提示 + */ + public String minSelectedTip = null; + + /** + * 最大可选人数 + */ + public int maxSelectNum = 2000; + + /** + * 超过最大可选人数的提示 + */ + public String maxSelectedTip = null; + + /** + * 是否显示已选头像区域 + */ + public boolean showContactSelectArea = true; + + /** + * 默认勾选(且可操作)的联系人项 + */ + public ArrayList alreadySelectedAccounts = null; + + /** + * 需要过滤(不显示)的联系人项 + */ + public ContactItemFilter itemFilter = null; + + /** + * 需要disable(可见但不可操作)的联系人项 + */ + public ContactItemFilter itemDisableFilter = null; + + /** + * 是否支持搜索 + */ + public boolean searchVisible = true; + + /** + * 允许不选任何人点击确定 + */ + public boolean allowSelectEmpty = false; + + /** + * 是否显示最大数目,结合maxSelectNum,与搜索位置相同 + */ + public boolean maxSelectNumVisible = false; + } + + public static void startActivityForResult(Context context, Option option, int requestCode) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_DATA, option); + intent.setClass(context, ContactSelectActivity.class); + + ((Activity) context).startActivityForResult(intent, requestCode); + } + + @Override + public void onBackPressed() { + if (searchView != null) { + searchView.setQuery("", true); + searchView.setIconified(true); + } + showKeyboard(false); + finish(); + } + + @Override + public boolean onCreateOptionsMenu(android.view.Menu menu) { + // search view + getMenuInflater().inflate(R.menu.nim_contacts_search_menu, menu); + MenuItem item = menu.findItem(R.id.action_search); + if (!option.searchVisible) { + item.setVisible(false); + return true; + } + + MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() { + + @Override + public boolean onMenuItemActionExpand(MenuItem menuItem) { + return true; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem menuItem) { + finish(); + return false; + } + }); + SearchView searchView = (SearchView) MenuItemCompat.getActionView(item); + this.searchView = searchView; + this.searchView.setVisibility(option.searchVisible ? View.VISIBLE : View.GONE); + searchView.setOnQueryTextListener(this); + return true; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_contacts_select); + + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + + parseIntentData(); + initAdapter(); + initListView(); + initContactSelectArea(); + + loadData(); + } + + private void parseIntentData() { + this.option = (Option) getIntent().getSerializableExtra(EXTRA_DATA); + if (TextUtils.isEmpty(option.maxSelectedTip)) { + option.maxSelectedTip = "最多选择" + option.maxSelectNum + "人"; + } + if (TextUtils.isEmpty(option.minSelectedTip)) { + option.minSelectedTip = "至少选择" + option.minSelectNum + "人"; + } + setTitle(option.title); + } + + private class ContactDataProviderEx extends ContactDataProvider { + private String teamId; + + private boolean loadedTeamMember = false; + + public ContactDataProviderEx(String teamId, int... itemTypes) { + super(itemTypes); + this.teamId = teamId; + } + + @Override + public List provide(TextQuery query) { + List data = new ArrayList<>(); + // 异步加载 + if (!loadedTeamMember) { + TeamMemberDataProvider.loadTeamMemberDataAsync(teamId, new TeamMemberDataProvider.LoadTeamMemberCallback() { + @Override + public void onResult(boolean success) { + if (success) { + loadedTeamMember = true; + // 列表重新加载数据 + loadData(); + } + } + }); + } else { + data = TeamMemberDataProvider.provide(query, teamId); + } + return data; + } + } + + private void initAdapter() { + IContactDataProvider dataProvider; + if (option.type == ContactSelectType.TEAM_MEMBER && !TextUtils.isEmpty(this.option.teamId)) { + dataProvider = new ContactDataProviderEx(this.option.teamId, ItemTypes.TEAM_MEMBER); + } else if (option.type == ContactSelectType.TEAM) { + option.showContactSelectArea = false; + dataProvider = new ContactDataProvider(ItemTypes.TEAM); + } else { + dataProvider = new ContactDataProvider(ItemTypes.FRIEND); + } + + // contact adapter + contactAdapter = new ContactSelectAdapter(ContactSelectActivity.this, new ContactsSelectGroupStrategy(), + dataProvider) { + boolean isEmptyContacts = false; + + @Override + protected List onNonDataItems() { + return null; + } + + @Override + protected void onPostLoad(boolean empty, String queryText, boolean all) { + if (empty) { + if (TextUtils.isEmpty(queryText)) { + isEmptyContacts = true; + } + updateEmptyView(queryText); + } else { + setSearchViewVisible(true); + } + } + + private void updateEmptyView(String queryText) { + if (!isEmptyContacts && !TextUtils.isEmpty(queryText)) { + setSearchViewVisible(true); + } else { + setSearchViewVisible(false); + } + } + + private void setSearchViewVisible(boolean visible) { + option.searchVisible = visible; + if (searchView != null) { + searchView.setVisibility(option.searchVisible ? View.VISIBLE : View.GONE); + } + } + }; + + Class c = option.multi ? ContactsMultiSelectHolder.class : ContactsSelectHolder.class; + contactAdapter.addViewHolder(ItemTypes.LABEL, LabelHolder.class); + contactAdapter.addViewHolder(ItemTypes.FRIEND, c); + contactAdapter.addViewHolder(ItemTypes.TEAM_MEMBER, c); + contactAdapter.addViewHolder(ItemTypes.TEAM, c); + + contactAdapter.setFilter(option.itemFilter); + contactAdapter.setDisableFilter(option.itemDisableFilter); + + // contact select adapter + contactSelectedAdapter = new ContactSelectAvatarAdapter(this); + } + + private void initListView() { + listView = findView(R.id.contact_list_view); + listView.setAdapter(contactAdapter); + listView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + showKeyboard(false); + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + position = position - listView.getHeaderViewsCount(); + AbsContactItem item = (AbsContactItem) contactAdapter.getItem(position); + + if (item == null) { + return; + } + + if (option.multi) { + if (!contactAdapter.isEnabled(position)) { + return; + } + IContact contact = null; + if (item instanceof ContactItem) { + contact = ((ContactItem) item).getContact(); + } + if (contactAdapter.isSelected(position)) { + contactAdapter.cancelItem(position); + if (contact != null) { + contactSelectedAdapter.removeContact(contact); + } + } else { + if (contactSelectedAdapter.getCount() <= option.maxSelectNum) { + contactAdapter.selectItem(position); + if (contact != null) { + contactSelectedAdapter.addContact(contact); + } + } else { + ToastHelper.showToast(ContactSelectActivity.this, option.maxSelectedTip); + } + + if (!TextUtils.isEmpty(queryText) && searchView != null) { + searchView.setQuery("", true); + searchView.setIconified(true); + showKeyboard(false); + } + } + arrangeSelected(); + } else { + if (item instanceof ContactItem) { + final IContact contact = ((ContactItem) item).getContact(); + ArrayList selectedIds = new ArrayList<>(); + selectedIds.add(contact.getContactId()); + onSelected(selectedIds); + } + + arrangeSelected(); + } + } + }); + + // 字母导航 + TextView letterHit = (TextView) findViewById(R.id.tv_hit_letter); + LetterIndexView idxView = (LetterIndexView) findViewById(R.id.liv_index); + idxView.setLetters(getResources().getStringArray(R.array.letter_list2)); + ImageView imgBackLetter = (ImageView) findViewById(R.id.img_hit_letter); + if (option.type != ContactSelectType.TEAM) { + livIndex = contactAdapter.createLivIndex(listView, idxView, letterHit, imgBackLetter); + livIndex.show(); + } else { + idxView.setVisibility(View.GONE); + } + } + + private void initContactSelectArea() { + btnSelect = (Button) findViewById(R.id.btnSelect); + if (!option.allowSelectEmpty) { + btnSelect.setEnabled(false); + } else { + btnSelect.setEnabled(true); + } + btnSelect.setOnClickListener(this); + bottomPanel = (RelativeLayout) findViewById(R.id.rlCtrl); + scrollViewSelected = (HorizontalScrollView) findViewById(R.id.contact_select_area); + if (option.multi) { + bottomPanel.setVisibility(View.VISIBLE); + if (option.showContactSelectArea) { + scrollViewSelected.setVisibility(View.VISIBLE); + btnSelect.setVisibility(View.VISIBLE); + } else { + scrollViewSelected.setVisibility(View.GONE); + btnSelect.setVisibility(View.GONE); + } + btnSelect.setText(getOKBtnText(0)); + } else { + bottomPanel.setVisibility(View.GONE); + } + + // selected contact image banner + imageSelectedGridView = (GridView) findViewById(R.id.contact_select_area_grid); + imageSelectedGridView.setAdapter(contactSelectedAdapter); + notifySelectAreaDataSetChanged(); + imageSelectedGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + try { + if (contactSelectedAdapter.getItem(position) == null) { + return; + } + + IContact iContact = contactSelectedAdapter.remove(position); + if (iContact != null) { + contactAdapter.cancelItem(iContact); + } + arrangeSelected(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + // init already selected items + List selectedUids = option.alreadySelectedAccounts; + if (selectedUids != null && !selectedUids.isEmpty()) { + contactAdapter.setAlreadySelectedAccounts(selectedUids); + List selectedItems = contactAdapter.getSelectedItem(); + for (ContactItem item : selectedItems) { + contactSelectedAdapter.addContact(item.getContact()); + } + arrangeSelected(); + } + } + + private void loadData() { + contactAdapter.load(true); + } + + private void arrangeSelected() { + this.contactAdapter.notifyDataSetChanged(); + if (option.multi) { + int count = contactSelectedAdapter.getCount(); + if (!option.allowSelectEmpty) { + btnSelect.setEnabled(count > 1); + } else { + btnSelect.setEnabled(true); + } + btnSelect.setText(getOKBtnText(count)); + notifySelectAreaDataSetChanged(); + } + } + + private void notifySelectAreaDataSetChanged() { + int converViewWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 46, this.getResources() + .getDisplayMetrics())); + ViewGroup.LayoutParams layoutParams = imageSelectedGridView.getLayoutParams(); + layoutParams.width = converViewWidth * contactSelectedAdapter.getCount(); + layoutParams.height = converViewWidth; + imageSelectedGridView.setLayoutParams(layoutParams); + imageSelectedGridView.setNumColumns(contactSelectedAdapter.getCount()); + + try { + final int x = layoutParams.width; + final int y = layoutParams.height; + new Handler().post(new Runnable() { + @Override + public void run() { + scrollViewSelected.scrollTo(x, y); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + + contactSelectedAdapter.notifyDataSetChanged(); + } + + private String getOKBtnText(int count) { + String caption = getString(R.string.ok); + int showCount = (count < 1 ? 0 : (count - 1)); + StringBuilder sb = new StringBuilder(caption); + sb.append(" ("); + sb.append(showCount); + if (option.maxSelectNumVisible) { + sb.append("/"); + sb.append(option.maxSelectNum); + } + sb.append(")"); + return sb.toString(); + } + + /** + * ************************** select ************************ + */ + + @Override + public void onClick(View v) { + if (v.getId() == R.id.btnSelect) { + List contacts = contactSelectedAdapter + .getSelectedContacts(); + if (option.allowSelectEmpty || checkMinMaxSelection(contacts.size())) { + ArrayList selectedAccounts = new ArrayList<>(); + for (IContact c : contacts) { + selectedAccounts.add(c.getContactId()); + } + onSelected(selectedAccounts); + } + + } + } + + private boolean checkMinMaxSelection(int selected) { + if (option.minSelectNum > selected) { + return showMaxMinSelectTip(true); + } else if (option.maxSelectNum < selected) { + return showMaxMinSelectTip(false); + } + return true; + } + + private boolean showMaxMinSelectTip(boolean min) { + if (min) { + ToastHelper.showToast(this, option.minSelectedTip); + } else { + ToastHelper.showToast(this, option.maxSelectedTip); + } + return false; + } + + public void onSelected(ArrayList selects) { + Intent intent = new Intent(); + intent.putStringArrayListExtra(RESULT_DATA, selects); + setResult(Activity.RESULT_OK, intent); + this.finish(); + } + + /** + * ************************* search ****************************** + */ + + @Override + public boolean onQueryTextChange(String query) { + queryText = query; + if (TextUtils.isEmpty(query)) { + this.contactAdapter.load(true); + } else { + this.contactAdapter.query(query); + } + return true; + } + + @Override + public boolean onQueryTextSubmit(String arg0) { + return false; + } + + @Override + public void finish() { + showKeyboard(false); + super.finish(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/adapter/ContactSelectAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/adapter/ContactSelectAdapter.java new file mode 100644 index 0000000..78ad7d4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/adapter/ContactSelectAdapter.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.selector.adapter; + +import android.content.Context; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.AbsContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ItemTypes; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactGroupStrategy; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.query.IContactDataProvider; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.util.ContactHelper; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class ContactSelectAdapter extends ContactDataAdapter { + private HashSet selects = new HashSet(); + + public ContactSelectAdapter(Context context, + ContactGroupStrategy groupStrategy, IContactDataProvider dataProvider) { + super(context, groupStrategy, dataProvider); + } + + public final void setAlreadySelectedAccounts(List accounts) { + selects.addAll(accounts); + } + + public final List getSelectedItem() { + if (selects.isEmpty()) { + return null; + } + + List res = new ArrayList<>(); + for (String account : selects) { + final UserInfo user = NimUIKit.getUserInfoProvider().getUserInfo(account); + if (user != null) { + res.add(new ContactItem(ContactHelper.makeContactFromUserInfo(user), ItemTypes.FRIEND)); + } + } + + return res; + } + + public final void selectItem(int position) { + AbsContactItem item = (AbsContactItem) getItem(position); + if (item != null && item instanceof ContactItem) { + selects.add(((ContactItem) item).getContact().getContactId()); + } + notifyDataSetChanged(); + } + + public final boolean isSelected(int position) { + AbsContactItem item = (AbsContactItem) getItem(position); + if (item != null && item instanceof ContactItem) { + return selects.contains(((ContactItem) item).getContact().getContactId()); + } + return false; + } + + public final void cancelItem(int position) { + AbsContactItem item = (AbsContactItem) getItem(position); + if (item != null && item instanceof ContactItem) { + selects.remove(((ContactItem) item).getContact().getContactId()); + } + notifyDataSetChanged(); + } + + public final void cancelItem(IContact iContact) { + selects.remove(iContact.getContactId()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/adapter/ContactSelectAvatarAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/adapter/ContactSelectAvatarAdapter.java new file mode 100644 index 0000000..a7c7ce6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/adapter/ContactSelectAvatarAdapter.java @@ -0,0 +1,111 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.selector.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +class GalleryItemViewHolder { + HeadImageView imageView; +} + +public class ContactSelectAvatarAdapter extends BaseAdapter { + private Context context; + + private List selectedContactItems; + + public ContactSelectAvatarAdapter(Context context) { + this.context = context; + this.selectedContactItems = new ArrayList(); + selectedContactItems.add(null); + } + + @Override + public int getCount() { + return selectedContactItems.size(); + } + + @Override + public Object getItem(int position) { + return selectedContactItems.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + HeadImageView imageView; + + if (convertView == null) { + convertView = LayoutInflater.from(context).inflate(R.layout.nim_contact_select_area_item, null); + imageView = (HeadImageView) convertView.findViewById(R.id.contact_select_area_image); + + GalleryItemViewHolder holder = new GalleryItemViewHolder(); + holder.imageView = imageView; + convertView.setTag(holder); + } else { + GalleryItemViewHolder holder = (GalleryItemViewHolder) convertView.getTag(); + imageView = holder.imageView; + } + + try { + IContact item = selectedContactItems.get(position); + if (item == null) { + imageView.setBackgroundResource(R.drawable.nim_contact_select_dot_avatar); + imageView.setImageDrawable(null); + } else { + imageView.loadBuddyAvatar(item.getContactId()); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return convertView; + } + + public void addContact(IContact contact) { + if (selectedContactItems.size() > 0) { + IContact iContact = selectedContactItems.get(selectedContactItems.size() - 1); + if (iContact == null) { + selectedContactItems.remove(selectedContactItems.size() - 1); + } + } + this.selectedContactItems.add(contact); + selectedContactItems.add(null); + } + + public void removeContact(IContact contact) { + if (contact == null) { + return; + } + for (Iterator iterator = selectedContactItems.iterator(); iterator.hasNext(); ) { + IContact iContact = iterator.next(); + if (iContact == null) { + continue; + } + if (iContact.getContactId().equals(contact.getContactId())) { + iterator.remove(); + } + } + } + + public IContact remove(int pos) { + return this.selectedContactItems.remove(pos); + } + + public List getSelectedContacts() { + return this.selectedContactItems.subList(0, selectedContactItems.size() - 1); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/viewholder/ContactsMultiSelectHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/viewholder/ContactsMultiSelectHolder.java new file mode 100644 index 0000000..45018df --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/viewholder/ContactsMultiSelectHolder.java @@ -0,0 +1,7 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.selector.viewholder; + +public class ContactsMultiSelectHolder extends ContactsSelectHolder { + public ContactsMultiSelectHolder() { + super(true); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/viewholder/ContactsSelectHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/viewholder/ContactsSelectHolder.java new file mode 100644 index 0000000..eaad91d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/contact/selector/viewholder/ContactsSelectHolder.java @@ -0,0 +1,89 @@ +package com.fengliyan.tianlesue.im.uikit.business.contact.selector.viewholder; + +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactItem; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.ContactDataAdapter; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.model.IContact; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.viewholder.AbsContactViewHolder; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.adapter.ContactSelectAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; + + +public class ContactsSelectHolder extends AbsContactViewHolder { + private final boolean multi; + + private HeadImageView image; + + private TextView nickname; + + private ImageView select; + + private Drawable defaultBackground; + + public ContactsSelectHolder() { + this(false); + } + + ContactsSelectHolder(boolean multi) { + this.multi = multi; + } + + @Override + public void refresh(ContactDataAdapter adapter, int position, ContactItem item) { + if (multi) { + boolean disabled = !adapter.isEnabled(position); + boolean selected = adapter instanceof ContactSelectAdapter ? ((ContactSelectAdapter) adapter).isSelected(position) : false; + this.select.setVisibility(View.VISIBLE); + if (disabled) { + this.select.setBackgroundResource(R.drawable.nim_contact_checkbox_checked_grey); + getView().setBackgroundColor(context.getResources().getColor(R.color.transparent)); + } else if (selected) { + setBackground(getView(), defaultBackground); + this.select.setBackgroundResource(R.drawable.nim_contact_checkbox_checked_green); + } else { + setBackground(getView(), defaultBackground); + this.select.setBackgroundResource(R.drawable.nim_contact_checkbox_unchecked); + } + } else { + this.select.setVisibility(View.GONE); + } + + IContact contact = item.getContact(); + this.nickname.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); + this.nickname.setText(contact.getDisplayName()); + if (contact.getContactType() == IContact.Type.Friend || contact.getContactType() == IContact.Type.TeamMember) { + this.nickname.setText(contact.getDisplayName()); + this.image.loadBuddyAvatar(contact.getContactId()); + } else if (contact.getContactType() == IContact.Type.Team) { + this.image.loadTeamIconByTeam(NimUIKit.getTeamProvider().getTeamById(contact.getContactId())); + } + + this.image.setVisibility(View.VISIBLE); + } + + @Override + public View inflate(LayoutInflater inflater) { + View view = inflater.inflate(R.layout.nim_contacts_select_item, null); + defaultBackground = view.getBackground(); + this.image = view.findViewById(R.id.img_head); + this.nickname = view.findViewById(R.id.tv_nickname); + this.select = view.findViewById(R.id.imgSelect); + return view; + } + + private void setBackground(View view, Drawable drawable) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + view.setBackground(drawable); + } else { + view.setBackgroundDrawable(drawable); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/preference/UserPreferences.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/preference/UserPreferences.java new file mode 100644 index 0000000..f03a9f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/preference/UserPreferences.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.im.uikit.business.preference; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; + +/** + * Created by hzxuwen on 2015/10/21. + */ +public class UserPreferences { + + private final static String KEY_EARPHONE_MODE = "KEY_EARPHONE_MODE"; + + public static void setEarPhoneModeEnable(boolean on) { + saveBoolean(KEY_EARPHONE_MODE, on); + } + + public static boolean isEarPhoneModeEnable() { + return getBoolean(KEY_EARPHONE_MODE, true); + } + + private static boolean getBoolean(String key, boolean value) { + return getSharedPreferences().getBoolean(key, value); + } + + private static void saveBoolean(String key, boolean value) { + SharedPreferences.Editor editor = getSharedPreferences().edit(); + editor.putBoolean(key, value); + editor.apply(); + } + + private static SharedPreferences getSharedPreferences() { + return NimUIKit.getContext().getSharedPreferences("UIKit." + NimUIKit.getAccount(), Context.MODE_PRIVATE); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/RecentContactsCallback.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/RecentContactsCallback.java new file mode 100644 index 0000000..cf01356 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/RecentContactsCallback.java @@ -0,0 +1,46 @@ +package com.fengliyan.tianlesue.im.uikit.business.recent; + +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.model.RecentContact; + +/** + * 最近联系人列表自定义事件回调函数. + */ +public interface RecentContactsCallback { + + /** + * 最近联系人列表数据加载完成的回调函数 + */ + void onRecentContactsLoaded(); + + /** + * 有未读数更新时的回调函数,供更新除最近联系人列表外的其他界面和未读指示 + * + * @param unreadCount 当前总的未读数 + */ + void onUnreadCountChange(int unreadCount); + + /** + * 最近联系人点击响应回调函数,以供打开会话窗口时传入定制化参数,或者做其他动作 + * + * @param recent 最近联系人 + */ + void onItemClick(RecentContact recent); + + /** + * 设置自定义消息的摘要信息,展示在最近联系人列表的消息缩略栏上. + * 当然,你也可以自定义一些内建消息的缩略语,例如图片,语音,音视频会话等,自定义的缩略语会被优先使用。 + * + * @param attachment 消息附件对象 + * @return 消息摘要 + */ + String getDigestOfAttachment(RecentContact recent, MsgAttachment attachment); + + /** + * 设置Tip消息的摘要信息,展示在最近联系人列表的消息缩略栏上 + * + * @param recent 最近联系人 + * @return Tip消息摘要 + */ + String getDigestOfTipMsg(RecentContact recent); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/RecentContactsFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/RecentContactsFragment.java new file mode 100644 index 0000000..ba0a89c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/RecentContactsFragment.java @@ -0,0 +1,818 @@ +package com.fengliyan.tianlesue.im.uikit.business.recent; + +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.eventBus.UnReadCountEvent; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.main.OnlineStateChangeObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamMemberDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.business.recent.adapter.RecentContactAdapter; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.MessageHelper; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.CommonUtil; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.im.uikit.common.badger.Badger; +import com.fengliyan.tianlesue.im.uikit.common.fragment.TFragment; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.drop.DropCover; +import com.fengliyan.tianlesue.im.uikit.common.ui.drop.DropManager; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener.SimpleClickListener; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.friend.FriendService; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.msg.model.RevokeMsgNotification; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import de.greenrobot.event.EventBus; +import me.everything.android.ui.overscroll.OverScrollDecoratorHelper; + + +/** + * 最近联系人列表(会话列表) + *

+ * Created by huangjun on 2015/2/1. + */ +public class RecentContactsFragment extends TFragment { + + // 置顶功能可直接使用,也可作为思路,供开发者充分利用RecentContact的tag字段 + public static final long RECENT_TAG_STICKY = 0x0000000000000001; // 联系人置顶tag + + // view + private RecyclerView recyclerView; + + private View emptyBg; + + private TextView emptyHint; + + // data + private List items; + + private Map cached; // 暂缓刷上列表的数据(未读数红点拖拽动画运行时用) + + private RecentContactAdapter adapter; + + private boolean msgLoaded = false; + + private RecentContactsCallback callback; + + String avatar; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + findViews(); + initMessageList(); + requestMessages(true); + registerObservers(true); + registerDropCompletedListener(true); + registerOnlineStateChangeListener(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.nim_recent_contacts, container, false); + } + + private void notifyDataSetChanged() { + adapter.notifyDataSetChanged(); + boolean empty = items.isEmpty() && msgLoaded; + emptyBg.setVisibility(empty ? View.VISIBLE : View.GONE); + emptyHint.setHint("还没有会话,找个人聊聊吧!"); + } + + + @Override + public void onDestroy() { + super.onDestroy(); + registerObservers(false); + registerDropCompletedListener(false); + registerOnlineStateChangeListener(false); + DropManager.getInstance().setDropListener(null); + } + + /** + * 查找页面控件 + */ + private void findViews() { + recyclerView = findView(R.id.recycler_view); + emptyBg = findView(R.id.emptyBg); + emptyHint = findView(R.id.message_list_empty_hint); + } + + /** + * 初始化消息列表 + */ + private void initMessageList() { + items = new ArrayList<>(); + cached = new HashMap<>(3); + + // adapter + adapter = new RecentContactAdapter(recyclerView, items); + initCallBack(); + adapter.setCallback(callback); + + // recyclerView + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + recyclerView.addOnItemTouchListener(touchListener); + + // ios style + OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL); + + // drop listener + DropManager.getInstance().setDropListener(new DropManager.IDropListener() { + @Override + public void onDropBegin() { + touchListener.setShouldDetectGesture(false); + } + + @Override + public void onDropEnd() { + touchListener.setShouldDetectGesture(true); + } + }); + } + + private void initCallBack() { + if (callback != null) { + return; + } + callback = new RecentContactsCallback() { + @Override + public void onRecentContactsLoaded() { + + } + + @Override + public void onUnreadCountChange(int unreadCount) { + + } + + @Override + public void onItemClick(RecentContact recent) { + if (recent.getSessionType() == SessionTypeEnum.Team) { + NimUIKit.startTeamSession(getActivity(), recent.getContactId()); + } else if (recent.getSessionType() == SessionTypeEnum.P2P) { + NimUIKit.startChat(recent.getContactId(), getActivity()); + } + } + + @Override + public String getDigestOfAttachment(RecentContact recentContact, MsgAttachment attachment) { + return null; + } + + @Override + public String getDigestOfTipMsg(RecentContact recent) { + return null; + } + }; + } + + private SimpleClickListener touchListener = new SimpleClickListener() { + @Override + public void onItemClick(RecentContactAdapter adapter, View view, int position) { + if (callback != null) { + RecentContact recent = adapter.getItem(position); + callback.onItemClick(recent); + } + } + + @Override + public void onItemLongClick(RecentContactAdapter adapter, View view, int position) { +// //客服 +// if (position == 0) { +// return; +// } + showLongClickMenu(adapter.getItem(position), position); + } + + @Override + public void onItemChildClick(RecentContactAdapter adapter, View view, int position) { + + } + + @Override + public void onItemChildLongClick(RecentContactAdapter adapter, View view, int position) { + + } + }; + + OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() { + @Override + public void onlineStateChange(Set accounts) { + notifyDataSetChanged(); + } + }; + + private void registerOnlineStateChangeListener(boolean register) { + if (!NimUIKitImpl.enableOnlineState()) { + return; + } + NimUIKitImpl.getOnlineStateChangeObservable().registerOnlineStateChangeListeners(onlineStateChangeObserver, register); + } + + private void showLongClickMenu(final RecentContact recent, final int position) { + CustomAlertDialog alertDialog = new CustomAlertDialog(getActivity()); + alertDialog.setTitle(UserInfoHelper.getUserTitleName(recent.getContactId(), recent.getSessionType())); + String title = getString(R.string.main_msg_list_delete_chatting); + alertDialog.addItem(title, new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + // 删除会话,删除后,消息历史被一起删除 + NIMClient.getService(MsgService.class).deleteRecentContact(recent); + NIMClient.getService(MsgService.class).clearChattingHistory(recent.getContactId(), recent.getSessionType()); + adapter.remove(position); + + postRunnable(new Runnable() { + @Override + public void run() { + refreshMessages(true); + } + }); + } + }); + + title = (CommonUtil.isTagSet(recent, RECENT_TAG_STICKY) ? getString(R.string.main_msg_list_clear_sticky_on_top) : getString(R.string.main_msg_list_sticky_on_top)); + alertDialog.addItem(title, new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + if (CommonUtil.isTagSet(recent, RECENT_TAG_STICKY)) { + CommonUtil.removeTag(recent, RECENT_TAG_STICKY); + //tag + SPUtils.saveBoolean(getActivity(), recent.getContactId(), false); + } else { + CommonUtil.addTag(recent, RECENT_TAG_STICKY); + //tag + SPUtils.saveBoolean(getActivity(), recent.getContactId(), true); + } + NIMClient.getService(MsgService.class).updateRecent(recent); + + refreshMessages(false); + } + }); + + boolean checkState = NIMClient.getService(FriendService.class).isNeedMessageNotify(recent.getContactId()); + title = (checkState ? getString(R.string.main_msg_list_mute_on) : getString(R.string.main_msg_list_mute_off)); + alertDialog.addItem(title, new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + NIMClient.getService(FriendService.class).setMessageNotify(recent.getContactId(), !checkState).setCallback(new RequestCallbackWrapper() { + @Override + public void onResult(int code, Void result, Throwable exception) { + if (code == ResponseCode.RES_SUCCESS) { + int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount(true); + avatar = ""; + if (unreadNum > 0) { + NIMClient.getService(MsgService.class).queryRecentContacts().setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List recentContacts, Throwable throwable) { + if (recentContacts != null && recentContacts.size() > 0) { + for (int i = 0; i < recentContacts.size(); i++) { + if (NIMClient.getService(FriendService.class).isNeedMessageNotify(recentContacts.get(i).getContactId())) { + if (recentContacts.get(i).getUnreadCount() != 0 && Long.parseLong(recentContacts.get(i).getContactId()) > 20 && recentContacts.get(i).getSessionType() == SessionTypeEnum.P2P) { + NimUserInfo userInfo = NIMClient.getService(UserService.class).getUserInfo(recentContacts.get(i).getContactId()); + if (ConstUrl.LOGDEBUG)Log.i("TAG", "recentContacts: ----------->" + userInfo); + if (userInfo != null) { + avatar = userInfo.getAvatar(); + if (!TextUtils.isEmpty(avatar)) { + avatar = StrU.getResourcePath(avatar, getContext()); + } + } + break; + } + } + } + } + EventBus.getDefault().post(new UnReadCountEvent(unreadNum, avatar)); + } + }); + } else { + EventBus.getDefault().post(new UnReadCountEvent(unreadNum, avatar)); + } + + refreshMessages(false); +// if (checkState) { +// Toast.makeText(UserProfileActivity.this, "开启消息提醒", Toast.LENGTH_SHORT).show(); +// } else { +// Toast.makeText(UserProfileActivity.this, "关闭消息提醒", Toast.LENGTH_SHORT).show(); +// } + } + } + }); + } + }); + + /* alertDialog.addItem("删除该聊天(仅服务器)", new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + NIMClient.getService(MsgService.class) + .deleteRoamingRecentContact(recent.getContactId(), recent.getSessionType()) + .setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + ToastHelper.showToast(getActivity(), "delete success"); + } + + @Override + public void onFailed(int code) { + ToastHelper.showToast(getActivity(), "delete failed, code:" + code); + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + }); + */ + alertDialog.show(); + } + + private List loadedRecents; + + private void requestMessages(boolean delay) { + if (msgLoaded) { + return; + } + getHandler().postDelayed(new Runnable() { + + @Override + public void run() { + if (msgLoaded) { + return; + } + // 查询最近联系人列表数据 + NIMClient.getService(MsgService.class).queryRecentContacts().setCallback(new RequestCallbackWrapper>() { + + @Override + public void onResult(int code, List recents, Throwable exception) { + if (code != ResponseCode.RES_SUCCESS || recents == null) { + return; + } + loadedRecents = recents; + // 初次加载,更新离线的消息中是否有@我的消息 + loadedRecents.removeIf(loadedRecent -> loadedRecent.getSessionType() == SessionTypeEnum.Team); + + for (RecentContact loadedRecent : loadedRecents) { +// if (loadedRecent.getSessionType() == SessionTypeEnum.Team) { +//// updateOfflineContactAited(loadedRecent); +// } + + //取消默认置顶客服 + if (SPUtils.getInt(requireActivity(), Constans.CUSTOMER_TAG_STICKY, 0) == 0) { + if (TextUtils.equals("4", loadedRecent.getContactId())) { + if (CommonUtil.isTagSet(loadedRecent, RECENT_TAG_STICKY)) { + CommonUtil.removeTag(loadedRecent, RECENT_TAG_STICKY); + SPUtils.saveBoolean(requireActivity(), loadedRecent.getContactId(), false); + NIMClient.getService(MsgService.class).updateRecent(loadedRecent); + } + SPUtils.saveInt(requireActivity(), Constans.CUSTOMER_TAG_STICKY, 1); + } + } + } + // 此处如果是界面刚初始化,为了防止界面卡顿,可先在后台把需要显示的用户资料和群组资料在后台加载好,然后再刷新界面 + // + msgLoaded = true; + if (isAdded()) { + onRecentContactsLoaded(); + } + } + }); + } + }, delay ? 250 : 0); + } + + private void onRecentContactsLoaded() { + items.clear(); + if (loadedRecents != null) { + items.addAll(loadedRecents); + loadedRecents = null; + } + refreshMessages(true); + + if (callback != null) { + callback.onRecentContactsLoaded(); + } + } + + private void refreshMessages(boolean unreadChanged) { + sortRecentContacts(items); + notifyDataSetChanged(); + if (unreadChanged) { + // 方式一:累加每个最近联系人的未读(快) + + int unreadNum = 0; + for (RecentContact r : items) { + unreadNum += r.getUnreadCount(); + } + + // 方式二:直接从SDK读取(相对慢) + //int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount(); + + if (callback != null) { + callback.onUnreadCountChange(unreadNum); + } + + Badger.updateBadgerCount(unreadNum); + } + } + + /** + * **************************** 排序 *********************************** + */ + private void sortRecentContacts(List list) { + if (list.size() == 0) { + return; + } + Collections.sort(list, comp); + +// //3期 客服置顶添加标识 +// int serviceIndex = -1; +// for (int i = 0; i < list.size(); i++) { +// if (list.get(i).getContactId().equals("4")) { +// serviceIndex = i; +// break; +// } +// } +// //如果没有客服的添加一个客服的,有的话就把客服置顶 +// if (serviceIndex == -1) { +// RecentContact services = NIMClient.getService(MsgService.class).createEmptyRecentContact("4", +// SessionTypeEnum.P2P, +// RECENT_TAG_STICKY, +// System.currentTimeMillis(), +// true); +// } else { +// Collections.swap(list, 0, serviceIndex); +// } + } + + private static Comparator comp = new Comparator() { + + @Override + public int compare(RecentContact o1, RecentContact o2) { + if (o1.getContactId().equals("2")) return -1; //置顶系统通知 + if (o2.getContactId().equals("2")) return 1; + if (o1.getContactId().equals("4")) return -1; //置顶客服 + if (o2.getContactId().equals("4")) return 1; + + // 先比较置顶tag + long sticky = (o1.getTag() & RECENT_TAG_STICKY) - (o2.getTag() & RECENT_TAG_STICKY); + if (sticky != 0) { + return sticky > 0 ? -1 : 1; + } else { + long time = o1.getTime() - o2.getTime(); + return time == 0 ? 0 : (time > 0 ? -1 : 1); + } + } + }; + + /** + * ********************** 收消息,处理状态变化 ************************ + */ + private void registerObservers(boolean register) { + MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class); + service.observeReceiveMessage(messageReceiverObserver, register); + service.observeRecentContact(messageObserver, register); + service.observeMsgStatus(statusObserver, register); + service.observeRecentContactDeleted(deleteObserver, register); + service.observeRevokeMessage(revokeMessageObserver, register); +// registerTeamUpdateObserver(register); +// registerTeamMemberUpdateObserver(register); +// NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, register); +// if (register) { +// registerUserInfoObserver(); +// } else { +// unregisterUserInfoObserver(); +// } + } + + /** + * 注册群信息&群成员更新监听 + */ + private void registerTeamUpdateObserver(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataChangedObserver, register); + } + + private void registerTeamMemberUpdateObserver(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberDataChangedObserver, register); + } + + private void registerDropCompletedListener(boolean register) { + if (register) { + DropManager.getInstance().addDropCompletedListener(dropCompletedListener); + } else { + DropManager.getInstance().removeDropCompletedListener(dropCompletedListener); + } + } + + // 暂存消息,当RecentContact 监听回来时使用,结束后清掉 + private Map> cacheMessages = new HashMap<>(); + + //监听在线消息中是否有@我 + private Observer> messageReceiverObserver = new Observer>() { + @Override + public void onEvent(List imMessages) { + if (imMessages != null) { + for (IMMessage imMessage : imMessages) { + if (!TeamMemberAitHelper.isAitMessage(imMessage)) { + continue; + } + Set cacheMessageSet = cacheMessages.get(imMessage.getSessionId()); + if (cacheMessageSet == null) { + cacheMessageSet = new HashSet<>(); + cacheMessages.put(imMessage.getSessionId(), cacheMessageSet); + } + cacheMessageSet.add(imMessage); + } + } + } + }; + + Observer> messageObserver = new Observer>() { + @Override + public void onEvent(List recentContacts) { + if (!DropManager.getInstance().isTouchable()) { + // 正在拖拽红点,缓存数据 + for (RecentContact r : recentContacts) { + cached.put(r.getContactId(), r); + } + + return; + } + onRecentContactChanged(recentContacts); + } + }; + + private void onRecentContactChanged(List recentContacts) { + int index; + for (RecentContact r : recentContacts) { + index = -1; + for (int i = 0; i < items.size(); i++) { + if (r.getContactId().equals(items.get(i).getContactId()) + && r.getSessionType() == (items.get(i).getSessionType())) { + index = i; + break; + } + } + + if (index >= 0) { + items.remove(index); + } + + items.add(r); + if (r.getSessionType() == SessionTypeEnum.Team && cacheMessages.get(r.getContactId()) != null) { + TeamMemberAitHelper.setRecentContactAited(r, cacheMessages.get(r.getContactId())); + } + } + + cacheMessages.clear(); + + refreshMessages(true); + } + + DropCover.IDropCompletedListener dropCompletedListener = new DropCover.IDropCompletedListener() { + @Override + public void onCompleted(Object id, boolean explosive) { + if (cached != null && !cached.isEmpty()) { + // 红点爆裂,已经要清除未读,不需要再刷cached + if (explosive) { + if (id instanceof RecentContact) { + RecentContact r = (RecentContact) id; + cached.remove(r.getContactId()); + } else if (id instanceof String && ((String) id).contentEquals("0")) { + cached.clear(); + } + } + + // 刷cached + if (!cached.isEmpty()) { + List recentContacts = new ArrayList<>(cached.size()); + recentContacts.addAll(cached.values()); + cached.clear(); + + onRecentContactChanged(recentContacts); + } + } + } + }; + + Observer statusObserver = new Observer() { + @Override + public void onEvent(IMMessage message) { + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + RecentContact item = items.get(index); + item.setMsgStatus(message.getStatus()); + refreshViewHolderByIndex(index); + } + } + }; + + Observer deleteObserver = new Observer() { + @Override + public void onEvent(RecentContact recentContact) { + if (recentContact != null) { + for (RecentContact item : items) { + if (TextUtils.equals(item.getContactId(), recentContact.getContactId()) + && item.getSessionType() == recentContact.getSessionType()) { + items.remove(item); + refreshMessages(true); + break; + } + } + } else { + items.clear(); + refreshMessages(true); + } + } + }; + + TeamDataChangedObserver teamDataChangedObserver = new TeamDataChangedObserver() { + + @Override + public void onUpdateTeams(List teams) { + adapter.notifyDataSetChanged(); + } + + @Override + public void onRemoveTeam(Team team) { + + } + }; + + TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() { + @Override + public void onUpdateTeamMember(List members) { + adapter.notifyDataSetChanged(); + } + + @Override + public void onRemoveTeamMember(List member) { + + } + }; + + /** + * 消息撤回观察者 + */ + private Observer revokeMessageObserver = new Observer() { + @Override + public void onEvent(RevokeMsgNotification notification) { + if (notification == null || notification.getMessage() == null) { + return; + } + IMMessage message = notification.getMessage(); + MessageHelper.getInstance().onRevokeMessage(message, message.getFromAccount()); + } + }; + + private int getItemIndex(String uuid) { + for (int i = 0; i < items.size(); i++) { + RecentContact item = items.get(i); + if (TextUtils.equals(item.getRecentMessageId(), uuid)) { + return i; + } + } + + return -1; + } + + protected void refreshViewHolderByIndex(final int index) { + getActivity().runOnUiThread(new Runnable() { + + @Override + public void run() { + adapter.notifyItemChanged(index); + } + }); + } + + public void setCallback(RecentContactsCallback callback) { + this.callback = callback; + } + + private final UserInfoObserver userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + refreshMessages(false); + } + }; + + + private void unregisterUserInfoObserver() { + if (userInfoObserver != null) { + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, false); + } + } + + ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + refreshMessages(false); + } + + @Override + public void onDeletedFriends(List accounts) { + refreshMessages(false); + } + + @Override + public void onAddUserToBlackList(List account) { + refreshMessages(false); + } + + @Override + public void onRemoveUserFromBlackList(List account) { + refreshMessages(false); + } + }; + + private void updateOfflineContactAited(final RecentContact recentContact) { + if (recentContact == null || recentContact.getSessionType() != SessionTypeEnum.Team + || recentContact.getUnreadCount() <= 0) { + return; + } + + // 锚点 + List uuid = new ArrayList<>(1); + uuid.add(recentContact.getRecentMessageId()); + + List messages = NIMClient.getService(MsgService.class).queryMessageListByUuidBlock(uuid); + + if (messages == null || messages.size() < 1) { + return; + } + final IMMessage anchor = messages.get(0); + + // 查未读消息 + NIMClient.getService(MsgService.class).queryMessageListEx(anchor, QueryDirectionEnum.QUERY_OLD, + recentContact.getUnreadCount() - 1, false).setCallback(new RequestCallbackWrapper>() { + + @Override + public void onResult(int code, List result, Throwable exception) { + if (code == ResponseCode.RES_SUCCESS && result != null) { + result.add(0, anchor); + Set messages = null; + // 过滤存在的@我的消息 + for (IMMessage msg : result) { + if (TeamMemberAitHelper.isAitMessage(msg)) { + if (messages == null) { + messages = new HashSet<>(); + } + messages.add(msg); + } + } + + // 更新并展示 + if (messages != null) { + TeamMemberAitHelper.setRecentContactAited(recentContact, messages); + notifyDataSetChanged(); + } + } + } + }); + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/TeamMemberAitHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/TeamMemberAitHelper.java new file mode 100644 index 0000000..bea905b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/TeamMemberAitHelper.java @@ -0,0 +1,128 @@ +package com.fengliyan.tianlesue.im.uikit.business.recent; + +import android.graphics.Color; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.MemberPushOption; +import com.netease.nimlib.sdk.msg.model.RecentContact; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by hzchenkang on 2016/12/5. + */ + +public class TeamMemberAitHelper { + + private static final String KEY_AIT = "ait"; + + public static String getAitAlertString(String content) { + return "[有人@你] " + content; + } + + public static void replaceAitForeground(String value, SpannableString mSpannableString) { + if (TextUtils.isEmpty(value) || TextUtils.isEmpty(mSpannableString)) { + return; + } + Pattern pattern = Pattern.compile("(\\[有人@你\\])"); + Matcher matcher = pattern.matcher(value); + while (matcher.find()) { + int start = matcher.start(); + if (start != 0) { + continue; + } + int end = matcher.end(); + mSpannableString.setSpan(new ForegroundColorSpan(Color.RED), start, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + } + } + + public static boolean isAitMessage(IMMessage message) { + if (message == null || message.getSessionType() != SessionTypeEnum.Team) { + return false; + } + MemberPushOption option = message.getMemberPushOption(); + boolean isForce = option != null && option.isForcePush() && + (option.getForcePushList() == null || option.getForcePushList().contains(NimUIKit.getAccount())); + + return isForce; + } + + public static boolean hasAitExtension(RecentContact recentContact) { + if (recentContact == null || recentContact.getSessionType() != SessionTypeEnum.Team) { + return false; + } + Map ext = recentContact.getExtension(); + if (ext == null) { + return false; + } + List mid = (List) ext.get(KEY_AIT); + + return mid != null && !mid.isEmpty(); + } + + public static void clearRecentContactAited(RecentContact recentContact) { + if (recentContact == null || recentContact.getSessionType() != SessionTypeEnum.Team) { + return; + } + Map exts = recentContact.getExtension(); + if (exts != null) { + exts.put(KEY_AIT, null); + } + recentContact.setExtension(exts); + NIMClient.getService(MsgService.class).updateRecent(recentContact); + } + + + public static void buildAitExtensionByMessage(Map extention, IMMessage message) { + + if (extention == null || message == null || message.getSessionType() != SessionTypeEnum.Team) { + return; + } + List mid = (List) extention.get(KEY_AIT); + if (mid == null) { + mid = new ArrayList<>(); + } + if (!mid.contains(message.getUuid())) { + mid.add(message.getUuid()); + } + extention.put(KEY_AIT, mid); + } + + public static void setRecentContactAited(RecentContact recentContact, Set messages) { + + if (recentContact == null || messages == null || + recentContact.getSessionType() != SessionTypeEnum.Team) { + return; + } + + Map extension = recentContact.getExtension(); + + if (extension == null) { + extension = new HashMap<>(); + } + + Iterator iterator = messages.iterator(); + while (iterator.hasNext()) { + IMMessage msg = iterator.next(); + buildAitExtensionByMessage(extension, msg); + } + + recentContact.setExtension(extension); + NIMClient.getService(MsgService.class).updateRecent(recentContact); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/adapter/RecentContactAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/adapter/RecentContactAdapter.java new file mode 100644 index 0000000..70a8bea --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/adapter/RecentContactAdapter.java @@ -0,0 +1,78 @@ +package com.fengliyan.tianlesue.im.uikit.business.recent.adapter; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.recent.RecentContactsCallback; +import com.fengliyan.tianlesue.im.uikit.business.recent.holder.CommonRecentViewHolder; +import com.fengliyan.tianlesue.im.uikit.business.recent.holder.TeamRecentViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; + +import java.util.List; + +/** + * Created by huangjun on 2016/12/11. + */ + +public class RecentContactAdapter extends BaseMultiItemQuickAdapter { + + interface ViewType { + int VIEW_TYPE_COMMON = 1; + int VIEW_TYPE_TEAM = 2; + } + + private RecentContactsCallback callback; + + public RecentContactAdapter(RecyclerView recyclerView, List data) { + super(recyclerView, data); + addItemType(ViewType.VIEW_TYPE_COMMON, R.layout.nim_recent_contact_list_item, CommonRecentViewHolder.class); + addItemType(ViewType.VIEW_TYPE_TEAM, R.layout.nim_recent_contact_list_item, TeamRecentViewHolder.class); + } + + @Override + protected int getViewType(RecentContact item) { + return item.getSessionType() == SessionTypeEnum.Team ? ViewType.VIEW_TYPE_TEAM : ViewType.VIEW_TYPE_COMMON; + } + + @Override + protected String getItemKey(RecentContact item) { + StringBuilder sb = new StringBuilder(); + sb.append(item.getSessionType().getValue()).append("_").append(item.getContactId()); + + return sb.toString(); + } + + public RecentContactsCallback getCallback() { + return callback; + } + + public void setCallback(RecentContactsCallback callback) { + this.callback = callback; + } + + // @Override +// public void onViewRecycled(@NonNull BaseViewHolder holder) { +// super.onViewRecycled(holder); +// View svgaView = holder.getView(R.id.svga_image_view); +// if (svgaView instanceof SVGAImageView) { +// Log.e(TAG, "onViewRecycled: -------->" + ((SVGAImageView) svgaView).isAnimating()); +// ((SVGAImageView) svgaView).stopAnimation(); +// } +// } +// +// @Override +// public void onViewAttachedToWindow(BaseViewHolder holder) { +// super.onViewAttachedToWindow(holder); +// View svgaView = holder.getView(R.id.svga_image_view); +// if (svgaView instanceof SVGAImageView) { +// SVGAImageView svgImageView = (SVGAImageView) svgaView; +// // 如果之前已设置过动画,则重新启动 +// if (svgImageView.getVisibility() == View.VISIBLE) { +// svgImageView.startAnimation(); +// } +// } +// } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/CommonRecentViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/CommonRecentViewHolder.java new file mode 100644 index 0000000..613b196 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/CommonRecentViewHolder.java @@ -0,0 +1,60 @@ +package com.fengliyan.tianlesue.im.uikit.business.recent.holder; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; + +public class CommonRecentViewHolder extends RecentViewHolder { + + CommonRecentViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + @Override + protected String getContent(RecentContact recent) { + return descOfMsg(recent); + } + + @Override + protected String getOnlineStateContent(RecentContact recent) { + if (recent.getSessionType() == SessionTypeEnum.P2P && NimUIKitImpl.enableOnlineState()) { + return NimUIKitImpl.getOnlineStateContentProvider().getSimpleDisplay(recent.getContactId()); + } else { + return super.getOnlineStateContent(recent); + } + } + + String descOfMsg(RecentContact recent) { + if (recent.getMsgType() == MsgTypeEnum.text) { + return recent.getContent(); + } else if (recent.getMsgType() == MsgTypeEnum.tip) { + String digest = null; + if (getCallback() != null) { + digest = getCallback().getDigestOfTipMsg(recent); + } + + if (digest == null) { + digest = NimUIKitImpl.getRecentCustomization().getDefaultDigest(recent); + } + + return digest; + } else if (recent.getAttachment() != null) { + +// SysInfoTextAttachment sysInfoTextAttachment = (SysInfoTextAttachment) recent.getAttachment(); + String digest = null; + if (getCallback() != null) { + digest = getCallback().getDigestOfAttachment(recent, recent.getAttachment()); + } + + if (digest == null) { + digest = NimUIKitImpl.getRecentCustomization().getDefaultDigest(recent); + } + + return digest; + } + + return "[未知]"; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/RecentViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/RecentViewHolder.java new file mode 100644 index 0000000..1503f16 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/RecentViewHolder.java @@ -0,0 +1,371 @@ +package com.fengliyan.tianlesue.im.uikit.business.recent.holder; + +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + + +import com.blankj.utilcode.util.ActivityUtils; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.recent.RecentContactsCallback; +import com.fengliyan.tianlesue.im.uikit.business.recent.RecentContactsFragment; +import com.fengliyan.tianlesue.im.uikit.business.recent.adapter.RecentContactAdapter; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.MoonUtil; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.drop.DropFake; +import com.fengliyan.tianlesue.im.uikit.common.ui.drop.DropManager; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.utils.ImageUtils; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.friend.FriendService; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.opensource.svgaplayer.SVGAImageView; + +import java.util.Map; + +public abstract class RecentViewHolder extends RecyclerViewHolder { + + public RecentViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + private int lastUnreadCount = 0; + + protected FrameLayout portraitPanel; + + protected HeadImageView imgHead; + + protected TextView tvNickname; + + protected TextView tvMessage; + + protected TextView tvDatetime; + + // 消息发送错误状态标记,目前没有逻辑处理 + protected ImageView imgMsgStatus; + + protected View bottomLine; + + protected View topLine; + + // 未读红点(一个占坑,一个全屏动画) + protected DropFake tvUnread; + + private ImageView imgUnreadExplosion; + + protected ImageView ivMsgMute; + + protected TextView tvOnlineState; + protected ImageView serviceImageView; + protected ImageView iv_anchor_tag; + protected SimpleDraweeView borderImageView; + protected SVGAImageView svga_image_view; + + // 子类覆写 + protected abstract String getContent(RecentContact recent); + + @Override + public void convert(BaseViewHolder holder, RecentContact data, int position, boolean isScrolling) { + inflate(holder, data); + refresh(holder, data, position); + } + + public void inflate(BaseViewHolder holder, final RecentContact recent) { + this.portraitPanel = holder.getView(R.id.portrait_panel); + this.imgHead = holder.getView(R.id.img_head); + this.tvNickname = holder.getView(R.id.tv_nickname); + this.tvMessage = holder.getView(R.id.tv_message); + this.serviceImageView = holder.getView(R.id.serviceImageView); + this.iv_anchor_tag = holder.getView(R.id.iv_anchor_tag); + this.tvUnread = holder.getView(R.id.unread_number_tip); + this.imgUnreadExplosion = holder.getView(R.id.unread_number_explosion); + this.ivMsgMute = holder.getView(R.id.iv_msg_mute); + this.tvDatetime = holder.getView(R.id.tv_date_time); + this.imgMsgStatus = holder.getView(R.id.img_msg_status); + this.bottomLine = holder.getView(R.id.bottom_line); + this.topLine = holder.getView(R.id.top_line); + this.tvOnlineState = holder.getView(R.id.tv_online_state); + this.borderImageView = holder.getView(R.id.borderImageView); + this.svga_image_view = holder.getView(R.id.svga_image_view); + holder.addOnClickListener(R.id.unread_number_tip); + + this.tvUnread.setTouchListener(new DropFake.ITouchListener() { + @Override + public void onDown() { + DropManager.getInstance().setCurrentId(recent); + DropManager.getInstance().down(tvUnread, tvUnread.getText()); + } + + @Override + public void onMove(float curX, float curY) { + DropManager.getInstance().move(curX, curY); + } + + @Override + public void onUp() { + DropManager.getInstance().up(); + } + }); + } + + public void refresh(BaseViewHolder holder, RecentContact recent, final int position) { + // unread count animation + boolean shouldBoom = lastUnreadCount > 0 && recent.getUnreadCount() == 0; // 未读数从N->0执行爆裂动画; + lastUnreadCount = recent.getUnreadCount(); + + updateBackground(holder, recent, position); + + loadPortrait(recent); + updateNickLabel(UserInfoHelper.getUserTitleName(recent.getContactId(), recent.getSessionType()), recent.getContactId()); + + updateOnlineState(recent); + + updateMsgLabel(holder, recent); + + updateNewIndicator(recent); + + NimUserInfo userInfo = NIMClient.getService(UserService.class).getUserInfo(recent.getContactId()); + String avatar_frame_url_str = null; + if (userInfo != null) { + Map ext = userInfo.getExtensionMap(); + if (ext != null) { + if (BuildConfig.IS_DEV) { + Log.e("TAG", "refresh: ----------->" + userInfo.getName() + ext); + } + Object anchor_tag = ext.get("anchor_tag"); + if (anchor_tag != null) { + if ((int) anchor_tag == 1) { + iv_anchor_tag.setVisibility(View.VISIBLE); + iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag1); + } else if ((int) anchor_tag == 2) { + iv_anchor_tag.setVisibility(View.VISIBLE); + iv_anchor_tag.setImageResource(R.drawable.ic_anchor_tag2); + } else { + iv_anchor_tag.setVisibility(View.GONE); + } + } else { + iv_anchor_tag.setVisibility(View.GONE); + } + + Object avatar_frame_url = ext.get("avatar_frame_url"); + Object avatar_frame_effect_url = ext.get("avatar_frame_effect_url"); + //是否展示头像框 + boolean isShowFrame = false; + if (UserManager.getUserInfo().isWomen() && !StrU.equals("4", recent.getContactId())) { + Object man_avatar_effect = ext.get("man_avatar_effect"); + if (man_avatar_effect != null) { + isShowFrame = (int) man_avatar_effect == 1; + } + } else { + Object hide_avatar = ext.get("hide_avatar"); + if (hide_avatar != null) { + isShowFrame = (int) hide_avatar == 1; + } + } + + //有后台配置的头像框则展示 + if (avatar_frame_url instanceof String && !StrU.isEmpty((String) avatar_frame_url)) { + borderImageView.setVisibility(View.VISIBLE); + borderImageView.setImageURI(ConstUrl.IMAGE_URL + avatar_frame_url); + if (avatar_frame_effect_url instanceof String && !StrU.isEmpty((String) avatar_frame_effect_url)) { + svga_image_view.setVisibility(View.VISIBLE); + avatar_frame_url_str = (String) avatar_frame_url; + ImageUtils.showSVGA(ActivityUtils.getTopActivity(), (String) avatar_frame_effect_url, svga_image_view); +// holder.setIsRecyclable(false); + } else { + svga_image_view.setVisibility(View.GONE); + } + } else { + if (isShowFrame) { + //没有则展示会员头像框 + svga_image_view.setVisibility(View.GONE); + borderImageView.setVisibility(View.VISIBLE); + if (UserManager.getUserInfo().isWomen() && !StrU.equals("4", recent.getContactId())) { + borderImageView.setImageResource(R.mipmap.privilege_avatar_border_man); + } else { + borderImageView.setImageResource(R.mipmap.privilege_avatar_border); + } + } else { + borderImageView.setVisibility(View.GONE); + svga_image_view.setVisibility(View.GONE); + } + } + } else { + iv_anchor_tag.setVisibility(View.GONE); + borderImageView.setVisibility(View.GONE); + svga_image_view.setVisibility(View.GONE); + } + } + if (recent.getContactId().equals("4")) { + serviceImageView.setVisibility(View.INVISIBLE); + } else { + serviceImageView.setVisibility(View.INVISIBLE); + } + if (shouldBoom) { + Object o = DropManager.getInstance().getCurrentId(); + if (o instanceof String && o.equals("0")) { + imgUnreadExplosion.setImageResource(R.drawable.nim_explosion); + imgUnreadExplosion.setVisibility(View.VISIBLE); + new Handler().post(new Runnable() { + @Override + public void run() { + ((AnimationDrawable) imgUnreadExplosion.getDrawable()).start(); + // 解决部分手机动画无法播放的问题(例如华为荣耀) + getAdapter().notifyItemChanged(getAdapter().getViewHolderPosition(position)); + } + }); + } + } else { + imgUnreadExplosion.setVisibility(View.GONE); + } + } + + //设置置顶背景 + private void updateBackground(BaseViewHolder holder, RecentContact recent, int position) { + if ((recent.getTag() & RecentContactsFragment.RECENT_TAG_STICKY) == 0) { + holder.getConvertView().setBackgroundResource(R.drawable.nim_touch_bg); +// bottomLine.setVisibility(getAdapter().isLastDataItem(position) ? View.VISIBLE : View.GONE); + topLine.setVisibility(View.GONE); + bottomLine.setVisibility(View.GONE); + } else { + //消息置顶背景颜色 + holder.getConvertView().setBackgroundResource(R.drawable.msg_sticky_bg); + topLine.setVisibility(getAdapter().isFirstDataItem(position) ? View.GONE : View.GONE); + bottomLine.setVisibility(View.GONE); + } + } + + protected void loadPortrait(RecentContact recent) { + // 设置头像 + if (recent.getSessionType() == SessionTypeEnum.P2P) { + if (recent.getContactId().equals("4")) { + imgHead.setImageResource(R.drawable.icon_msg_customer); + } else if (recent.getContactId().equals("2")) { + imgHead.setImageResource(R.drawable.icon_msg_notice); + } else { + imgHead.loadBuddyAvatar(recent.getContactId()); + } + } else if (recent.getSessionType() == SessionTypeEnum.Team) { + Team team = NimUIKit.getTeamProvider().getTeamById(recent.getContactId()); + imgHead.loadTeamIconByTeam(team); + } + if (recent.getContactId().equals("4")) { + imgHead.setImageResource(R.drawable.icon_msg_customer); + } + if (recent.getContactId().equals("2")) { + imgHead.setImageResource(R.drawable.icon_msg_notice); + } + } + + private void updateNewIndicator(RecentContact recent) { + boolean checkState = NIMClient.getService(FriendService.class).isNeedMessageNotify(recent.getContactId()); + if (checkState) { + ivMsgMute.setVisibility(View.GONE); + int unreadNum = recent.getUnreadCount(); + tvUnread.setText(unreadCountShowRule(unreadNum)); + tvUnread.setVisibility(unreadNum > 0 ? View.VISIBLE : View.GONE); + } else { + ivMsgMute.setVisibility(View.VISIBLE); + tvUnread.setVisibility(View.GONE); + } + } + + private void updateMsgLabel(BaseViewHolder holder, RecentContact recent) { + // 显示消息具体内容 + MoonUtil.identifyRecentVHFaceExpressionAndTags(holder.getContext(), tvMessage, getContent(recent), -1, 0.45f); + //tvMessage.setText(getContent()); + + MsgStatusEnum status = recent.getMsgStatus(); + switch (status) { + case fail: + imgMsgStatus.setImageResource(R.drawable.nim_g_ic_failed_small); + imgMsgStatus.setVisibility(View.VISIBLE); + break; + case sending: + imgMsgStatus.setImageResource(R.drawable.nim_recent_contact_ic_sending); + imgMsgStatus.setVisibility(View.VISIBLE); + break; + default: + imgMsgStatus.setVisibility(View.GONE); + break; + } + + String timeString = TimeUtil.getTimeShowString(recent.getTime(), true); + tvDatetime.setText(timeString); + } + + protected String getOnlineStateContent(RecentContact recent) { + return ""; + } + + protected void updateOnlineState(RecentContact recent) { + if (recent.getSessionType() == SessionTypeEnum.Team) { + tvOnlineState.setVisibility(View.GONE); + } else { + String onlineStateContent = getOnlineStateContent(recent); + if (TextUtils.isEmpty(onlineStateContent)) { + tvOnlineState.setVisibility(View.GONE); + } else { + tvOnlineState.setVisibility(View.VISIBLE); + tvOnlineState.setText(getOnlineStateContent(recent)); + } + } + } + + protected void updateNickLabel(String nick, String id) { + int labelWidth = ScreenUtil.screenWidth; + labelWidth -= ScreenUtil.dip2px(50 + 70); // 减去固定的头像和时间宽度 + + if (labelWidth > 0) { + tvNickname.setMaxWidth(labelWidth); + } + + if (!TextUtils.isEmpty(id)) { + if ("2".equals(id) || "4".equals(id) || "11".equals(id) || "3".equals(id) || "5".equals(id) + || "6".equals(id) || "7".equals(id) || "8".equals(id) || "9".equals(id) || "10".equals(id)) { +// int colorBlue = Color.parseColor("#26a1f4"); + int colorBlue = Color.parseColor("#000000"); + tvNickname.setTextColor(colorBlue); + } else { + int colorBlack = Color.parseColor("#000000"); + tvNickname.setTextColor(colorBlack); + } + } + if ("4".equals(id)) { + tvNickname.setText("官方客服"); + } else { + tvNickname.setText(nick); + } + } + + protected String unreadCountShowRule(int unread) { + unread = Math.min(unread, 99); + return String.valueOf(unread); + } + + protected RecentContactsCallback getCallback() { + return ((RecentContactAdapter) getAdapter()).getCallback(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/TeamRecentViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/TeamRecentViewHolder.java new file mode 100644 index 0000000..fa9caab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/recent/holder/TeamRecentViewHolder.java @@ -0,0 +1,45 @@ +package com.fengliyan.tianlesue.im.uikit.business.recent.holder; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.recent.TeamMemberAitHelper; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.netease.nimlib.sdk.msg.attachment.NotificationAttachment; +import com.netease.nimlib.sdk.msg.model.RecentContact; + +public class TeamRecentViewHolder extends CommonRecentViewHolder { + + public TeamRecentViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + @Override + protected String getContent(RecentContact recent) { + String content = descOfMsg(recent); + + String fromId = recent.getFromAccount(); + if (!TextUtils.isEmpty(fromId) + && !fromId.equals(NimUIKit.getAccount()) + && !(recent.getAttachment() instanceof NotificationAttachment)) { + String tid = recent.getContactId(); + String teamNick = getTeamUserDisplayName(tid, fromId); + content = teamNick + ": " + content; + + if (TeamMemberAitHelper.hasAitExtension(recent)) { + if (recent.getUnreadCount() == 0) { + TeamMemberAitHelper.clearRecentContactAited(recent); + } else { + content = TeamMemberAitHelper.getAitAlertString(content); + } + } + } + + return content; + } + + private String getTeamUserDisplayName(String tid, String account) { + return TeamHelper.getTeamMemberDisplayName(tid, account); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotBotContent.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotBotContent.java new file mode 100644 index 0000000..96829d4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotBotContent.java @@ -0,0 +1,25 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.model; + +import java.io.Serializable; + +/** + * Created by hzchenkang on 2017/6/30. + */ + +public class RobotBotContent implements Serializable { + private String botMsg; + private String type; + + public RobotBotContent(String botMsg, String type) { + this.botMsg = botMsg; + this.type = type; + } + + public String getType() { + return type; + } + + public String getBotMsg() { + return botMsg; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotFaqContent.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotFaqContent.java new file mode 100644 index 0000000..3edd70c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotFaqContent.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.model; + +import java.io.Serializable; + +/** + * Created by hzchenkang on 2017/6/30. + */ + +public class RobotFaqContent implements Serializable { + + private String faqMsg; + + private int score; + + public RobotFaqContent(String faqMsg, int score) { + this.faqMsg = faqMsg; + this.score = score; + } + + public int getScore() { + return score; + } + + public String getFaqMsg() { + return faqMsg; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotResponseContent.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotResponseContent.java new file mode 100644 index 0000000..e95db79 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/model/RobotResponseContent.java @@ -0,0 +1,119 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.model; + +import android.text.TextUtils; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by hzchenkang on 2017/6/26. + */ + +public class RobotResponseContent implements Serializable { + + public static final String FLAG_BOT = "bot"; + public static final String FLAG_FAQ = "faq"; + + // 机器人下行消息实体,xml 格式 + + private String flag; + + private String s; + + private List botContents; + + private List faqContents; + + private static final String KEY_MSG = "message"; + private static final String KEY_CONTENT = "content"; + private static final String KEY_FLAG = "flag"; + private static final String KEY_S = "s"; + private static final String KEY_TYPE = "type"; + + // faq + private static final String KEY_MATCH = "match"; + private static final String KEY_ANSWER = "answer"; + private static final String KEY_ANSWER_TYPE = "answer_type"; + private static final String QUERY = "query"; + private static final String KEY_SCORE = "score"; + + public static final String RES_TYPE_BOT_TEXT = "01"; + public static final String RES_TYPE_BOT_IMAGE = "02"; + public static final String RES_TYPE_BOT_QUICK = "03"; + public static final String RES_TYPE_BOT_COMP = "11"; + + public String getFlag() { + return flag; + } + + public List getBotContents() { + return botContents; + } + + public List getFaqContents() { + return faqContents; + } + + public String getMaxScoreFaqContent() { + if (faqContents == null) { + return null; + } + int maxScore = -1; + RobotFaqContent result = null; + + for (RobotFaqContent faqContent : faqContents) { + if (faqContent.getScore() > maxScore) { + result = faqContent; + maxScore = result.getScore(); + } + } + + return result == null ? null : result.getFaqMsg(); + } + + public RobotResponseContent(String jsonString) { + if (jsonString == null) { + return; + } + JSONObject json = JSONObject.parseObject(jsonString); + if (json == null) { + return; + } + flag = json.getString(KEY_FLAG); + s = json.getString(KEY_S); + if (TextUtils.isEmpty(flag)) { + return; + } + if (flag.equals(FLAG_BOT)) { + JSONArray msgArray = json.getJSONArray(KEY_MSG); + // 解消息 + if (msgArray != null && msgArray.size() >= 0) { + botContents = new ArrayList<>(); + for (int i = 0; i < msgArray.size(); i++) { + JSONObject msgJson = msgArray.getJSONObject(i); + String botMsg = msgJson.getString(KEY_CONTENT); + String type = msgJson.getString(KEY_TYPE); + RobotBotContent content = new RobotBotContent(botMsg, type); + botContents.add(content); + } + } + } else if (flag.equals(FLAG_FAQ)) { + JSONObject msg = json.getJSONObject(KEY_MSG); + JSONArray array = msg.getJSONArray(KEY_MATCH); + if (array != null && array.size() >= 0) { + faqContents = new ArrayList<>(); + for (int i = 0; i < array.size(); i++) { + JSONObject msgJson = array.getJSONObject(i); + String faqMsg = msgJson.getString(KEY_ANSWER); + int score = msgJson.getIntValue(KEY_SCORE); + RobotFaqContent content = new RobotFaqContent(faqMsg, score); + faqContents.add(content); + } + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/Element.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/Element.java new file mode 100644 index 0000000..c682d1b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/Element.java @@ -0,0 +1,14 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by huangjun on 2017/6/22. + *

+ * 元素,只有属性,不支持嵌套 + */ + +public abstract class Element { + public abstract void parse(JSONObject jsonObject) throws JSONException; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/ElementGroup.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/ElementGroup.java new file mode 100644 index 0000000..eb5a0f1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/ElementGroup.java @@ -0,0 +1,39 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by huangjun on 2017/6/22. + *

+ * 支持嵌套的容器 + */ + +public abstract class ElementGroup extends Element { + + private List elements; + + protected void addElement(T e) { + if (elements == null) { + elements = new ArrayList<>(); + } + + if (e != null) { + elements.add(e); + } + } + + protected void addElements(List es) { + if (elements == null) { + elements = new ArrayList<>(); + } + + if (es != null) { + elements.addAll(es); + } + } + + public List getElements() { + return elements; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/ElementTag.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/ElementTag.java new file mode 100644 index 0000000..b6a1297 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/base/ElementTag.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base; + +/** + * Created by huangjun on 2017/6/23. + */ + +public final class ElementTag { + // xml + public static final String XML_HEADER_PREFIX = ""; + + // node + public static final String ELEMENT_LABEL_TEMPLATE = "template"; + public static final String ELEMENT_LABEL_TEXT = "text"; + public static final String ELEMENT_LABEL_IMAGE = "image"; + public static final String ELEMENT_LABEL_LINK = "link"; + public static final String ELEMENT_LABEL_LINEAR_LAYOUT = "LinearLayout"; + + // attr + public static final String ELEMENT_ATTRIBUTE_ID = "id"; + public static final String ELEMENT_ATTRIBUTE_NAME = "name"; + public static final String ELEMENT_ATTRIBUTE_CONTENT = "content"; + public static final String ELEMENT_ATTRIBUTE_PARAMS = "params"; + public static final String ELEMENT_ATTRIBUTE_VERSION = "version"; + public static final String ELEMENT_ATTRIBUTE_WIDTH = "width"; + public static final String ELEMENT_ATTRIBUTE_HEIGHT = "height"; + public static final String ELEMENT_ATTRIBUTE_COLOR = "color"; + public static final String ELEMENT_ATTRIBUTE_URL = "url"; + public static final String ELEMENT_ATTRIBUTE_TYPE = "type"; + public static final String ELEMENT_ATTRIBUTE_STYLE = "style"; + public static final String ELEMENT_ATTRIBUTE_TARGET = "target"; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/element/ImageElement.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/element/ImageElement.java new file mode 100644 index 0000000..f3c2ffa --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/element/ImageElement.java @@ -0,0 +1,69 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementTag; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.helper.ElementParseHelper; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by huangjun on 2017/6/22. + *

+ * + */ + +public class ImageElement extends Element { + private String name; + private String url; + private int width; + private boolean widthUsePercent = true; // 默认用百分比 + private int height; + private boolean heightUsePercent = true; // 默认用百分比 + + @Override + public void parse(JSONObject jsonObject) throws JSONException { + name = jsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_NAME); + url = jsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_URL); + + if (jsonObject.has(ElementTag.ELEMENT_ATTRIBUTE_WIDTH)) { + ElementParseHelper.Value v = ElementParseHelper.getValue(jsonObject.getString(ElementTag.ELEMENT_ATTRIBUTE_WIDTH)); + if (v != null) { + width = v.getValue(); + widthUsePercent = v.isPercent(); + } + } + + if (jsonObject.has(ElementTag.ELEMENT_ATTRIBUTE_HEIGHT)) { + ElementParseHelper.Value v = ElementParseHelper.getValue(jsonObject.getString(ElementTag.ELEMENT_ATTRIBUTE_HEIGHT)); + if (v != null) { + height = v.getValue(); + heightUsePercent = v.isPercent(); + } + } + } + + public String getName() { + return name; + } + + public String getUrl() { + return url; + } + + public int getWidth() { + return width; + } + + public boolean isWidthUsePercent() { + return widthUsePercent; + } + + public int getHeight() { + return height; + } + + public boolean isHeightUsePercent() { + return heightUsePercent; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/element/TextElement.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/element/TextElement.java new file mode 100644 index 0000000..e4a36a1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/element/TextElement.java @@ -0,0 +1,60 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementTag; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.helper.ElementParseHelper; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by huangjun on 2017/6/22. + *

+ * 文本内容 + */ + +public class TextElement extends Element { + private String name; + private String content; + private int width = -1; + private boolean widthUsePercent = true; // 默认用百分比 + private String color; + + @Override + public void parse(JSONObject jsonObject) throws JSONException { + name = jsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_NAME); + content = jsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_CONTENT); + + if (jsonObject.has(ElementTag.ELEMENT_ATTRIBUTE_WIDTH)) { + ElementParseHelper.Value v = ElementParseHelper.getValue(jsonObject.getString(ElementTag.ELEMENT_ATTRIBUTE_WIDTH)); + if (v != null) { + width = v.getValue(); + widthUsePercent = v.isPercent(); + } + } + + if (jsonObject.has(ElementTag.ELEMENT_ATTRIBUTE_COLOR)) { + color = jsonObject.getString(ElementTag.ELEMENT_ATTRIBUTE_COLOR); + } + } + + public String getName() { + return name; + } + + public String getContent() { + return content; + } + + public int getWidth() { + return width; + } + + public boolean isWidthUsePercent() { + return widthUsePercent; + } + + public String getColor() { + return color; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/LinearLayout.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/LinearLayout.java new file mode 100644 index 0000000..16fab49 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/LinearLayout.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementGroup; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.helper.ElementParseHelper; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by huangjun on 2017/6/22. + *

+ * 节点下面存在三种节点,分别是 ; + * 目前的静态组合形式有 +Array( ), ,Array( ) + * 后期会增加 + +Array( ) + */ + +public class LinearLayout extends ElementGroup { + + @Override + public void parse(JSONObject rootJsonObject) throws JSONException { + addElements(ElementParseHelper.getElements(rootJsonObject)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/LinkElement.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/LinkElement.java new file mode 100644 index 0000000..949af1f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/LinkElement.java @@ -0,0 +1,55 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementGroup; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementTag; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.helper.ElementParseHelper; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by huangjun on 2017/6/22. + *

+ * + * + * 当顿庄园 澳洲进口牛肉腌制菲力牛排1200克8片装套餐 + * 99 + * 1 + * 待发货 + * + */ + +public class LinkElement extends ElementGroup { + private String type; + private String style; + private String target; + private String params; + public static final String TYPE_BLOCK = "block"; + public static final String TYPE_URL = "url"; + + @Override + public void parse(JSONObject rootJsonObject) throws JSONException { + type = rootJsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_TYPE); + style = rootJsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_STYLE); + target = rootJsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_TARGET); + params = rootJsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_PARAMS); + addElements(ElementParseHelper.getElements(rootJsonObject)); + } + + public String getType() { + return type; + } + + public String getStyle() { + return style; + } + + public String getTarget() { + return target; + } + + public String getParams() { + return params; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/TemplateRoot.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/TemplateRoot.java new file mode 100644 index 0000000..fde77c1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/group/TemplateRoot.java @@ -0,0 +1,84 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementGroup; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementTag; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.XML; + +/** + * 根元素,解析器入口 + *

+ * Created by huangjun on 2017/6/22. + */ + +public class TemplateRoot extends ElementGroup { + // attr + private String templateId; // 模板编号 + private String globalParams; // 全局变量 + private String version; // 协议版本号 + + // log + private String jsonString; // xml2JsonString + + public TemplateRoot(String xml) { + try { + if (!xml.contains(ElementTag.XML_HEADER_PREFIX)) { + xml = ElementTag.XML_HEADER + xml; + } + JSONObject rootJsonObject = XML.toJSONObject(xml); + parse(rootJsonObject); + jsonString = rootJsonObject.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void parse(JSONObject rootJsonObject) throws JSONException { + JSONObject jsonObject = rootJsonObject.getJSONObject(ElementTag.ELEMENT_LABEL_TEMPLATE); + + templateId = jsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_ID); + globalParams = jsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_PARAMS); + version = jsonObject.optString(ElementTag.ELEMENT_ATTRIBUTE_VERSION); + + if (jsonObject.has(ElementTag.ELEMENT_LABEL_LINEAR_LAYOUT)) { + + JSONObject object = jsonObject.optJSONObject(ElementTag.ELEMENT_LABEL_LINEAR_LAYOUT); + if (object != null) { + LinearLayout linearLayout = new LinearLayout(); + linearLayout.parse(object); + addElement(linearLayout); + } else { + JSONArray array = jsonObject.optJSONArray(ElementTag.ELEMENT_LABEL_LINEAR_LAYOUT); + if (array != null && array.length() > 0) { + for (int i = 0; i < array.length(); i++) { + JSONObject obj = array.getJSONObject(i); + LinearLayout linearLayout = new LinearLayout(); + linearLayout.parse(obj); + addElement(linearLayout); + } + } + } + } + } + + public String getTemplateId() { + return templateId; + } + + public String getGlobalParams() { + return globalParams; + } + + public String getVersion() { + return version; + } + + @Override + public String toString() { + return jsonString; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/helper/ElementParseHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/helper/ElementParseHelper.java new file mode 100644 index 0000000..953749e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/robot/parser/elements/helper/ElementParseHelper.java @@ -0,0 +1,128 @@ +package com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.helper; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.ElementTag; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.ImageElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.TextElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.LinkElement; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * 元素解析器辅助类 + *

+ * Created by huangjun on 2017/6/23. + */ + +public class ElementParseHelper { + public static class Value { + private int value; + private boolean percent; + + Value(int value, boolean percent) { + this.value = value; + this.percent = percent; + } + + public int getValue() { + return value; + } + + public boolean isPercent() { + return percent; + } + } + + public static Value getValue(String number) { + if (TextUtils.isEmpty(number)) { + return null; + } + + boolean percent = number.contains("%"); + number = number.trim().replaceAll("%", ""); + int value = 0; + + try { + value = Integer.parseInt(number); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + + return new Value(value, percent); + } + + public static int getIntFromHex(String value, int def) { + int result = def; + try { + result = Integer.parseInt(value, 16); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + return result; + } + + public static List getElements(JSONObject rootJsonObject) throws JSONException { + List elements = new ArrayList<>(); + + Iterator keys = rootJsonObject.keys(); + String tag; + while (keys.hasNext()) { + tag = keys.next(); + if (!canParseElement(tag)) { + continue; + } + + // parse recursive + Object o = rootJsonObject.get(tag); + if (o instanceof JSONObject) { + parseElement((JSONObject) o, tag, elements); + } else if (o instanceof JSONArray) { + parseElements((JSONArray) o, tag, elements); // 可能一次性把所有text拿出来了 + } + } + + return elements; + } + + private static void parseElements(final JSONArray array, final String tag, final List elements) throws JSONException { + for (int i = 0; i < array.length(); i++) { + parseElement(array.getJSONObject(i), tag, elements); + } + } + + private static void parseElement(final JSONObject obj, final String tag, final List elements) throws JSONException { + Element e = null; + switch (tag) { + case ElementTag.ELEMENT_LABEL_TEXT: + e = new TextElement(); + break; + case ElementTag.ELEMENT_LABEL_IMAGE: + e = new ImageElement(); + break; + case ElementTag.ELEMENT_LABEL_LINK: + e = new LinkElement(); + break; + default: + break; + } + + if (e != null && obj != null) { + e.parse(obj); + elements.add(e); + } + } + + private static boolean canParseElement(final String tag) { + return tag.equals(ElementTag.ELEMENT_LABEL_TEXT) || + tag.equals(ElementTag.ELEMENT_LABEL_IMAGE) || + tag.equals(ElementTag.ELEMENT_LABEL_LINK); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/BaseAction.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/BaseAction.java new file mode 100644 index 0000000..c7893e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/BaseAction.java @@ -0,0 +1,93 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.actions; + +import android.app.Activity; +import android.content.Intent; + +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.Serializable; +import java.lang.ref.WeakReference; + +/** + * Action基类。
+ * 注意:在子类中调用startActivityForResult时,requestCode必须用makeRequestCode封装一遍,否则不能再onActivityResult中收到结果。 + * requestCode仅能使用最低8位。 + */ +public abstract class BaseAction implements Serializable { + + private int iconResId; + + private int titleId; + + private transient int index; + + // Container持有activity , 防止内存泄露 + private transient WeakReference containerRef; + + /** + * 构造函数 + * + * @param iconResId 图标 res id + * @param titleId 图标标题的string res id + */ + protected BaseAction(int iconResId, int titleId) { + this.iconResId = iconResId; + this.titleId = titleId; + } + + public Activity getActivity() { + return getContainer().activity; + } + + public String getAccount() { + return getContainer().account; + } + + public SessionTypeEnum getSessionType() { + return getContainer().sessionType; + } + + public int getIconResId() { + return iconResId; + } + + public int getTitleId() { + return titleId; + } + + public Container getContainer() { + Container container = containerRef.get(); + if (container == null) { + throw new RuntimeException("container be recycled by vm "); + } + return container; + } + + public abstract void onClick(); + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + // default: empty + } + + protected void sendMessage(IMMessage message) { + getContainer().proxy.sendMessage(message); + } + + protected int makeRequestCode(int requestCode) { + if ((requestCode & 0xffffff00) != 0) { + throw new IllegalArgumentException("Can only use lower 8 bits for requestCode"); + } + return ((index + 1) << 8) + (requestCode & 0xff); + } + + public void setContainer(Container container) { + this.containerRef = new WeakReference<>(container); + } + + public void setIndex(int index) { + this.index = index; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/ImageAction.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/ImageAction.java new file mode 100644 index 0000000..79e537d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/ImageAction.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.actions; + +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.File; + +/** + * Created by hzxuwen on 2015/6/12. + */ +public class ImageAction extends PickImageAction { + + public ImageAction() { + super(R.drawable.nim_message_plus_photo_selector, R.string.input_panel_photo, true); + } + + @Override + protected void onPicked(File file) { + IMMessage message; + if (getContainer() != null && getContainer().sessionType == SessionTypeEnum.ChatRoom) { + message = ChatRoomMessageBuilder.createChatRoomImageMessage(getAccount(), file, file.getName()); + } else { + message = MessageBuilder.createImageMessage(getAccount(), getSessionType(), file, file.getName()); + } + sendMessage(message); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/LocationAction.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/LocationAction.java new file mode 100644 index 0000000..e5f13a9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/LocationAction.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.actions; + +import com.fengliyan.tianlesue.im.uikit.api.model.location.LocationProvider; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * Created by hzxuwen on 2015/6/12. + */ +public class LocationAction extends BaseAction { + private final static String TAG = "LocationAction"; + + public LocationAction() { + super(R.drawable.nim_message_plus_location_selector, R.string.input_panel_location); + } + + @Override + public void onClick() { + if (NimUIKitImpl.getLocationProvider() != null) { + NimUIKitImpl.getLocationProvider().requestLocation(getActivity(), new LocationProvider.Callback() { + @Override + public void onSuccess(double longitude, double latitude, String address) { + IMMessage message = MessageBuilder.createLocationMessage(getAccount(), getSessionType(), latitude, longitude, + address); + sendMessage(message); + } + }); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/PickImageAction.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/PickImageAction.java new file mode 100644 index 0000000..ec2f7b7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/PickImageAction.java @@ -0,0 +1,198 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.actions; + +import android.content.Intent; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.RequestCode; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.SendImageHelper; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.PickImageHelper; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.activity.PickImageActivity; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.activity.PreviewImageFromCameraActivity; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.R; + +import java.io.File; + +/** + * Created by zhoujianghua on 2015/7/31. + */ +public abstract class PickImageAction extends BaseAction { + + private static final int PICK_IMAGE_COUNT = 9; + private static final int PORTRAIT_IMAGE_WIDTH = 720; + + public static final String MIME_JPEG = "image/jpeg"; + public static final String JPG = ".jpg"; + + private boolean multiSelect; + private boolean crop = false; + + protected abstract void onPicked(File file); + + protected PickImageAction(int iconResId, int titleId, boolean multiSelect) { + super(iconResId, titleId); + this.multiSelect = multiSelect; + } + + @Override + public void onClick() { + int requestCode = makeRequestCode(RequestCode.PICK_IMAGE); + showSelector(getTitleId(), requestCode, multiSelect, tempFile()); + +// PermissionHelper.request(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, +// new AbsPermissionResultCallBack() { +// @Override +// public void onPermissionGranted() { +// permissionDialog.dismiss(); +// int requestCode = makeRequestCode(RequestCode.PICK_IMAGE); +// showSelector(getTitleId(), requestCode, multiSelect, tempFile()); +// } +// +// @Override +// public void onPermissionDenied(String... permissions) { +// String market = DeviceManager.getInstance().getApplicationMarket(); +// if (market != null && market.equals("huawei")) { +// permissionDialog.dismiss(); +// return; +// } +// super.onPermissionDenied(permissions); +// permissionDialog.dismiss(); +// } +// }); + } + + private String tempFile() { + String filename = StringUtil.get32UUID() + JPG; + return StorageUtil.getWritePath(filename, StorageType.TYPE_TEMP); + } + + /** + * 打开图片选择器 + */ + private void showSelector(int titleId, final int requestCode, final boolean multiSelect, final String outPath) { + PickImageHelper.PickImageOption option = new PickImageHelper.PickImageOption(); + option.titleResId = titleId; + option.multiSelect = multiSelect; + option.multiSelectMaxCount = PICK_IMAGE_COUNT; + option.crop = crop; + option.cropOutputImageWidth = PORTRAIT_IMAGE_WIDTH; + option.cropOutputImageHeight = PORTRAIT_IMAGE_WIDTH; + option.outputPath = outPath; + + PickImageHelper.pickImage(getActivity(), requestCode, option); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case RequestCode.PICK_IMAGE: + onPickImageActivityResult(requestCode, data); + break; + case RequestCode.PREVIEW_IMAGE_FROM_CAMERA: + onPreviewImageActivityResult(requestCode, data); + break; + } + } + + /** + * 图片选取回调 + */ + private void onPickImageActivityResult(int requestCode, Intent data) { + if (data == null) { + ToastHelper.showToastLong(getActivity(), R.string.picker_image_error); + return; + } + boolean local = data.getBooleanExtra(Extras.EXTRA_FROM_LOCAL, false); + if (local) { + // 本地相册 + sendImageAfterSelfImagePicker(data); + } else { + // 拍照 + Intent intent = new Intent(); + if (!handleImagePath(intent, data)) { + return; + } + + intent.setClass(getActivity(), PreviewImageFromCameraActivity.class); + getActivity().startActivityForResult(intent, makeRequestCode(RequestCode.PREVIEW_IMAGE_FROM_CAMERA)); + } + } + + /** + * 是否可以获取图片 + */ + private boolean handleImagePath(Intent intent, Intent data) { + String photoPath = data.getStringExtra(Extras.EXTRA_FILE_PATH); + if (TextUtils.isEmpty(photoPath)) { + ToastHelper.showToast(getActivity(), R.string.picker_image_error); + return false; + } + + File imageFile = new File(photoPath); + intent.putExtra("OrigImageFilePath", photoPath); + File scaledImageFile = ImageUtil.getScaledImageFileWithMD5(imageFile, MIME_JPEG); + + boolean local = data.getExtras().getBoolean(Extras.EXTRA_FROM_LOCAL, true); + if (!local) { + // 删除拍照生成的临时文件 + AttachmentStore.delete(photoPath); + } + + if (scaledImageFile == null) { + ToastHelper.showToast(getActivity(), R.string.picker_image_error); + return false; + } else { + ImageUtil.makeThumbnail(scaledImageFile); + } + intent.putExtra("ImageFilePath", scaledImageFile.getAbsolutePath()); + return true; + } + + /** + * 从预览界面点击发送图片 + */ + private void sendImageAfterPreviewPhotoActivityResult(Intent data) { + SendImageHelper.sendImageAfterPreviewPhotoActivityResult(data, new SendImageHelper.Callback() { + + @Override + public void sendImage(File file, boolean isOrig) { + onPicked(file); + } + }); + } + + /** + * 发送图片 + */ + private void sendImageAfterSelfImagePicker(final Intent data) { + SendImageHelper.sendImageAfterSelfImagePicker(getActivity(), data, new SendImageHelper.Callback() { + + @Override + public void sendImage(File file, boolean isOrig) { + onPicked(file); + } + }); + } + + /** + * 拍摄回调 + */ + private void onPreviewImageActivityResult(int requestCode, Intent data) { + if (data.getBooleanExtra(PreviewImageFromCameraActivity.RESULT_SEND, false)) { + sendImageAfterPreviewPhotoActivityResult(data); + } else if (data.getBooleanExtra(PreviewImageFromCameraActivity.RESULT_RETAKE, false)) { + String filename = StringUtil.get32UUID() + JPG; + String path = StorageUtil.getWritePath(filename, StorageType.TYPE_TEMP); + + if (requestCode == RequestCode.PREVIEW_IMAGE_FROM_CAMERA) { + PickImageActivity.start(getActivity(), makeRequestCode(RequestCode.PICK_IMAGE), PickImageActivity.FROM_CAMERA, path); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/VideoAction.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/VideoAction.java new file mode 100644 index 0000000..00fd643 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/actions/VideoAction.java @@ -0,0 +1,224 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.actions; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.Base64; + +import com.google.gson.Gson; +import com.fengliyan.tianlesue.agora.utils.ToastUtil; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.RequestCode; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.VideoMessageHelper; +import com.fengliyan.tianlesue.model.chat.ImageCheckBean; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.settings.video.ExtractFrameWorkThread; +import com.fengliyan.tianlesue.view.settings.video.ExtractVideoInfoUtil; +import com.fengliyan.tianlesue.view.settings.video.PictureUtils; +import com.fengliyan.tianlesue.view.settings.video.VideoEditInfo; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by hzxuwen on 2015/6/12. + */ +public class VideoAction extends BaseAction { + + // 视频 + protected transient VideoMessageHelper videoMessageHelper; + + public VideoAction() { + super(R.drawable.nim_message_plus_video_selector, R.string.input_panel_video); + + } + + private ExtractFrameWorkThread mExtractFrameWorkThread; + private long endPosition; + private final List pornList = new ArrayList<>(); + private int thumbnailsCount; + private String videoMd5; + private File videoFile; + private String OutPutFileDirPath; + private ExtractVideoInfoUtil mExtractVideoInfoUtil; + private PermissionDialog permissionDialog; + + @Override + public void onClick() { + //权限允许 + videoHelper().showVideoSource(makeRequestCode(RequestCode.GET_LOCAL_VIDEO), makeRequestCode(RequestCode.CAPTURE_VIDEO)); + +// PermissionHelper.request(new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, +// new AbsPermissionResultCallBack() { +// @Override +// public void onPermissionGranted() { +// permissionDialog.dismiss(); +// videoHelper().showVideoSource(makeRequestCode(RequestCode.GET_LOCAL_VIDEO), makeRequestCode(RequestCode.CAPTURE_VIDEO)); +// } +// +// @Override +// public void onPermissionDenied(String... permissions) { +// String market = DeviceManager.getInstance().getApplicationMarket(); +// if (market != null && market.equals("huawei")) { +// permissionDialog.dismiss(); +// return; +// } +// super.onPermissionDenied(permissions); +// permissionDialog.dismiss(); +// } +// }); + } + + /** + * ********************** 视频 ******************************* + */ + private void initVideoMessageHelper() { + videoMessageHelper = new VideoMessageHelper(getActivity(), new VideoMessageHelper.VideoMessageHelperListener() { + + @Override + public void onVideoPicked(File file, String md5) { + //视频截帧鉴黄 + videoMd5 = md5; + videoFile = file; + pornList.clear(); + thumbnailsCount = NoClearSPUtils.getInt(getActivity(), ConsUser.SEND_VIDEO_MAX_NUM); + int interval = NoClearSPUtils.getInt(getActivity(), ConsUser.SEND_VIDEO_INTERVAL) * 1000; + OutPutFileDirPath = PictureUtils.getSaveEditThumbnailDir(getActivity()); + mExtractVideoInfoUtil = new ExtractVideoInfoUtil(file.getAbsolutePath()); + long duration = Long.parseLong(mExtractVideoInfoUtil.getVideoLength()); + int length = interval * thumbnailsCount; + if (length > duration) { + thumbnailsCount = (int) (duration / interval); + endPosition = (long) interval * thumbnailsCount; + if (thumbnailsCount < 1) { + thumbnailsCount = 1; + endPosition = duration; + } + } else { + endPosition = length; + } + int extractW = mExtractVideoInfoUtil.getVideoWidth(); + int extractH = mExtractVideoInfoUtil.getVideoHeight(); + mExtractFrameWorkThread = new ExtractFrameWorkThread(extractW, extractH, mUIHandler, file.getAbsolutePath(), OutPutFileDirPath, 0, endPosition, thumbnailsCount); + mExtractFrameWorkThread.start(); + } + }); + } + + Handler mUIHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == ExtractFrameWorkThread.MSG_SAVE_SUCCESS) { + checkVideo(msg); + } + } + }; + + //视频鉴黄 + private void checkVideo(Message msg) { + VideoEditInfo info = (VideoEditInfo) msg.obj; + final Bitmap bitmap = BitmapFactory.decodeFile(info.path); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + if (bitmap != null) { + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); //参数100表示不压缩 + } + String img = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT); + pornList.add(img); + if (pornList.size() == thumbnailsCount) { + String s = new Gson().toJson(pornList); + SettingManager.videoCheck((BaseActivity) getActivity(), s, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ImageCheckBean result, String tips) { + destroyWork(); + if (result.getIs_upload() == 1) { + MediaPlayer mediaPlayer = getVideoMediaPlayer(videoFile); + long duration = mediaPlayer == null ? 0 : mediaPlayer.getDuration(); + int height = mediaPlayer == null ? 0 : mediaPlayer.getVideoHeight(); + int width = mediaPlayer == null ? 0 : mediaPlayer.getVideoWidth(); + IMMessage message = MessageBuilder.createVideoMessage(getAccount(), getSessionType(), videoFile, duration, width, height, videoMd5); + VideoAction.this.sendMessage(message); + } else { + MaleToast.showMessage(activity, "视频违规"); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + destroyWork(); + ToastUtil.showToast(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + destroyWork(); + ToastUtil.showToast(activity, "发送失败" + e.getMessage()); + } + }); + } + } + + //释放相关资源 + private void destroyWork() { + if (mExtractFrameWorkThread != null) { + mExtractFrameWorkThread.stopExtract(); + } + if (mExtractVideoInfoUtil != null) { + mExtractVideoInfoUtil.release(); + } + if (!TextUtils.isEmpty(OutPutFileDirPath)) { + PictureUtils.deleteFile(new File(OutPutFileDirPath)); + } + if (mUIHandler != null) { + mUIHandler.removeCallbacksAndMessages(null); + } + } + + /** + * 获取视频mediaPlayer + * + * @param file 视频文件 + * @return mediaPlayer + */ + private MediaPlayer getVideoMediaPlayer(File file) { + try { + return MediaPlayer.create(getActivity(), Uri.fromFile(file)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case RequestCode.GET_LOCAL_VIDEO: + videoHelper().onGetLocalVideoResult(data); + break; + case RequestCode.CAPTURE_VIDEO: + videoHelper().onCaptureVideoResult(data); + break; + } + } + + private VideoMessageHelper videoHelper() { + if (videoMessageHelper == null) { + initVideoMessageHelper(); + } + return videoMessageHelper; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/BaseMessageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/BaseMessageActivity.java new file mode 100644 index 0000000..69cc1ca --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/BaseMessageActivity.java @@ -0,0 +1,197 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.content.Context; +import android.content.Intent; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import androidx.appcompat.widget.Toolbar; + +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.business.preference.UserPreferences; +import com.fengliyan.tianlesue.im.uikit.business.session.audio.MessageAudioControl; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.fragment.MessageFragment; +import com.fengliyan.tianlesue.im.uikit.common.CommonUtil; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created by zhoujianghua on 2015/9/10. + */ +public abstract class BaseMessageActivity extends UI { + + protected String sessionId; + + private SessionCustomization customization; + + private MessageFragment messageFragment; + + private SensorManager sensorManager; + + private Sensor proximitySensor; + + protected abstract MessageFragment fragment(); + + protected abstract int getContentViewId(); + + protected abstract void initToolBar(); + + /** + * 是否开启距离传感器 + */ + protected abstract boolean enableSensor(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(getContentViewId()); + + initToolBar(); + parseIntent(); + Window window = getWindow(); + //设置修改状态栏 + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + //设置状态栏的颜色,和你的app主题或者标题栏颜色设置一致就ok了 + window.setStatusBarColor(getResources().getColor(R.color.black)); + String servids = NoClearSPUtils.getString(this, ConsUser.SERVIDS); + ArrayList selectLabelList = new ArrayList<>(Arrays.asList(servids.split(","))); + boolean b = false; + for (int i = 0; i < selectLabelList.size(); i++) { + if (TextUtils.equals(selectLabelList.get(i), UserManager.getUserInfo().getUser_id() + "")) { + b = true; + break; + } + } + if (!b && !TextUtils.equals("2", sessionId)) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); + } + messageFragment = (MessageFragment) switchContent(fragment()); + if (enableSensor()) { + initSensor(); + } + } + + @Override + public void onResume() { + super.onResume(); + if (sensorManager != null && proximitySensor != null) { + sensorManager.registerListener(sensorEventListener, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (sensorManager != null && proximitySensor != null) { + sensorManager.unregisterListener(sensorEventListener); + } + } + + @Override + public void onBackPressed() { + if (messageFragment != null && messageFragment.onBackPressed()) { + return; + } + super.onBackPressed(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (messageFragment != null) { + messageFragment.onActivityResult(requestCode, resultCode, data); + } + + if (customization != null) { + customization.onActivityResult(this, requestCode, resultCode, data); + } + } + + private void parseIntent() { + Intent intent = getIntent(); + sessionId = intent.getStringExtra(Extras.EXTRA_ACCOUNT); + customization = (SessionCustomization) intent.getSerializableExtra(Extras.EXTRA_CUSTOMIZATION); + + if (customization != null) { + addRightCustomViewOnActionBar(this, customization.buttons); + } + } + + // 添加action bar的右侧按钮及响应事件 + private void addRightCustomViewOnActionBar(UI activity, List buttons) { + if (CommonUtil.isEmpty(buttons)) { + return; + } + + Toolbar toolbar = getToolBar(); + if (toolbar == null) { + return; + } + + LinearLayout buttonContainer = (LinearLayout) LayoutInflater.from(activity).inflate(R.layout.nim_action_bar_custom_view, null); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); + for (final SessionCustomization.OptionsButton button : buttons) { + ImageView imageView = new ImageView(activity); + imageView.setImageResource(button.iconId); + imageView.setBackgroundResource(R.drawable.nim_nim_action_bar_button_selector); + imageView.setPadding(ScreenUtil.dip2px(10), 0, ScreenUtil.dip2px(10), 0); + imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + button.onClick(BaseMessageActivity.this, v, sessionId); + } + }); + buttonContainer.addView(imageView, params); + } + + toolbar.addView(buttonContainer, new Toolbar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.RIGHT | Gravity.CENTER)); + } + + + private SensorEventListener sensorEventListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + float[] dis = event.values; + if (0.0f == dis[0]) { + //靠近,设置为听筒模式 + MessageAudioControl.getInstance(BaseMessageActivity.this).setEarPhoneModeEnable(true); + } else { + //离开,复原 + MessageAudioControl.getInstance(BaseMessageActivity.this).setEarPhoneModeEnable(UserPreferences.isEarPhoneModeEnable()); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + + } + }; + + private void initSensor() { + sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); + if (sensorManager != null) { + proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/CaptureVideoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/CaptureVideoActivity.java new file mode 100644 index 0000000..04b124f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/CaptureVideoActivity.java @@ -0,0 +1,748 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.PixelFormat; +import android.graphics.Point; +import android.hardware.Camera; +import android.media.CamcorderProfile; +import android.media.MediaRecorder; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialogHelper; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nim.uikit.R; + +import java.io.File; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +/** + * 视频录制界面 + *

+ * Created by huangjun on 2015/4/11. + */ +public class CaptureVideoActivity extends UI implements SurfaceHolder.Callback { + + private static final String TAG = "video"; + + public static final String EXTRA_DATA_FILE_NAME = "EXTRA_DATA_FILE_NAME"; + + private static final int VIDEO_TIMES = 180; + + private static final int VIDEO_WIDTH = 320; + + private static final int VIDEO_HEIGHT = 240; + + // context + + public Handler handler = new Handler(); + + // media + + private MediaRecorder mediaRecorder;// 录制视频的类 + + private Camera camera; + + // view + + private SurfaceView surfaceview; + + private SurfaceHolder surfaceHolder; + + private ImageView recordBtn; + + private ImageView recordingState; + + private TextView recordingTimeTextView; + + private ImageView switchCamera; // 切换摄像头 + + // state + + private int cameraId = 0; + + private String filename; + + private boolean previewing = false; + + private boolean multiCamera = false; + + private boolean recording = false; + + private long start, end; // 录制时间控制 + + private long duration = 0; + + private boolean destroyed = false; + + private int mAngle = 0; + + private LinkedList backCameraSize = new LinkedList<>(); + + private LinkedList frontCameraSize = new LinkedList<>(); + + public static void start(Activity activity, String videoFilePath, int captureCode) { + Intent intent = new Intent(); + intent.setClass(activity, CaptureVideoActivity.class); + intent.putExtra(EXTRA_DATA_FILE_NAME, videoFilePath); + activity.startActivityForResult(intent, captureCode); + } + + // 录制时间计数 + private Runnable runnable = new Runnable() { + + public void run() { + end = new Date().getTime(); + duration = (end - start); + int invs = (int) (duration / 1000); + + recordingTimeTextView.setText(TimeUtil.secToTime(invs)); + + // 录制过程中红点闪烁效果 + if (invs % 2 == 0) { + recordingState.setBackgroundResource(R.drawable.nim_record_start); + } else { + recordingState.setBackgroundResource(R.drawable.nim_record_video); + } + if (invs >= VIDEO_TIMES) { + stopRecorder(); + sendVideo(); + } else { + handler.postDelayed(this, 1000); + } + } + }; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFormat(PixelFormat.TRANSLUCENT); // 使得窗口支持透明度 + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.nim_capture_video_activity); + setTitle(R.string.video_record); + + parseIntent(); + findViews(); + initActionBar(); + + setViewsListener(); + updateRecordUI(); + + getVideoPreviewSize(); + + surfaceview = (SurfaceView) this.findViewById(R.id.videoView); + SurfaceHolder holder = surfaceview.getHolder(); + holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + holder.addCallback(this); + + resizeSurfaceView(); + } + + private void parseIntent() { + filename = getIntent().getExtras().getString(EXTRA_DATA_FILE_NAME); + } + + private void findViews() { + recordingTimeTextView = (TextView) findViewById(R.id.record_times); + recordingState = (ImageView) findViewById(R.id.recording_id); + + recordBtn = (ImageView) findViewById(R.id.record_btn); + switchCamera = (ImageView) findViewById(R.id.switch_cameras); + } + + private void initActionBar() { + checkMultiCamera(); + } + + private void setViewsListener() { + recordBtn.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (recording) { + stopRecorder(); + sendVideo(); + } else { + startRecorder(); + } + } + }); + switchCamera.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + switchCamera(); + } + }); + } + + @TargetApi(9) + private void switchCamera() { + if (Build.VERSION.SDK_INT >= 9) { + cameraId = (cameraId + 1) % Camera.getNumberOfCameras(); + } + resizeSurfaceView(); + shutdownCamera(); + initCamera(); + startPreview(); + } + + public void onResume() { + super.onResume(); + + getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + + public void onPause() { + super.onPause(); + + getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + if (recording) { + stopRecorder(); + sendVideo(); + } else { + shutdownCamera(); + } + + } + + public void onDestroy() { + super.onDestroy(); + + shutdownCamera(); + + destroyed = true; + } + + @Override + public void onBackPressed() { + if (recording) { + stopRecorder(); + } + + shutdownCamera(); + + setResult(RESULT_CANCELED); + finish(); + } + + @SuppressLint("NewApi") + private void getVideoPreviewSize(boolean isFront) { + CamcorderProfile profile; + int cameraId = 0; + + if (super.isCompatible(9)) { + if (isFront) { + cameraId = Camera.CameraInfo.CAMERA_FACING_FRONT; + } else { + cameraId = Camera.CameraInfo.CAMERA_FACING_BACK; + } + } + + if (super.isCompatible(11)) { + if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_480P)) { + profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_480P); + if (profile != null) { + Point point = new Point(); + point.x = profile.videoFrameWidth; + point.y = profile.videoFrameHeight; + if (isFront) { + frontCameraSize.addLast(point); + } else { + backCameraSize.addLast(point); + } + } + } else { + LogUtil.e(TAG, (isFront ? "Back Camera" : "Front Camera") + " no QUALITY_480P"); + } + + if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_CIF)) { + profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_CIF); + if (profile != null) { + Point point = new Point(); + point.x = profile.videoFrameWidth; + point.y = profile.videoFrameHeight; + if (isFront) { + frontCameraSize.addLast(point); + } else { + backCameraSize.addLast(point); + } + } + } else { + LogUtil.e(TAG, (isFront ? "Back Camera" : "Front Camera") + " no QUALITY_CIF"); + } + + if (super.isCompatible(15)) { + if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_QVGA)) { + profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_QVGA); + if (profile != null) { + Point point = new Point(); + point.x = profile.videoFrameWidth; + point.y = profile.videoFrameHeight; + if (isFront) { + frontCameraSize.addLast(point); + } else { + backCameraSize.addLast(point); + } + } + } else { + LogUtil.e(TAG, (isFront ? "Back Camera" : "Front Camera") + " no QUALITY_QVGA"); + } + } + } + + if (super.isCompatible(9)) { + profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_LOW); + if (profile == null) { + Point point = new Point(); + point.x = 320; + point.y = 240; + if (isFront) { + frontCameraSize.addLast(point); + } else { + backCameraSize.addLast(point); + } + LogUtil.e(TAG, (isFront ? "Back Camera" : "Front Camera") + " no QUALITY_LOW"); + } else { + Point point = new Point(); + point.x = profile.videoFrameWidth; + point.y = profile.videoFrameHeight; + if (isFront) { + frontCameraSize.addLast(point); + } else { + backCameraSize.addLast(point); + } + } + } else { + if (!isFront) { + profile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW); + if (profile == null) { + Point point = new Point(); + point.x = 320; + point.y = 240; + backCameraSize.addLast(point); + } else { + Point point = new Point(); + point.x = profile.videoFrameWidth; + point.y = profile.videoFrameHeight; + backCameraSize.addLast(point); + } + } + } + } + + + @SuppressLint("NewApi") + private void getVideoPreviewSize() { + backCameraSize.clear(); + frontCameraSize.clear(); + getVideoPreviewSize(false); + if (Build.VERSION.SDK_INT >= 9) { + if (Camera.getNumberOfCameras() >= 2) { + getVideoPreviewSize(true); + } + } + } + + private Point currentUsePoint = null; + + private void resizeSurfaceView() { + Point point; + if (cameraId == 0) { + point = backCameraSize.getFirst(); + } else { + point = frontCameraSize.getFirst(); + } + if (currentUsePoint != null && point.equals(currentUsePoint)) { + return; + } else { + currentUsePoint = point; + int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); + int surfaceHeight = screenWidth * point.x / point.y; + if (surfaceview != null) { + RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) surfaceview.getLayoutParams(); + lp.width = screenWidth; + lp.height = surfaceHeight; + lp.addRule(13); + surfaceview.setLayoutParams(lp); + } + } + } + + + @SuppressLint("NewApi") + private void setCamcorderProfile() { + CamcorderProfile profile; + + profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P); + + if (profile != null) { + if (currentUsePoint != null) { + profile.videoFrameWidth = currentUsePoint.x; + profile.videoFrameHeight = currentUsePoint.y; + } + + profile.fileFormat = MediaRecorder.OutputFormat.MPEG_4; + + if (Build.MODEL.equalsIgnoreCase("MB525") || Build.MODEL.equalsIgnoreCase("C8812") || Build.MODEL.equalsIgnoreCase("C8650")) { + profile.videoCodec = MediaRecorder.VideoEncoder.H263; + } else { + profile.videoCodec = MediaRecorder.VideoEncoder.H264; + } + + if (Build.VERSION.SDK_INT >= 14) { + profile.audioCodec = MediaRecorder.AudioEncoder.AAC; + } else { + if (Build.DISPLAY != null && Build.DISPLAY.indexOf("MIUI") >= 0) { + profile.audioCodec = MediaRecorder.AudioEncoder.AAC; + } else { + profile.audioCodec = MediaRecorder.AudioEncoder.AMR_NB; + } + } + mediaRecorder.setProfile(profile); + } else { + mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); + mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); + mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); + mediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT); + } + } + + @SuppressLint("NewApi") + private void setVideoOrientation() { + if (Build.VERSION.SDK_INT >= 9) { + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(cameraId, info); + mediaRecorder.setOrientationHint(info.orientation); + } + } + + public void updateRecordUI() { + if (recording) { + recordBtn.setBackgroundResource(R.drawable.nim_video_capture_stop_btn); + } else { + recordBtn.setBackgroundResource(R.drawable.nim_video_capture_start_btn); + } + } + + private boolean startRecorderInternal() throws Exception { + shutdownCamera(); + if (!initCamera()) + return false; + + switchCamera.setVisibility(View.GONE); + mediaRecorder = new MediaRecorder(); + + camera.unlock(); + mediaRecorder.setCamera(camera); + mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); + mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); + + setCamcorderProfile(); + + mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); + mediaRecorder.setMaxDuration(1000 * VIDEO_TIMES); + mediaRecorder.setOutputFile(filename); + setVideoOrientation(); + + mediaRecorder.prepare(); + mediaRecorder.start(); + + return true; + } + + private void startRecorder() { + try { + startRecorderInternal(); + } catch (Exception e) { + LogUtil.e(TAG, "start MediaRecord failed: " + e); + ToastHelper.showToast(this, R.string.start_camera_to_record_failed); + mediaRecorder.release(); + mediaRecorder = null; + camera.release(); + camera = null; + return; + + } + recording = true; + start = new Date().getTime(); + handler.postDelayed(runnable, 1000); + + recordingTimeTextView.setText("00:00"); + + updateRecordUI(); + } + + private void stopRecorder() { + if (mediaRecorder != null) { + try { + mediaRecorder.stop(); + } catch (Exception e) { + LogUtil.w(TAG, getString(R.string.stop_fail_maybe_stopped)); + } + mediaRecorder.release(); + mediaRecorder = null; + } + if (camera != null) { + camera.release(); + camera = null; + } + + handler.removeCallbacks(runnable); + recordingState.setBackgroundResource(R.drawable.nim_record_start); + recording = false; + updateRecordUI(); + } + + private void sendVideo() { + File convertedFile = new File(filename); + String message = ""; + if (convertedFile.exists()) { + int b = (int) convertedFile.length(); + int kb = b / 1024; + float mb = kb / 1024f; + message += mb > 1 ? getString(R.string.capture_video_size_in_mb, mb) : getString( + R.string.capture_video_size_in_kb, kb); + message += getString(R.string.is_send_video); + if (mb <= 1 && kb < 10) { + tooShortAlert(); + return; + } + } + EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() { + + @Override + public void doCancelAction() { + cancelRecord(); + } + + @Override + public void doOkAction() { + Intent intent = new Intent(); + intent.putExtra("duration", duration); + intent.putExtra(EXTRA_DATA_FILE_NAME, filename); + setResult(RESULT_OK, intent); + finish(); + } + }; + + final EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(this, null, message, true, listener); + + if (!isFinishing() && !destroyed) { + dialog.show(); + } + } + + /** + * 视频录制太短 + */ + private void tooShortAlert() { + EasyAlertDialogHelper.showOneButtonDiolag(this, null, getString(R.string.video_record_short), getString(R.string.iknow), true, new OnClickListener() { + @Override + public void onClick(View v) { + cancelRecord(); + } + }); + } + + /** + * 取消重录 + */ + private void cancelRecord() { + AttachmentStore.delete(filename); + recordingTimeTextView.setText("00:00"); + shutdownCamera(); + initCamera(); + startPreview(); + checkMultiCamera(); + } + + /** + * *************************************************** Camera Start *************************************************** + */ + @SuppressLint("NewApi") + public void checkMultiCamera() { + if (Build.VERSION.SDK_INT >= 9) { + if (Camera.getNumberOfCameras() > 1) { + multiCamera = true; + switchCamera.setVisibility(View.VISIBLE); + } else { + switchCamera.setVisibility(View.GONE); + } + } else { + switchCamera.setVisibility(View.GONE); + } + } + + @SuppressLint("NewApi") + private boolean initCamera() { + try { + if (multiCamera) { + camera = Camera.open(cameraId); + } else { + camera = Camera.open(); + } + } catch (RuntimeException e) { + LogUtil.e(TAG, "init camera failed: " + e); + ToastHelper.showToast(this, R.string.connect_vedio_device_fail); + return false; + } + + if (camera != null) { + setCameraParameters(); + } + + return camera != null; + } + + @SuppressLint("NewApi") + private void setCameraParameters() { + Camera.Parameters params = camera.getParameters(); + + if (Build.VERSION.SDK_INT >= 15) { + if (params.isVideoStabilizationSupported()) { + params.setVideoStabilization(true); + } + } + + List focusMode = params.getSupportedFocusModes(); + if (focusMode.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { + params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + + if (params != null) { + mAngle = setCameraDisplayOrientation(this, cameraId, camera); + Log.i(TAG, "camera angle = " + mAngle); + } + + params.setPreviewSize(currentUsePoint.x, currentUsePoint.y); + + try { + camera.setParameters(params); + } catch (RuntimeException e) { + LogUtil.e(TAG, "setParameters failed", e); + + } + } + + private void shutdownCamera() { + if (camera != null) { + if (previewing) { + camera.stopPreview(); + } + camera.release(); + camera = null; + previewing = false; + } + } + + + /** + * **************************** SurfaceHolder.Callback Start ******************************* + */ + + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + surfaceHolder = holder; + } + + public void surfaceCreated(SurfaceHolder holder) { + surfaceHolder = holder; + + shutdownCamera(); + if (!initCamera()) + return; + startPreview(); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + surfaceHolder = null; + mediaRecorder = null; + } + + /** + * ************************ SurfaceHolder.Callback Start ******************************** + */ + + private void startPreview() { + try { + camera.setPreviewDisplay(surfaceHolder); + camera.startPreview(); + previewing = true; + } catch (Exception e) { + ToastHelper.showToast(this, R.string.connect_vedio_device_fail); + shutdownCamera(); + e.printStackTrace(); + } + } + + /** + * ********************************* camera util ************************************ + */ + @SuppressLint("NewApi") + public int setCameraDisplayOrientation(Context context, int cameraId, Camera camera) { + int orientation = 90; + boolean front = (cameraId == 1); + if (Build.VERSION.SDK_INT >= 9) { + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(cameraId, info); + orientation = info.orientation; + front = (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT); + } + + WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + int rotation = manager.getDefaultDisplay().getRotation(); + int activityOrientation = roundRotation(rotation); + int result; + if (front) { + result = (orientation + activityOrientation) % 360; + result = (360 - result) % 360; // compensate the mirror + } else { // back-facing + result = (orientation - activityOrientation + 360) % 360; + //遇到过一个小米1s后置摄像头旋转180°,但是不确定是不是所有小米1s都是这样的. 先做一个适配,以后有问题再说. + if ("Xiaomi_MI-ONE Plus".equalsIgnoreCase(Build.MANUFACTURER + "_" + Build.MODEL)) { + result = 90; + } + } + camera.setDisplayOrientation(result); + return result; + } + + private int roundRotation(int rotation) { + switch (rotation) { + case Surface.ROTATION_0: + return 0; + case Surface.ROTATION_90: + return 90; + case Surface.ROTATION_180: + return 180; + case Surface.ROTATION_270: + return 270; + } + return 0; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/P2PMessageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/P2PMessageActivity.java new file mode 100644 index 0000000..b973e4d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/P2PMessageActivity.java @@ -0,0 +1,344 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.main.OnlineStateChangeObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionEventListener; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.fragment.MessageFragment; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.SoftHideKeyBoardUtil; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + + +/** + * 点对点聊天界面 + *

+ * Created by huangjun on 2015/2/1. + */ +public class P2PMessageActivity extends BaseMessageActivity { + + private boolean isResume = false; + private TextView mRlTextWarm; + + public static void start(Context context, String contactId, SessionCustomization customization, IMMessage anchor) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_ACCOUNT, contactId); + +// if (!SysSPUtils.getString(context, "sys_id").equals(contactId) && !SysSPUtils.getString(context, "serv_id").equals(contactId)) { //不是系统通知才显示自定义的聊天bar +// intent.putExtra(Extras.EXTRA_CUSTOMIZATION, customization); +// } + + if (!"2".equals(contactId) && !"4".equals(contactId) && !"11".equals(contactId) && !"3".equals(contactId) && !"5".equals(contactId) + && !"6".equals(contactId) && !"7".equals(contactId) && !"8".equals(contactId) && !"9".equals(contactId) && !"10".equals(contactId)) { //不是系统通知才显示自定义的聊天bar + intent.putExtra(Extras.EXTRA_CUSTOMIZATION, customization); + } + + + if (anchor != null) { + intent.putExtra(Extras.EXTRA_ANCHOR, anchor); + } + intent.setClass(context, P2PMessageActivity.class); + +// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + + context.startActivity(intent); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initState(this, Color.TRANSPARENT); +// StatusBarUtil.setAndroidNativeLightStatusBar(this, false); + SoftHideKeyBoardUtil.assistActivity(this); +// StatusBarCompat.setStatusBarColor(this, Color.TRANSPARENT); + hideTitleBar(); + // 单聊特例话数据,包括个人信息, +// requestBuddyInfo(); +// getToolBar().setBackgroundColor(ContextCompat.getColor(this,R.color.bg_gray)); + displayOnlineState(); + registerObservers(true); + + NimUIKit.setSessionListener(new SessionEventListener() { + @Override + public void onAvatarClicked(Context context, IMMessage message) { //头像左边点击事件 + String sessionId = message.getSessionId(); + if (!TextUtils.isEmpty(sessionId)) { + int uid = Integer.parseInt(sessionId); + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", uid); + context.startActivity(intent); + } + + } + + @Override + public void onAvatarRightClicked(Context context, IMMessage message) { //头像右边点击事件 + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", SPUtils.getInt(context, ConsUser.USER_ID)); + context.startActivity(intent); + } + + @Override + public void onAvatarLongClicked(Context context, IMMessage message) { + + } + + @Override + public void onAckMsgClicked(Context context, IMMessage message) { + + } + }); + + title = getToolBar().getTitle().toString(); + } + + //设置状态栏透明 + public void initState(Activity mActivity, int color) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + //Android 4.4 statusBar半透明 + mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + //Android 5.0以上 statusBar背景全透明 + Window window = mActivity.getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(color); + } + Utils.StatusBarLightMode(this, true); + } + + @Override + public void onDestroy() { + super.onDestroy(); + registerObservers(false); + } + + @Override + public void onResume() { + super.onResume(); + isResume = true; + } + + @Override + protected void onStop() { + super.onStop(); + isResume = false; + } + + private void requestBuddyInfo() { + String id = getIntent().getStringExtra(Extras.EXTRA_ACCOUNT); + if (!TextUtils.isEmpty(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P))) { + setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + return; + } + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(id); + if (info != null && !TextUtils.isEmpty(info.getName())) { + setTitle(info.getName()); + return; + } + List accounts = new ArrayList<>(); + accounts.add(id); + NIMClient.getService(UserService.class).fetchUserInfo(accounts) + .setCallback(new RequestCallback>() { + @Override + public void onSuccess(List userInfos) { + try { + NimUserInfo user = userInfos.get(0); + setTitle(user.getName()); + } catch (Exception e) { + } + } + + @Override + public void onFailed(int i) { + Log.e(",", ""); + } + + @Override + public void onException(Throwable throwable) { + Log.e(",", ""); + } + }); + } + + private void displayOnlineState() { + if (!NimUIKitImpl.enableOnlineState()) { + return; + } + String detailContent = NimUIKitImpl.getOnlineStateContentProvider().getDetailDisplay(sessionId); + setSubTitle(detailContent); + } + + + /** + * 命令消息接收观察者 + */ + private Observer commandObserver = new Observer() { + @Override + public void onEvent(CustomNotification message) { + if (!sessionId.equals(message.getSessionId()) || message.getSessionType() != SessionTypeEnum.P2P) { + return; + } + showCommandMessage(message); + } + }; + + + /** + * 用户信息变更观察者 + */ + private UserInfoObserver userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + if (!accounts.contains(sessionId)) { + return; + } + requestBuddyInfo(); + } + }; + + /** + * 好友资料变更(eg:关系) + */ + private ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + + @Override + public void onDeletedFriends(List accounts) { + setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + + @Override + public void onAddUserToBlackList(List account) { + setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + + @Override + public void onRemoveUserFromBlackList(List account) { + setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + }; + + /** + * 好友在线状态观察者 + */ + private OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() { + @Override + public void onlineStateChange(Set accounts) { + if (!accounts.contains(sessionId)) { + return; + } + // 按照交互来展示 + displayOnlineState(); + } + }; + + private void registerObservers(boolean register) { +// NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(commandObserver, register); +// NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, register); +// NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + if (NimUIKit.enableOnlineState()) { + NimUIKit.getOnlineStateChangeObservable().registerOnlineStateChangeListeners(onlineStateChangeObserver, register); + } + } + + private String title; + + protected void showCommandMessage(CustomNotification message) { + if (!isResume) { + return; + } + String content = message.getContent(); + try { + JSONObject json = JSON.parseObject(content); + int id = json.getIntValue("id"); + if (id == 1) { + // 正在输入 + String s = title + "(对方正在输入...)"; + setTitle(s); + getHandler().postDelayed(() -> { + setTitle(title); + }, 2000); + +// ToastHelper.showToastLong(P2PMessageActivity.this, "对方正在输入..."); + } +// else { +// ToastHelper.showToast(P2PMessageActivity.this, "command: " + content); +// } + } catch (Exception ignored) { + + } + } + + @Override + protected MessageFragment fragment() { + Bundle arguments = getIntent().getExtras(); + arguments.putSerializable(Extras.EXTRA_TYPE, SessionTypeEnum.P2P); + MessageFragment fragment = new MessageFragment(); + fragment.setArguments(arguments); + fragment.setContainerId(R.id.message_fragment_container); + return fragment; + } + + @Override + protected int getContentViewId() { + return R.layout.nim_message_activity; + } + + @Override + protected void initToolBar() { + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + } + + @Override + protected boolean enableSensor() { + return true; + } + + public String getSessionId() { + return sessionId; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/TeamMessageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/TeamMessageActivity.java new file mode 100644 index 0000000..eddd36f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/TeamMessageActivity.java @@ -0,0 +1,253 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamMemberDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.fragment.MessageFragment; +import com.fengliyan.tianlesue.im.uikit.business.session.fragment.TeamMessageFragment; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.List; + +/** + * 群聊界面 + *

+ * Created by huangjun on 2015/3/5. + */ +public class TeamMessageActivity extends BaseMessageActivity { + + // model + private Team team; + + private View invalidTeamTipView; + + private TextView invalidTeamTipText; + + private TeamMessageFragment fragment; + + private Class backToClass; + + public static void start(Context context, String tid, SessionCustomization customization, + Class backToClass, IMMessage anchor) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_ACCOUNT, tid); + intent.putExtra(Extras.EXTRA_CUSTOMIZATION, customization); + intent.putExtra(Extras.EXTRA_BACK_TO_CLASS, backToClass); + if (anchor != null) { + intent.putExtra(Extras.EXTRA_ANCHOR, anchor); + } + intent.setClass(context, TeamMessageActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + + context.startActivity(intent); + } + + protected void findViews() { + invalidTeamTipView = findView(R.id.invalid_team_tip); + invalidTeamTipText = findView(R.id.invalid_team_text); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + backToClass = (Class) getIntent().getSerializableExtra(Extras.EXTRA_BACK_TO_CLASS); + findViews(); + + registerTeamUpdateObserver(true); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + registerTeamUpdateObserver(false); + } + + @Override + public void onResume() { + super.onResume(); + requestTeamInfo(); + } + + /** + * 请求群基本信息 + */ + private void requestTeamInfo() { + // 请求群基本信息 + Team t = NimUIKit.getTeamProvider().getTeamById(sessionId); + if (t != null) { + updateTeamInfo(t); + } else { + NimUIKit.getTeamProvider().fetchTeamById(sessionId, new SimpleCallback() { + @Override + public void onResult(boolean success, Team result, int code) { + if (success && result != null) { + updateTeamInfo(result); + } else { + onRequestTeamInfoFailed(); + } + } + }); + } + } + + private void onRequestTeamInfoFailed() { + ToastHelper.showToast(TeamMessageActivity.this, "获取群组信息失败!"); + finish(); + } + + /**R + * 更新群信息 + * + * @param d + */ + private void updateTeamInfo(final Team d) { + if (d == null) { + return; + } + + team = d; + fragment.setTeam(team); + + setTitle(team == null ? sessionId : team.getName() + "(" + team.getMemberCount() + "人)"); + + invalidTeamTipText.setText(team.getType() == TeamTypeEnum.Normal ? R.string.normal_team_invalid_tip : R.string.team_invalid_tip); + invalidTeamTipView.setVisibility(team.isMyTeam() ? View.GONE : View.VISIBLE); + } + + /** + * 注册群信息更新监听 + * + * @param register + */ + private void registerTeamUpdateObserver(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataChangedObserver, register); + NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberDataChangedObserver, register); + NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + } + + /** + * 群资料变动通知和移除群的通知(包括自己退群和群被解散) + */ + TeamDataChangedObserver teamDataChangedObserver = new TeamDataChangedObserver() { + @Override + public void onUpdateTeams(List teams) { + if (team == null) { + return; + } + for (Team t : teams) { + if (t.getId().equals(team.getId())) { + updateTeamInfo(t); + break; + } + } + } + + @Override + public void onRemoveTeam(Team team) { + if (team == null) { + return; + } + if (team.getId().equals(TeamMessageActivity.this.team.getId())) { + updateTeamInfo(team); + } + } + }; + + /** + * 群成员资料变动通知和移除群成员通知 + */ + TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() { + + @Override + public void onUpdateTeamMember(List members) { + fragment.refreshMessageList(); + } + + @Override + public void onRemoveTeamMember(List member) { + } + }; + + ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + fragment.refreshMessageList(); + } + + @Override + public void onDeletedFriends(List accounts) { + fragment.refreshMessageList(); + } + + @Override + public void onAddUserToBlackList(List account) { + fragment.refreshMessageList(); + } + + @Override + public void onRemoveUserFromBlackList(List account) { + fragment.refreshMessageList(); + } + }; + + @Override + protected MessageFragment fragment() { + // 添加fragment + Bundle arguments = getIntent().getExtras(); + arguments.putSerializable(Extras.EXTRA_TYPE, SessionTypeEnum.Team); + fragment = new TeamMessageFragment(); + fragment.setArguments(arguments); + fragment.setContainerId(R.id.message_fragment_container); + return fragment; + } + + @Override + protected int getContentViewId() { + return R.layout.nim_team_message_activity; + } + + @Override + protected void initToolBar() { + ToolBarOptions options = new NimToolBarOptions(); + options.titleString = "群聊"; + setToolBar(R.id.toolbar, options); + } + + @Override + protected boolean enableSensor() { + return true; + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + if (backToClass != null) { + Intent intent = new Intent(); + intent.setClass(this, backToClass); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(intent); + finish(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/VoiceTrans.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/VoiceTrans.java new file mode 100644 index 0000000..3e435ac --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/VoiceTrans.java @@ -0,0 +1,145 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.app.Activity; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.NimNosSceneKeyConstant; +import com.netease.nimlib.sdk.AbortableFuture; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * Created by hzxuwen on 2015/7/9. + */ +public class VoiceTrans { + private static final String TAG = VoiceTrans.class.getSimpleName(); + + private final Activity baseActivity; + + // view + private View textLayout; + private TextView voiceTransText; + private View cancelBtn; + private ProgressBar refreshingIndicator; + private View failIcon; + + private AbortableFuture callFuture; + + public VoiceTrans(Activity baseActivity) { + this.baseActivity = baseActivity; + findViews(); + setListener(); + } + + private void hideKeyBoard() { + InputMethodManager imm = (InputMethodManager) baseActivity.getSystemService(Context.INPUT_METHOD_SERVICE); + if (baseActivity.getCurrentFocus() != null) { + imm.hideSoftInputFromWindow(baseActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + + private void findViews() { + textLayout = baseActivity.findViewById(R.id.voice_trans_layout); + if (textLayout == null) { + LayoutInflater layoutInflater = LayoutInflater.from(baseActivity); + textLayout = layoutInflater.inflate(R.layout.nim_voice_trans_layout, null); + ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseActivity.addContentView(textLayout, layoutParams); + } + voiceTransText = (TextView) textLayout.findViewById(R.id.voice_trans_text); + cancelBtn = textLayout.findViewById(R.id.cancel_btn); + refreshingIndicator = (ProgressBar) textLayout.findViewById(R.id.refreshing_indicator); + failIcon = textLayout.findViewById(R.id.trans_fail_icon); + } + + private void setListener() { + cancelBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + hide(); + } + }); + textLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + hide(); + } + }); + } + + public void hide() { + if (callFuture != null) { + callFuture.abort(); + } + voiceTransText.scrollTo(0, 0); + textLayout.setVisibility(View.GONE); + } + + public void show() { + hideKeyBoard(); + textLayout.setVisibility(View.VISIBLE); + voiceTransText.setText("正在转换"); + } + + public boolean isShow() { + return textLayout.getVisibility() == View.VISIBLE; + } + + public void voiceToText(IMMessage msg) { + voiceToText(msg, NimNosSceneKeyConstant.NIM_DEFAULT_IM); + } + + public void voiceToText(IMMessage msg, String sceneKey) { + AudioAttachment attachment = (AudioAttachment) msg.getAttachment(); + String voiceUrl = attachment.getUrl(); + String path = attachment.getPath(); + refreshStartUI(); + callFuture = NIMClient.getService(MsgService.class).transVoiceToTextEnableForce(voiceUrl, path, attachment.getDuration(), sceneKey, false); + callFuture.setCallback(new RequestCallback() { + @Override + public void onSuccess(String param) { + voiceTransText.setText(param); + updateUI(); + } + + @Override + public void onFailed(int code) { + LogUtil.e(TAG, "voice to text failed, code=" + code); + voiceTransText.setText(R.string.trans_voice_failed); + failIcon.setVisibility(View.VISIBLE); + updateUI(); + } + + @Override + public void onException(Throwable exception) { + LogUtil.e(TAG, "voice to text throw exception, e=" + exception.getMessage()); + voiceTransText.setText("参数错误"); + failIcon.setVisibility(View.VISIBLE); + updateUI(); + } + }); + show(); + } + + private void refreshStartUI() { + failIcon.setVisibility(View.GONE); + cancelBtn.setVisibility(View.VISIBLE); + refreshingIndicator.setVisibility(View.VISIBLE); + } + + private void updateUI() { + refreshingIndicator.setVisibility(View.GONE); + cancelBtn.setVisibility(View.GONE); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchMessagePictureActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchMessagePictureActivity.java new file mode 100644 index 0000000..2ec733c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchMessagePictureActivity.java @@ -0,0 +1,580 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.os.Bundle; +import android.os.Handler; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.view.ViewCompat; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.BaseZoomableImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.ImageGestureListener; +import com.fengliyan.tianlesue.im.uikit.common.util.C; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nimlib.sdk.AbortableFuture; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +/** + * 查看聊天消息原图 + * Created by huangjun on 2015/3/6. + */ +public class WatchMessagePictureActivity extends UI { + + private static final String TAG = WatchMessagePictureActivity.class.getSimpleName(); + private static final String INTENT_EXTRA_IMAGE = "INTENT_EXTRA_IMAGE"; + private static final String INTENT_EXTRA_MENU = "INTENT_EXTRA_MENU"; + + private static final int MODE_NOMARL = 0; + private static final int MODE_GIF = 1; + + private Handler handler; + private IMMessage message; + private boolean isShowMenu; + private List imageMsgList = new ArrayList<>(); + private int firstDisplayImageIndex = 0; + + private boolean newPageSelected = false; + + private View loadingLayout; + private BaseZoomableImageView image; + private ImageView simpleImageView; + private int mode; + protected CustomAlertDialog alertDialog; + private ViewPager imageViewPager; + private PagerAdapter adapter; + private AbortableFuture downloadFuture; + + public static void start(Context context, IMMessage message) { + Intent intent = new Intent(); + intent.putExtra(INTENT_EXTRA_IMAGE, message); + intent.setClass(context, WatchMessagePictureActivity.class); + context.startActivity(intent); + } + + public static void start(Context context, IMMessage message, boolean isShowMenu) { + Intent intent = new Intent(); + intent.putExtra(INTENT_EXTRA_IMAGE, message); + intent.putExtra(INTENT_EXTRA_MENU, isShowMenu); + intent.setClass(context, WatchMessagePictureActivity.class); + context.startActivity(intent); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_watch_picture_activity); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleString = "图片"; + options.navigateId = R.drawable.nim_actionbar_white_back_icon; + setToolBar(R.id.toolbar, options); + + handleIntent(); + + initActionbar(); + findViews(); + + loadMsgAndDisplay(); + + handler = new Handler(); + registerObservers(true); + } + + private void handleIntent() { + this.message = (IMMessage) getIntent().getSerializableExtra(INTENT_EXTRA_IMAGE); + mode = ImageUtil.isGif(((ImageAttachment) message.getAttachment()).getExtension()) ? MODE_GIF : MODE_NOMARL; + setTitle(message); + isShowMenu = getIntent().getBooleanExtra(INTENT_EXTRA_MENU, true); + } + + @Override + public void onDestroy() { + registerObservers(false); + if (imageViewPager != null) { + imageViewPager.setAdapter(null); + } + if (downloadFuture != null) { + downloadFuture.abort(); + downloadFuture = null; + } + super.onDestroy(); + } + + private void setTitle(IMMessage message) { + if (message == null) { + return; + } + super.setTitle(String.format("图片发送于%s", TimeUtil.getDateString(message.getTime()))); + } + + private void initActionbar() { + TextView menuBtn = findView(R.id.actionbar_menu); + if (isShowMenu) { + menuBtn.setVisibility(View.VISIBLE); + menuBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WatchPicAndVideoMenuActivity.startActivity(WatchMessagePictureActivity.this, message); + } + }); + } else { + menuBtn.setVisibility(View.GONE); + } + } + + private void findViews() { + alertDialog = new CustomAlertDialog(this); + loadingLayout = findViewById(R.id.loading_layout); + + imageViewPager = (ViewPager) findViewById(R.id.view_pager_image); + simpleImageView = (ImageView) findViewById(R.id.simple_image_view); + + if (mode == MODE_GIF) { + simpleImageView.setVisibility(View.VISIBLE); + simpleImageView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (isOriginImageHasDownloaded(message)) { + showWatchPictureAction(); + } + return true; + } + }); + + imageViewPager.setVisibility(View.GONE); + } else if (mode == MODE_NOMARL) { + simpleImageView.setVisibility(View.GONE); + imageViewPager.setVisibility(View.VISIBLE); + } + } + + // 加载并显示 + private void loadMsgAndDisplay() { + if (mode == MODE_NOMARL) { + queryImageMessages(); + } else if (mode == MODE_GIF) { + displaySimpleImage(); + } + } + + // 显示单个gif图片 + private void displaySimpleImage() { + String path = ((ImageAttachment) message.getAttachment()).getPath(); + String thumbPath = ((ImageAttachment) message.getAttachment()).getThumbPath(); + if (!TextUtils.isEmpty(path)) { + Glide.with(this).asGif().load(new File(path)).into(simpleImageView); + return; + } + if (!TextUtils.isEmpty(thumbPath)) { + Glide.with(this).asGif().load(new File(thumbPath)).into(simpleImageView); + } + + if (message.getDirect() == MsgDirectionEnum.In) { + requestOriImage(message); + } + } + + + // 查询并显示图片,带viewPager + private void queryImageMessages() { + IMMessage anchor = MessageBuilder.createEmptyMessage(message.getSessionId(), message.getSessionType(), 0); + NIMClient.getService(MsgService.class).queryMessageListByType(MsgTypeEnum.image, anchor, Integer.MAX_VALUE).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List param) { + for (IMMessage imMessage : param) { + if (!ImageUtil.isGif(((ImageAttachment) imMessage.getAttachment()).getExtension())) { + imageMsgList.add(imMessage); + } + } + // imageMsgList.addAll(param); + Collections.reverse(imageMsgList); + setDisplayIndex(); + setViewPagerAdapter(); + } + + @Override + public void onFailed(int code) { + Log.i(TAG, "query msg by type failed, code:" + code); + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + + // 设置第一个选中的图片index + private void setDisplayIndex() { + for (int i = 0; i < imageMsgList.size(); i++) { + IMMessage imageObject = imageMsgList.get(i); + if (compareObjects(message, imageObject)) { + firstDisplayImageIndex = i; + break; + } + } + } + + protected boolean compareObjects(IMMessage t1, IMMessage t2) { + return (t1.getUuid().equals(t2.getUuid())); + } + + private void setViewPagerAdapter() { + adapter = new PagerAdapter() { + @Override + public int getCount() { + return imageMsgList == null ? 0 : imageMsgList.size(); + } + + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + View layout = (View) object; + BaseZoomableImageView iv = (BaseZoomableImageView) layout.findViewById(R.id.watch_image_view); + iv.clear(); + container.removeView(layout); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return (view == object); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + ViewGroup layout; + layout = (ViewGroup) LayoutInflater.from(WatchMessagePictureActivity.this).inflate(R.layout.nim_image_layout_multi_touch, null); + layout.setBackgroundColor(Color.BLACK); + + container.addView(layout); + layout.setTag(position); + + if (position == firstDisplayImageIndex) { + onViewPagerSelected(position); + } + + return layout; + } + + @Override + public int getItemPosition(Object object) { + return POSITION_NONE; + } + }; + + imageViewPager.setAdapter(adapter); + imageViewPager.setOffscreenPageLimit(2); + imageViewPager.setCurrentItem(firstDisplayImageIndex); + imageViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (positionOffset == 0f && newPageSelected) { + newPageSelected = false; + onViewPagerSelected(position); + } + } + + @Override + public void onPageSelected(int position) { + newPageSelected = true; + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + } + + private void onViewPagerSelected(int position) { + if (downloadFuture != null) { + downloadFuture.abort(); + downloadFuture = null; + } + setTitle(imageMsgList.get(position)); + updateCurrentImageView(position); + onImageViewFound(image); + } + + // 初始化每个view的image + protected void updateCurrentImageView(final int position) { + View currentLayout = imageViewPager.findViewWithTag(position); + if (currentLayout == null) { + ViewCompat.postOnAnimation(imageViewPager, new Runnable() { + + @Override + public void run() { + updateCurrentImageView(position); + } + }); + return; + } + image = (BaseZoomableImageView) currentLayout.findViewById(R.id.watch_image_view); + requestOriImage(imageMsgList.get(position)); + } + + // 若图片已下载,直接显示图片;若图片未下载,则下载图片 + private void requestOriImage(IMMessage msg) { + if (isOriginImageHasDownloaded(msg)) { + onDownloadSuccess(msg); + return; + } + + // async download original image + onDownloadStart(msg); + message = msg; // 下载成功之后,判断是否是同一条消息时需要使用 + downloadFuture = NIMClient.getService(MsgService.class).downloadAttachment(msg, false); + } + + private boolean isOriginImageHasDownloaded(final IMMessage message) { + if (message.getAttachStatus() == AttachStatusEnum.transferred && + !TextUtils.isEmpty(((ImageAttachment) message.getAttachment()).getPath())) { + return true; + } + + return false; + } + + /** + * ******************************** 设置图片 ********************************* + */ + + private void setThumbnail(IMMessage msg) { + String thumbPath = ((ImageAttachment) msg.getAttachment()).getThumbPath(); + String path = ((ImageAttachment) msg.getAttachment()).getPath(); + + Bitmap bitmap = null; + if (!TextUtils.isEmpty(thumbPath)) { + bitmap = BitmapDecoder.decodeSampledForDisplay(thumbPath); + bitmap = ImageUtil.rotateBitmapInNeeded(thumbPath, bitmap); + } else if (!TextUtils.isEmpty(path)) { + bitmap = BitmapDecoder.decodeSampledForDisplay(path); + bitmap = ImageUtil.rotateBitmapInNeeded(path, bitmap); + } + + if (bitmap != null) { + image.setImageBitmap(bitmap); + return; + } + + image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnLoading())); + } + + private void setImageView(final IMMessage msg) { + String path = ((ImageAttachment) msg.getAttachment()).getPath(); + if (TextUtils.isEmpty(path)) { + image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnLoading())); + return; + } + + Bitmap bitmap = BitmapDecoder.decodeSampledForDisplay(path, false); + bitmap = ImageUtil.rotateBitmapInNeeded(path, bitmap); + if (bitmap == null) { + ToastHelper.showToastLong(this, R.string.picker_image_error); + image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnFailed())); + } else { + image.setImageBitmap(bitmap); + } + } + + private int getImageResOnLoading() { + return R.drawable.nim_image_default; + } + + private int getImageResOnFailed() { + return R.drawable.nim_image_download_failed; + } + + /** + * ********************************* 下载 **************************************** + */ + + private void registerObservers(boolean register) { + NIMClient.getService(MsgServiceObserve.class).observeMsgStatus(statusObserver, register); + } + + private Observer statusObserver = new Observer() { + @Override + public void onEvent(IMMessage msg) { + if (!msg.isTheSame(message) || isDestroyedCompatible()) { + return; + } + + if (isOriginImageHasDownloaded(msg)) { + onDownloadSuccess(msg); + } else if (msg.getAttachStatus() == AttachStatusEnum.fail) { + onDownloadFailed(); + } + } + }; + + private void onDownloadStart(final IMMessage msg) { + if (TextUtils.isEmpty(((ImageAttachment) msg.getAttachment()).getPath())) { + loadingLayout.setVisibility(View.VISIBLE); + } else { + loadingLayout.setVisibility(View.GONE); + } + if (mode == MODE_NOMARL) { + setThumbnail(msg); + } + } + + private void onDownloadSuccess(final IMMessage msg) { + loadingLayout.setVisibility(View.GONE); + if (mode == MODE_NOMARL) { + handler.post(new Runnable() { + + @Override + public void run() { + setImageView(msg); + } + }); + } else if (mode == MODE_GIF) { + displaySimpleImage(); + } + } + + private void onDownloadFailed() { + loadingLayout.setVisibility(View.GONE); + if (mode == MODE_NOMARL) { + if (image != null) { + image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnFailed())); + } + } else if (mode == MODE_GIF) { + if (simpleImageView != null) { + simpleImageView.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnFailed())); + } + } + ToastHelper.showToastLong(this, R.string.download_picture_fail); + } + + /** + * ***********************************图片点击事件******************************************* + */ + + // 设置图片点击事件 + protected void onImageViewFound(BaseZoomableImageView imageView) { + imageView.setImageGestureListener(new ImageGestureListener() { + + @Override + public void onImageGestureSingleTapConfirmed() { + onImageViewTouched(); + } + + @Override + public void onImageGestureLongPress() { + showWatchPictureAction(); + } + + @Override + public void onImageGestureFlingDown() { + finish(); + } + }); + } + + // 图片单击 + protected void onImageViewTouched() { + finish(); + } + + // 图片长按 + protected void showWatchPictureAction() { + if (alertDialog.isShowing()) { + alertDialog.dismiss(); + return; + } + alertDialog.clearData(); + String path = ((ImageAttachment) message.getAttachment()).getThumbPath(); + if (TextUtils.isEmpty(path)) { + return; + } + String title; + if (!TextUtils.isEmpty(((ImageAttachment) message.getAttachment()).getPath())) { + title = getString(R.string.save_to_device); + alertDialog.addItem(title, new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + savePicture(); + } + }); + } + alertDialog.show(); + } + + // 保存图片 + public void savePicture() { + ImageAttachment attachment = (ImageAttachment) message.getAttachment(); + String path = attachment.getPath(); + if (TextUtils.isEmpty(path)) { + return; + } + + String srcFilename = attachment.getFileName(); + //默认jpg + String extension = TextUtils.isEmpty(attachment.getExtension()) ? "jpg" : attachment.getExtension(); + srcFilename += ("." + extension); + + String picPath = StorageUtil.getSystemImagePath(); + String dstPath = picPath + srcFilename; + if (AttachmentStore.copy(path, dstPath) != -1) { + try { + ContentValues values = new ContentValues(2); + values.put(MediaStore.Images.Media.MIME_TYPE, C.MimeType.MIME_JPEG); + values.put(MediaStore.Images.Media.DATA, dstPath); + getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + ToastHelper.showToastLong(WatchMessagePictureActivity.this, getString(R.string.picture_save_to)); + } catch (Exception e) { + // may be java.lang.UnsupportedOperationException + ToastHelper.showToastLong(WatchMessagePictureActivity.this, getString(R.string.picture_save_fail)); + } + } else { + ToastHelper.showToastLong(WatchMessagePictureActivity.this, getString(R.string.picture_save_fail)); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchPicAndVideoMenuActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchPicAndVideoMenuActivity.java new file mode 100644 index 0000000..c1affb1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchPicAndVideoMenuActivity.java @@ -0,0 +1,130 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; + +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.adapter.MediaAdapter; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by winnie on 2017/9/18. + */ + +public class WatchPicAndVideoMenuActivity extends UI { + private final static String EXTRA_MESSAGE = "EXTRA_MESSAGE"; + + // view + private RecyclerView recyclerView; + + // data + private IMMessage message; + private MediaAdapter adapter; + private List mediaItems; + + public static void startActivity(Context context, IMMessage message) { + Intent intent = new Intent(); + intent.setClass(context, WatchPicAndVideoMenuActivity.class); + intent.putExtra(EXTRA_MESSAGE, message); + context.startActivity(intent); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_watch_pic_video_menu_activity); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleId = R.string.pic_and_video; + options.navigateId = R.drawable.nim_actionbar_white_back_icon; + setToolBar(R.id.toolbar, options); + + message = (IMMessage) getIntent().getSerializableExtra(EXTRA_MESSAGE); + + findViews(); + queryPicAndVideo(); + } + + private void findViews() { + recyclerView = findView(R.id.recycler_view); + final GridLayoutManager manager = new GridLayoutManager(this, 3); + recyclerView.setLayoutManager(manager); + mediaItems = new ArrayList<>(); + adapter = new MediaAdapter(this, mediaItems); + recyclerView.setAdapter(adapter); + + manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + return adapter.isDateType(position) ? manager.getSpanCount() : 1; + } + }); + } + + private void queryPicAndVideo() { + // 查找图片和视频类型 + List types = new ArrayList<>(); + types.add(MsgTypeEnum.image); + types.add(MsgTypeEnum.video); + + // 查询锚点 + IMMessage anchor = MessageBuilder.createEmptyMessage(message.getSessionId(), message.getSessionType(), 0); + + NIMClient.getService(MsgService.class).queryMessageListByTypes(types, anchor, + 0, QueryDirectionEnum.QUERY_OLD, Integer.MAX_VALUE, false).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List param) { + addMediaItem(param); + } + + @Override + public void onFailed(int code) { + + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + + private void addMediaItem(List messages) { + if (messages == null || messages.size() < 0) { + return; + } + String currentTime = ""; + for (IMMessage msg : messages) { + String msgTime = TimeUtil.getDateTimeString(msg.getTime(), "yyyyMM"); + if (!TextUtils.equals(msgTime, currentTime)) { + currentTime = msgTime; + MediaAdapter.MediaItem itemDateTip = new MediaAdapter.MediaItem(msg, true); + itemDateTip.setTime(msg.getTime()); + mediaItems.add(itemDateTip); + } + + MediaAdapter.MediaItem item = new MediaAdapter.MediaItem(msg, false); + mediaItems.add(item); + } + adapter.notifyDataSetChanged(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchVideoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchVideoActivity.java new file mode 100644 index 0000000..01497f9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/activity/WatchVideoActivity.java @@ -0,0 +1,574 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.media.MediaPlayer; +import android.media.MediaPlayer.OnCompletionListener; +import android.media.MediaPlayer.OnErrorListener; +import android.media.MediaPlayer.OnPreparedListener; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.SurfaceHolder; +import android.view.SurfaceHolder.Callback; +import android.view.SurfaceView; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.appcompat.app.ActionBar; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.AbortableFuture; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.VideoAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.model.AttachmentProgress; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * 视频播放界面 + *

+ * Created by huangjun on 2015/4/11. + */ +public class WatchVideoActivity extends UI implements Callback { + public static final String INTENT_EXTRA_DATA = "EXTRA_DATA"; + public static final String INTENT_EXTRA_MENU = "EXTRA_MENU"; + + // player + + private MediaPlayer mediaPlayer; + + // context + + private Handler handlerTimes = new Handler(); + + private ActionBar actionBar; + + private IMMessage message; + + // view + + private SurfaceView surfaceView; + + private SurfaceHolder surfaceHolder; + + private View videoIcon; + + private View downloadLayout; + + private View downloadProgressBackground; + + private View downloadProgressForeground; + + private TextView downloadProgressText; + + protected TextView fileInfoTextView; + + private TextView playTimeTextView; + + // state + private boolean isShowMenu = true; + + private boolean isSurfaceCreated = false; + + protected String videoFilePath; + + protected long videoLength = 0; + + private float lastPercent; + + private int playState = PLAY_STATE_STOP; + + private final static int PLAY_STATE_PLAYING = 1; + + private final static int PLAY_STATE_STOP = 2; + + private final static int PLAY_STATE_PAUSE = 3; + + // download control + private boolean downloading; + private ImageView downloadBtn; + private AbortableFuture downloadFuture; + + public static void start(Context context, IMMessage message) { + Intent intent = new Intent(); + intent.putExtra(WatchVideoActivity.INTENT_EXTRA_DATA, message); + intent.setClass(context, WatchVideoActivity.class); + context.startActivity(intent); + } + + public static void start(Context context, IMMessage message, boolean isShowMenu) { + Intent intent = new Intent(); + intent.putExtra(WatchVideoActivity.INTENT_EXTRA_DATA, message); + intent.putExtra(INTENT_EXTRA_MENU, isShowMenu); + intent.setClass(context, WatchVideoActivity.class); + context.startActivity(intent); + } + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.nim_watch_video_activity); + + ToolBarOptions options = new NimToolBarOptions(); + options.navigateId = R.drawable.nim_actionbar_white_back_icon; + setToolBar(R.id.toolbar, options); + + parseIntent(); + findViews(); + initActionbar(); + + showVideoInfo(); + + registerObservers(true); + download(); + } + + public void onResume() { + super.onResume(); + mediaPlayer = new MediaPlayer(); + + if (isSurfaceCreated) { + play(); + } + } + + @Override + public void onPause() { + super.onPause(); + + stopMediaPlayer(); + } + + @Override + public void onBackPressed() { + stopDownload(); + super.onBackPressed(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + registerObservers(false); + } + + private void parseIntent() { + message = (IMMessage) getIntent().getSerializableExtra(INTENT_EXTRA_DATA); + setTitle(String.format("视频发送于%s", TimeUtil.getDateString(message.getTime()))); + isShowMenu = getIntent().getBooleanExtra(INTENT_EXTRA_MENU, true); + } + + private void findViews() { + downloadLayout = findViewById(R.id.layoutDownload); + downloadProgressBackground = findViewById(R.id.downloadProgressBackground); + downloadProgressForeground = findViewById(R.id.downloadProgressForeground); + downloadProgressText = (TextView) findViewById(R.id.downloadProgressText); + videoIcon = findViewById(R.id.videoIcon); + + surfaceView = (SurfaceView) findViewById(R.id.videoView); + surfaceHolder = surfaceView.getHolder(); + surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + surfaceHolder.addCallback(this); + + playTimeTextView = (TextView) findViewById(R.id.lblVideoTimes); + playTimeTextView.setVisibility(View.INVISIBLE); + fileInfoTextView = (TextView) findViewById(R.id.lblVideoFileInfo); + playTimeTextView.setVisibility(View.INVISIBLE); + + downloadBtn = (ImageView) findViewById(R.id.control_download_btn); + downloadBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (downloading) { + stopDownload(); + } else { + download(); + } + downloadBtn.setImageResource(downloading ? R.drawable.nim_icon_download_pause : R.drawable.nim_icon_download_resume); + } + }); + + actionBar = getSupportActionBar(); + } + + private void initActionbar() { + TextView menuBtn = findView(R.id.actionbar_menu); + if (isShowMenu) { + menuBtn.setVisibility(View.VISIBLE); + menuBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + WatchPicAndVideoMenuActivity.startActivity(WatchVideoActivity.this, message); + } + }); + } else { + menuBtn.setVisibility(View.GONE); + } + } + + private void initVideoSize() { + if (mediaPlayer == null) { + return; + } + // 视频宽高 + int width = mediaPlayer.getVideoWidth(); + int height = mediaPlayer.getVideoHeight(); + + if (width <= 0 || height <= 0) { + return; + } + + // 屏幕宽高 + DisplayMetrics dm = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(dm); + int screenWidth = dm.widthPixels; + int screenHeight = dm.heightPixels; + + int videoRatio = width / height; + int screenRatio = screenWidth / screenHeight; + + if (screenRatio > videoRatio) { + int newHeight = screenHeight; + int newWidth = screenHeight * width / height; + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( + newWidth, newHeight); + int margin = (screenWidth - newWidth) / 2; + layoutParams.setMargins(margin, 0, margin, 0); + surfaceView.setLayoutParams(layoutParams); + } else { + int newWidth = screenWidth; + int newHeight = screenWidth * height / width; + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( + newWidth, newHeight); + int margin = (screenHeight - newHeight) / 2; + layoutParams.setMargins(0, margin, 0, margin); + surfaceView.setLayoutParams(layoutParams); + } + } + + /** + * ****************************** MediaPlayer Start ******************************** + */ + private void stopMediaPlayer() { + if (mediaPlayer != null) { + if (mediaPlayer.isPlaying()) { + mediaPlayer.stop(); + } + mediaPlayer.reset(); + mediaPlayer.release(); + mediaPlayer = null; + actionBar.show(); + + } + } + + /** + * 处理视频播放时间 + */ + private Runnable timeRunnable = new Runnable() { + public void run() { + if (mediaPlayer != null && mediaPlayer.isPlaying()) { + playState = PLAY_STATE_PLAYING; + + if (videoLength <= 0) { + playTimeTextView.setVisibility(View.INVISIBLE); + } else { + // 由于mediaPlayer取到的时间不统一,采用消息体中的时间 + int leftTimes = (int) (videoLength * 1000 - mediaPlayer.getCurrentPosition()); + if (leftTimes < 0) { + leftTimes = 0; + } + + playTimeTextView.setVisibility(View.VISIBLE); + long seconds = TimeUtil.getSecondsByMilliseconds(leftTimes); + playTimeTextView.setText(TimeUtil.secToTime((int) seconds)); + handlerTimes.postDelayed(this, 1000); + } + + } + } + }; + + protected void pauseVideo() { + videoIcon.setVisibility(View.VISIBLE); + if (mediaPlayer != null && mediaPlayer.isPlaying()) { + mediaPlayer.pause(); + handlerTimes.removeCallbacks(timeRunnable); + playState = PLAY_STATE_PAUSE; + actionBar.show(); + } + } + + protected void resumeVideo() { + videoIcon.setVisibility(View.GONE); + if (mediaPlayer != null) { + if (!mediaPlayer.isPlaying()) { + mediaPlayer.start(); + playState = PLAY_STATE_PLAYING; + handlerTimes.postDelayed(timeRunnable, 100); + actionBar.hide(); + } + } + } + + protected void playVideo() { + videoIcon.setVisibility(View.GONE); + if (mediaPlayer != null) { + if (mediaPlayer.isPlaying()) { + mediaPlayer.stop(); + } else { + if (isSurfaceCreated) { + mediaPlayer.setDisplay(surfaceHolder); + } else { + ToastHelper.showToast(WatchVideoActivity.this, R.string.look_video_fail_try_again); + return; + } + } + mediaPlayer.reset(); + try { + mediaPlayer.setDataSource(videoFilePath); + } catch (Exception e) { + ToastHelper.showToast(WatchVideoActivity.this, R.string.look_video_fail_try_again); + e.printStackTrace(); + return; + } + + setMediaPlayerListener(); + mediaPlayer.prepareAsync(); + actionBar.hide(); + } + } + + private void setMediaPlayerListener() { + mediaPlayer.setOnCompletionListener(new OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + videoIcon.setVisibility(View.VISIBLE); + + playState = PLAY_STATE_STOP; + playTimeTextView.setText("00:00"); + handlerTimes.removeCallbacks(timeRunnable); + actionBar.show(); + } + }); + + mediaPlayer.setOnErrorListener(new OnErrorListener() { + @Override + public boolean onError(MediaPlayer mp, int what, int extra) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW); + String type = "video/3gp"; + Uri name = Uri.parse("file://" + videoFilePath); + intent.setDataAndType(name, type); + startActivity(intent); + finish(); + } catch (Exception e) { + ToastHelper.showToastLong(WatchVideoActivity.this, R.string.look_video_fail); + } + return true; + } + }); + + mediaPlayer.setOnPreparedListener(new OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mp)// 缓冲完毕 + { + mediaPlayer.start();// 播放视频 + initVideoSize();//根据视频宽高,调整视频显示 + // if (position > 0) { + // mediaPlayer.seekTo(position); + // mediaPlayer.start(); + // } + handlerTimes.postDelayed(timeRunnable, 100); + } + }); + } + + /** + * **************************** 下载视频 ********************************* + */ + private void showVideoInfo() { + long duration = ((VideoAttachment) message.getAttachment()).getDuration(); + long fileSize = ((VideoAttachment) message.getAttachment()).getSize(); + + if (duration <= 0) { + fileInfoTextView.setText("大小: " + FileUtil.formatFileSize(fileSize)); + } else { + long seconds = TimeUtil.getSecondsByMilliseconds(duration); + fileInfoTextView.setText("大小: " + FileUtil.formatFileSize(fileSize) + ",时长: " + + String.valueOf(seconds) + " 秒"); + videoLength = seconds; + } + } + + private void registerObservers(boolean register) { + NIMClient.getService(MsgServiceObserve.class).observeMsgStatus(statusObserver, register); + NIMClient.getService(MsgServiceObserve.class).observeAttachmentProgress(attachmentProgressObserver, register); + } + + private Observer statusObserver = new Observer() { + @Override + public void onEvent(IMMessage msg) { + if (!msg.isTheSame(message) || isDestroyedCompatible()) { + return; + } + + if (msg.getAttachStatus() == AttachStatusEnum.transferred && isVideoHasDownloaded(msg)) { + onDownloadSuccess(msg); + } else if (msg.getAttachStatus() == AttachStatusEnum.fail) { + onDownloadFailed(); + } + } + }; + + private Observer attachmentProgressObserver = new Observer() { + @Override + public void onEvent(AttachmentProgress p) { + long total = p.getTotal(); + long progress = p.getTransferred(); + float percent = (float) progress / (float) total; + if (percent > 1.0) { + // 消息中标识的文件大小有误,小于实际大小 + percent = (float) 1.0; + progress = total; + } + if (percent - lastPercent >= 0.10) { + lastPercent = percent; + setDownloadProgress(getString(R.string.download_video), progress, total); + } else { + if (lastPercent == 0.0) { + lastPercent = percent; + setDownloadProgress(getString(R.string.download_video), progress, total); + } + if (percent == 1.0 && lastPercent != 1.0) { + lastPercent = percent; + setDownloadProgress(getString(R.string.download_video), progress, total); + } + } + } + }; + + private void setDownloadProgress(final String label, final long progress, final long total) { + final float percent = (float) ((double) progress / total); + + runOnUiThread(new Runnable() { + @Override + public void run() { + LayoutParams fgLayoutParams = downloadProgressForeground.getLayoutParams(); + fgLayoutParams.width = (int) (downloadProgressBackground.getWidth() * percent); + downloadProgressForeground.setLayoutParams(fgLayoutParams); + + downloadProgressText.setText(String.format(getString(R.string.download_progress_description), label, + FileUtil.formatFileSize(progress), FileUtil.formatFileSize(total))); + } + }); + } + + private boolean isVideoHasDownloaded(final IMMessage message) { + if (message.getAttachStatus() == AttachStatusEnum.transferred && + !TextUtils.isEmpty(((VideoAttachment) message.getAttachment()).getPath())) { + return true; + } + + return false; + } + + private void download() { + if (!isVideoHasDownloaded(message)) { + // async download original image + onDownloadStart(message); + downloadFuture = NIMClient.getService(MsgService.class).downloadAttachment(message, false); + downloading = true; + } + } + + private void play() { + if (isVideoHasDownloaded(message)) { + onDownloadSuccess(message); + } + } + + private void onDownloadSuccess(final IMMessage message) { + downloadFuture = null; + + downloadLayout.setVisibility(View.GONE); + + videoFilePath = ((VideoAttachment) message.getAttachment()).getPath(); + + surfaceView.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + if (playState == PLAY_STATE_PAUSE) { + resumeVideo(); + } else if (playState == PLAY_STATE_PLAYING) { + pauseVideo(); + } else if (playState == PLAY_STATE_STOP) { + playVideo(); + } + } + }); + playVideo(); + } + + private void onDownloadFailed() { + downloadFuture = null; + + downloadLayout.setVisibility(View.GONE); + ToastHelper.showToast(WatchVideoActivity.this, R.string.download_video_fail); + } + + private void onDownloadStart(IMMessage message) { + setDownloadProgress(getString(R.string.download_video), 0, ((VideoAttachment) message.getAttachment()).getSize()); + downloadLayout.setVisibility(View.VISIBLE); + } + + private void stopDownload() { + if (downloadFuture != null) { + downloadFuture.abort(); + downloadFuture = null; + downloading = false; + } + } + + /** + * ***************************** SurfaceHolder Callback ************************************** + */ + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + if (!isSurfaceCreated) { + isSurfaceCreated = true; + play(); + } + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + isSurfaceCreated = false; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + initVideoSize();// 屏幕旋转后,改变视频显示布局 + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/adapter/MediaAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/adapter/MediaAdapter.java new file mode 100644 index 0000000..0dce43c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/adapter/MediaAdapter.java @@ -0,0 +1,143 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.adapter; + +import android.content.Context; +import androidx.recyclerview.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.WatchMessagePictureActivity; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.WatchVideoActivity; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.media.DateViewHolder; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.media.MediaViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.attachment.VideoAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.List; + +/** + * Created by winnie on 2017/9/18. + */ + +public class MediaAdapter extends RecyclerView.Adapter { + + private static final int ITEM_VIEW_TYPE_DATE = 0; + private static final int ITEM_VIEW_TYPE_ITEM = 1; + + private Context context; + private List mediaItems; + + public static class MediaItem { + private boolean isDate; + private IMMessage message; + private long time; + + public MediaItem(IMMessage message, boolean isDate) { + this.isDate = isDate; + this.message = message; + } + + public boolean isDate() { + return isDate; + } + + public void setDate(boolean date) { + isDate = date; + } + + public IMMessage getMessage() { + return message; + } + + public void setMessage(IMMessage message) { + this.message = message; + } + + public void setTime(long time) { + this.time = time; + } + + public long getTime() { + return time; + } + } + + public MediaAdapter(Context context, List mediaItems) { + this.context = context; + this.mediaItems = mediaItems; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == ITEM_VIEW_TYPE_DATE) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.nim_media_item_date, parent, false); + return new DateViewHolder(view); + } else { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.nim_media_item_normal, parent, false); + return new MediaViewHolder(view); + } + } + + @Override + public int getItemViewType(int position) { + return mediaItems.get(position).isDate ? ITEM_VIEW_TYPE_DATE : ITEM_VIEW_TYPE_ITEM; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (getItemViewType(position) == ITEM_VIEW_TYPE_DATE) { + ((DateViewHolder) holder).dateText.setText(TimeUtil.getDateTimeString(mediaItems.get(position).getTime(), "yyyy年MM月")); + } else { + // 显示图片或视频缩略图 + final IMMessage msg = mediaItems.get(position).getMessage(); + if (msg.getMsgType() == MsgTypeEnum.image) { + ((MediaViewHolder) holder).playImage.setVisibility(View.GONE); + ImageAttachment imageAttachment = (ImageAttachment) msg.getAttachment(); + String path = ""; + if (!TextUtils.isEmpty(imageAttachment.getThumbPath())) { + path = imageAttachment.getThumbPath(); + } else if (!TextUtils.isEmpty(imageAttachment.getPath())) { + path = imageAttachment.getPath(); + } + Glide.with(context).load(path).into(((MediaViewHolder) holder).mediaImage); + ((MediaViewHolder) holder).mediaImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WatchMessagePictureActivity.start(context, msg, false); + } + }); + } else if (msg.getMsgType() == MsgTypeEnum.video) { + ((MediaViewHolder) holder).playImage.setVisibility(View.VISIBLE); + VideoAttachment videoAttachment = (VideoAttachment) msg.getAttachment(); + String path = ""; + if (!TextUtils.isEmpty(videoAttachment.getThumbPath())) { + path = videoAttachment.getThumbPath(); + } else if (!TextUtils.isEmpty(videoAttachment.getPath())) { + path = videoAttachment.getPath(); + } + Glide.with(context).load(path).into(((MediaViewHolder) holder).mediaImage); + ((MediaViewHolder) holder).mediaImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WatchVideoActivity.start(context, msg, false); + } + }); + } + } + } + + @Override + public int getItemCount() { + return mediaItems == null ? 0 : mediaItems.size(); + } + + public boolean isDateType(int position) { + return getItemViewType(position) == ITEM_VIEW_TYPE_DATE; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/audio/AudioMessagePlayable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/audio/AudioMessagePlayable.java new file mode 100644 index 0000000..68bf623 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/audio/AudioMessagePlayable.java @@ -0,0 +1,37 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.audio; + +import com.fengliyan.tianlesue.im.uikit.common.media.audioplayer.Playable; +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +public class AudioMessagePlayable implements Playable { + + private IMMessage message; + + public IMMessage getMessage() { + return message; + } + + public AudioMessagePlayable(IMMessage playableMessage) { + this.message = playableMessage; + } + + @Override + public long getDuration() { + return ((AudioAttachment) message.getAttachment()).getDuration(); + } + + @Override + public String getPath() { + return ((AudioAttachment) message.getAttachment()).getPath(); + } + + @Override + public boolean isAudioEqual(Playable audio) { + if (AudioMessagePlayable.class.isInstance(audio)) { + return message.isTheSame(((AudioMessagePlayable) audio).getMessage()); + } else { + return false; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/audio/MessageAudioControl.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/audio/MessageAudioControl.java new file mode 100644 index 0000000..64643d5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/audio/MessageAudioControl.java @@ -0,0 +1,226 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.audio; + +import android.content.Context; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.media.audioplayer.BaseAudioControl; +import com.fengliyan.tianlesue.im.uikit.common.media.audioplayer.Playable; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.File; +import java.util.List; + +public class MessageAudioControl extends BaseAudioControl { + private static MessageAudioControl mMessageAudioControl = null; + + private boolean mIsNeedPlayNext = false; + + private BaseMultiItemFetchLoadAdapter mAdapter; + + private IMMessage mItem = null; + + private MessageAudioControl(Context context) { + super(context, true); + } + + public static MessageAudioControl getInstance(Context context) { + if (mMessageAudioControl == null) { + synchronized (MessageAudioControl.class) { + if (mMessageAudioControl == null) { + mMessageAudioControl = new MessageAudioControl(NimUIKit.getContext()); + } + } + } + + return mMessageAudioControl; + } + + @Override + protected void setOnPlayListener(Playable playingPlayable, AudioControlListener audioControlListener) { + this.audioControlListener = audioControlListener; + + BasePlayerListener basePlayerListener = new BasePlayerListener(currentAudioPlayer, playingPlayable) { + + @Override + public void onInterrupt() { + if (!checkAudioPlayerValid()) { + return; + } + + super.onInterrupt(); + cancelPlayNext(); + } + + @Override + public void onError(String error) { + if (!checkAudioPlayerValid()) { + return; + } + + super.onError(error); + cancelPlayNext(); + } + + @Override + public void onCompletion() { + if (!checkAudioPlayerValid()) { + return; + } + + resetAudioController(listenerPlayingPlayable); + + boolean isLoop = false; + if (mIsNeedPlayNext) { + if (mAdapter != null && mItem != null) { + isLoop = playNextAudio(mAdapter, mItem); + } + } + + if (!isLoop) { + if (audioControlListener != null) { + audioControlListener.onEndPlay(currentPlayable); + } + + playSuffix(); + } + } + }; + + basePlayerListener.setAudioControlListener(audioControlListener); + currentAudioPlayer.setOnPlayListener(basePlayerListener); + } + + @Override + public IMMessage getPlayingAudio() { + if (isPlayingAudio() && AudioMessagePlayable.class.isInstance(currentPlayable)) { + return ((AudioMessagePlayable) currentPlayable).getMessage(); + } else { + return null; + } + } + + @Override + public void startPlayAudioDelay( + final long delayMillis, + final IMMessage message, + final AudioControlListener audioControlListener, final int audioStreamType) { + // 如果不存在则下载 + AudioAttachment audioAttachment = (AudioAttachment) message.getAttachment(); + File file = new File(audioAttachment.getPathForSave()); + if (!file.exists()) { + NIMClient.getService(MsgService.class).downloadAttachment(message, false).setCallback(new RequestCallbackWrapper() { + @Override + public void onResult(int code, Object result, Throwable exception) { + startPlayAudio(message, audioControlListener, audioStreamType, true, delayMillis); + } + }); + return; + } + startPlayAudio(message, audioControlListener, audioStreamType, true, delayMillis); + } + + //连续播放时不需要resetOrigAudioStreamType + private void startPlayAudio( + IMMessage message, + AudioControlListener audioControlListener, + int audioStreamType, + boolean resetOrigAudioStreamType, + long delayMillis) { + if (StorageUtil.isExternalStorageExist()) { + if (startAudio(new AudioMessagePlayable(message), audioControlListener, audioStreamType, resetOrigAudioStreamType, delayMillis)) { + // 将未读标识去掉,更新数据库 + if (isUnreadAudioMessage(message)) { + message.setStatus(MsgStatusEnum.read); + NIMClient.getService(MsgService.class).updateIMMessageStatus(message); + } + } + } else { + ToastHelper.showToast(mContext, R.string.sdcard_not_exist_error); + } + } + + private boolean playNextAudio(BaseMultiItemFetchLoadAdapter tAdapter, IMMessage messageItem) { + final List list = tAdapter.getData(); + int index = 0; + int nextIndex = -1; + //找到当前已经播放的 + for (int i = 0; i < list.size(); ++i) { + IMMessage item = (IMMessage) list.get(i); + if (item.equals(messageItem)) { + index = i; + break; + } + } + //找到下一个将要播放的 + for (int i = index; i < list.size(); ++i) { + IMMessage item = (IMMessage) list.get(i); + IMMessage message = item; + if (isUnreadAudioMessage(message)) { + nextIndex = i; + break; + } + } + + if (nextIndex == -1) { + cancelPlayNext(); + return false; + } + IMMessage message = (IMMessage) list.get(nextIndex); + AudioAttachment attach = (AudioAttachment) message.getAttachment(); + if (mMessageAudioControl != null && attach != null) { + if (message.getAttachStatus() != AttachStatusEnum.transferred) { + cancelPlayNext(); + return false; + } + if (message.getStatus() != MsgStatusEnum.read) { + message.setStatus(MsgStatusEnum.read); + NIMClient.getService(MsgService.class).updateIMMessageStatus(message); + } + //不是直接通过点击ViewHolder开始的播放,不设置AudioControlListener + //notifyDataSetChanged会触发ViewHolder刷新,对应的ViewHolder会把AudioControlListener设置上去 + //连续播放 1.继续使用playingAudioStreamType 2.不需要resetOrigAudioStreamType + mMessageAudioControl.startPlayAudio(message, null, getCurrentAudioStreamType(), false, 0); + mItem = (IMMessage) list.get(nextIndex); + tAdapter.notifyDataSetChanged(); + return true; + } + return false; + } + + private void cancelPlayNext() { + setPlayNext(false, null, null); + } + + public void setPlayNext(boolean isPlayNext, BaseMultiItemFetchLoadAdapter adapter, IMMessage item) { + mIsNeedPlayNext = isPlayNext; + mAdapter = adapter; + mItem = item; + } + + public void stopAudio() { + super.stopAudio(); + } + + public boolean isUnreadAudioMessage(IMMessage message) { + if ((message.getMsgType() == MsgTypeEnum.audio) + && message.getDirect() == MsgDirectionEnum.In + && message.getAttachStatus() == AttachStatusEnum.transferred + && message.getStatus() != MsgStatusEnum.read) { + return true; + } else { + return false; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/constant/Extras.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/constant/Extras.java new file mode 100644 index 0000000..e8df268 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/constant/Extras.java @@ -0,0 +1,47 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.constant; + +/** + * Created by zhoujianghua on 2015/8/11. + */ +public interface Extras { + + String EXTRA_FILE_PATH = "file_path"; + + String EXTRA_DATA = "data"; + + String EXTRA_FROM = "from"; + + // 选择图片 + String EXTRA_NEED_CROP = "need-crop"; + + String EXTRA_OUTPUTX = "outputX"; + + String EXTRA_OUTPUTY = "outputY"; + + String EXTRA_FROM_LOCAL = "from_local"; + + String EXTRA_SRC_FILE = "src-file"; + + String EXTRA_RETURN_DATA = "return-data"; + + // 参数 + String EXTRA_ACCOUNT = "account"; + String EXTRA_TYPE = "type"; + String EXTRA_ANCHOR = "anchor"; + + String EXTRA_CUSTOMIZATION = "customization"; + String EXTRA_BACK_TO_CLASS = "backToClass"; + + //图片选自器 + String EXTRA_PHOTO_LISTS = "photo_list"; + String EXTRA_SELECTED_IMAGE_LIST = "selected_image_list"; + String EXTRA_MUTI_SELECT_MODE = "muti_select_mode"; + String EXTRA_MUTI_SELECT_SIZE_LIMIT = "muti_select_size_limit"; + String EXTRA_SUPPORT_ORIGINAL = "support_original"; + String EXTRA_IS_ORIGINAL = "is_original"; + String EXTRA_PREVIEW_CURRENT_POS = "current_pos"; + String EXTRA_PREVIEW_IMAGE_BTN_TEXT = "preview_image_btn_text"; + String EXTRA_SCALED_IMAGE_LIST = "scaled_image_list"; + String EXTRA_ORIG_IMAGE_LIST = "orig_image_list"; + String EXTRA_NEED_SHOW_SEND_ORIGINAL = "need_show_send_original_image"; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/constant/RequestCode.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/constant/RequestCode.java new file mode 100644 index 0000000..4b24d6b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/constant/RequestCode.java @@ -0,0 +1,12 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.constant; + +public class RequestCode { + public final static int CAPTURE_VIDEO = 1;// 拍摄视频 + public final static int GET_LOCAL_VIDEO = 2;// 选择视频 + public final static int GET_LOCAL_FILE = 3; // 选择文件 + public final static int PICK_IMAGE = 4; + public final static int PICKER_IMAGE_PREVIEW = 5; + public final static int PREVIEW_IMAGE_FROM_CAMERA = 6; + public final static int GET_LOCAL_IMAGE = 7;// 相册 + public final static int SEND_ACK_MESSAGE = 8; // 发送需要已读回执的消息 +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmojiAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmojiAdapter.java new file mode 100644 index 0000000..1193d7a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmojiAdapter.java @@ -0,0 +1,55 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; + +import com.netease.nim.uikit.R; + +public class EmojiAdapter extends BaseAdapter { + + private Context context; + + private int startIndex; + + public EmojiAdapter(Context mContext, int startIndex) { + this.context = mContext; + this.startIndex = startIndex; + } + + public int getCount() { + int count = EmojiManager.getDisplayCount() - startIndex + 1; + count = Math.min(count, EmoticonView.EMOJI_PER_PAGE + 1); + return count; + } + + @Override + public Object getItem(int position) { + return null; + } + + @Override + public long getItemId(int position) { + return startIndex + position; + } + + @SuppressLint({"ViewHolder", "InflateParams"}) + public View getView(int position, View convertView, ViewGroup parent) { + convertView = LayoutInflater.from(context).inflate(R.layout.nim_emoji_item, null); + ImageView emojiThumb = (ImageView) convertView.findViewById(R.id.imgEmoji); + int count = EmojiManager.getDisplayCount(); + int index = startIndex + position; + if (position == EmoticonView.EMOJI_PER_PAGE || index == count) { + emojiThumb.setBackgroundResource(R.drawable.nim_emoji_del); + } else if (index < count) { + emojiThumb.setBackgroundDrawable(EmojiManager.getDisplayDrawable(context, index)); + } + + return convertView; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmojiManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmojiManager.java new file mode 100644 index 0000000..33506d6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmojiManager.java @@ -0,0 +1,194 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapFactory.Options; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.util.DisplayMetrics; +import android.util.LruCache; +import android.util.Xml; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +public class EmojiManager { + + private static final String EMOT_DIR = "emoji/"; + + // max cache size + private static final int CACHE_MAX_SIZE = 1024; + + private static Pattern pattern; + + // default entries + private static final List defaultEntries = new ArrayList(); + // text to entry + private static final Map text2entry = new HashMap(); + // asset bitmap cache, key: asset path + private static LruCache drawableCache; + + static { + Context context = NimUIKit.getContext(); + + load(context, EMOT_DIR + "emoji.xml"); + + pattern = makePattern(); + + drawableCache = new LruCache(CACHE_MAX_SIZE) { + @Override + protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { + if (oldValue != newValue) + oldValue.recycle(); + } + }; + } + + private static class Entry { + String text; + String assetPath; + + Entry(String text, String assetPath) { + this.text = text; + this.assetPath = assetPath; + } + } + + // + // display + // + + public static final int getDisplayCount() { + return defaultEntries.size(); + } + + public static final Drawable getDisplayDrawable(Context context, int index) { + String text = (index >= 0 && index < defaultEntries.size() ? + defaultEntries.get(index).text : null); + return text == null ? null : getDrawable(context, text); + } + + public static final String getDisplayText(int index) { + return index >= 0 && index < defaultEntries.size() ? defaultEntries + .get(index).text : null; + } + + public static final Pattern getPattern() { + return pattern; + } + + public static final Drawable getDrawable(Context context, String text) { + Entry entry = text2entry.get(text); + if (entry == null) { + return null; + } + + Bitmap cache = drawableCache.get(entry.assetPath); + if (cache == null) { + cache = loadAssetBitmap(context, entry.assetPath); + } + return new BitmapDrawable(context.getResources(), cache); + } + + // + // internal + // + + private static Pattern makePattern() { + return Pattern.compile(patternOfDefault()); + } + + private static String patternOfDefault() { + return "\\[[^\\[]{1,10}\\]"; + } + + private static Bitmap loadAssetBitmap(Context context, String assetPath) { + InputStream is = null; + try { + Resources resources = context.getResources(); + Options options = new Options(); + options.inDensity = DisplayMetrics.DENSITY_HIGH; + options.inScreenDensity = resources.getDisplayMetrics().densityDpi; + options.inTargetDensity = resources.getDisplayMetrics().densityDpi; + is = context.getAssets().open(assetPath); + Bitmap bitmap = BitmapFactory.decodeStream(is, new Rect(), options); + if (bitmap != null) { + drawableCache.put(assetPath, bitmap); + } + return bitmap; + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + private static final void load(Context context, String xmlPath) { + new EntryLoader().load(context, xmlPath); + } + + // + // load emoticons from asset + // + private static class EntryLoader extends DefaultHandler { + private String catalog = ""; + + void load(Context context, String assetPath) { + InputStream is = null; + try { + is = context.getAssets().open(assetPath); + Xml.parse(is, Xml.Encoding.UTF_8, this); + } catch (IOException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + + if (localName.equals("Catalog")) { + catalog = attributes.getValue(uri, "Title"); + } else if (localName.equals("Emoticon")) { + String tag = attributes.getValue(uri, "Tag"); + String fileName = attributes.getValue(uri, "File"); + Entry entry = new Entry(tag, EMOT_DIR + catalog + "/" + fileName); + + text2entry.put(entry.text, entry); + if (catalog.equals("default")) { + defaultEntries.add(entry); + } + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmoticonPickerView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmoticonPickerView.java new file mode 100644 index 0000000..d025f87 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmoticonPickerView.java @@ -0,0 +1,285 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Bitmap; +import android.os.Build; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.HorizontalScrollView; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.CheckedImageButton; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +/** + * 贴图表情选择控件 + */ +public class EmoticonPickerView extends LinearLayout implements IEmoticonCategoryChanged { + + private Context context; + + private IEmoticonSelectedListener listener; + + private boolean loaded = false; + + private boolean withSticker; + + private EmoticonView gifView; + + private ViewPager currentEmojiPage; + + private LinearLayout pageNumberLayout;//页面布局 + + private HorizontalScrollView scrollView; + + private LinearLayout tabView; + + private int categoryIndex; + + private Handler uiHandler; + + public EmoticonPickerView(Context context) { + super(context); + + init(context); + } + + public EmoticonPickerView(Context context, AttributeSet attrs) { + super(context, attrs); + + init(context); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public EmoticonPickerView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + init(context); + } + + private void init(Context context) { + this.context = context; + this.uiHandler = new Handler(context.getMainLooper()); + + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.nim_emoji_layout, this); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + setupEmojView(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + } + + public void show(IEmoticonSelectedListener listener) { + setListener(listener); + + if (loaded) + return; + loadStickers(); + loaded = true; + + show(); + } + + public void setListener(IEmoticonSelectedListener listener) { + if (listener != null) { + this.listener = listener; + } else { + LogUtil.i("sticker", "listener is null"); + } + } + + protected void setupEmojView() { + currentEmojiPage = (ViewPager) findViewById(R.id.scrPlugin); + pageNumberLayout = (LinearLayout) findViewById(R.id.layout_scr_bottom); + tabView = (LinearLayout) findViewById(R.id.emoj_tab_view); + scrollView = (HorizontalScrollView) findViewById(R.id.emoj_tab_view_container); + + findViewById(R.id.top_divider_line).setVisibility(View.VISIBLE); + } + + // 添加各个tab按钮 + OnClickListener tabCheckListener = new OnClickListener() { + @Override + public void onClick(View v) { + onEmoticonBtnChecked(v.getId()); + } + }; + + private void loadStickers() { + if (!withSticker) { + scrollView.setVisibility(View.GONE); + return; + } + + final StickerManager manager = StickerManager.getInstance(); + + tabView.removeAllViews(); + + int index = 0; + + // emoji表情 + CheckedImageButton btn = addEmoticonTabBtn(index++, tabCheckListener); + btn.setNormalImageId(R.drawable.nim_emoji_icon_inactive); + btn.setCheckedImageId(R.drawable.nim_emoji_icon); + + // 贴图 + List categories = manager.getCategories(); + for (StickerCategory category : categories) { + btn = addEmoticonTabBtn(index++, tabCheckListener); + setCheckedButtomImage(btn, category); + } + } + + + private CheckedImageButton addEmoticonTabBtn(int index, OnClickListener listener) { + CheckedImageButton emotBtn = new CheckedImageButton(context); + emotBtn.setNormalBkResId(R.drawable.nim_sticker_button_background_normal_layer_list); + emotBtn.setCheckedBkResId(R.drawable.nim_sticker_button_background_pressed_layer_list); + emotBtn.setId(index); + emotBtn.setOnClickListener(listener); + emotBtn.setScaleType(ImageView.ScaleType.FIT_CENTER); + emotBtn.setPaddingValue(ScreenUtil.dip2px(7)); + + final int emojiBtnWidth = ScreenUtil.dip2px(50); + final int emojiBtnHeight = ScreenUtil.dip2px(44); + + tabView.addView(emotBtn); + + ViewGroup.LayoutParams emojBtnLayoutParams = emotBtn.getLayoutParams(); + emojBtnLayoutParams.width = emojiBtnWidth; + emojBtnLayoutParams.height = emojiBtnHeight; + emotBtn.setLayoutParams(emojBtnLayoutParams); + + return emotBtn; + } + + private void setCheckedButtomImage(CheckedImageButton btn, StickerCategory category) { + try { + InputStream is = category.getCoverNormalInputStream(context); + if (is != null) { + Bitmap bmp = BitmapDecoder.decode(is); + btn.setNormalImage(bmp); + is.close(); + } + is = category.getCoverPressedInputStream(context); + if (is != null) { + Bitmap bmp = BitmapDecoder.decode(is); + btn.setCheckedImage(bmp); + is.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void onEmoticonBtnChecked(int index) { + updateTabButton(index); + showEmotPager(index); + } + + private void updateTabButton(int index) { + for (int i = 0; i < tabView.getChildCount(); ++i) { + View child = tabView.getChildAt(i); + if (child instanceof FrameLayout) { + child = ((FrameLayout) child).getChildAt(0); + } + + if (child != null && child instanceof CheckedImageButton) { + CheckedImageButton tabButton = (CheckedImageButton) child; + if (tabButton.isChecked() && i != index) { + tabButton.setChecked(false); + } else if (!tabButton.isChecked() && i == index) { + tabButton.setChecked(true); + } + } + } + } + + private void showEmotPager(int index) { + if (gifView == null) { + gifView = new EmoticonView(context, listener, currentEmojiPage, pageNumberLayout); + gifView.setCategoryChangCheckedCallback(this); + } + + gifView.showStickers(index); + } + + private void showEmojiView() { + if (gifView == null) { + gifView = new EmoticonView(context, listener, currentEmojiPage, pageNumberLayout); + } + gifView.showEmojis(); + } + + private void show() { + if (listener == null) { + LogUtil.i("sticker", "show picker view when listener is null"); + } + if (!withSticker) { + showEmojiView(); + } else { + onEmoticonBtnChecked(0); + setSelectedVisible(0); + } + } + + + private void setSelectedVisible(final int index) { + final Runnable runnable = new Runnable() { + @Override + public void run() { + if (scrollView.getChildAt(0).getWidth() == 0) { + uiHandler.postDelayed(this, 100); + } + int x = -1; + View child = tabView.getChildAt(index); + if (child != null) { + if (child.getRight() > scrollView.getWidth()) { + x = child.getRight() - scrollView.getWidth(); + } + } + if (x != -1) { + scrollView.smoothScrollTo(x, 0); + } + } + }; + uiHandler.postDelayed(runnable, 100); + } + + + @Override + public void onCategoryChanged(int index) { + if (categoryIndex == index) { + return; + } + + categoryIndex = index; + updateTabButton(index); + } + + public void setWithSticker(boolean withSticker) { + this.withSticker = withSticker; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmoticonView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmoticonView.java new file mode 100644 index 0000000..18374ec --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/EmoticonView.java @@ -0,0 +1,389 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.content.Context; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * 贴图显示viewpager + */ +public class EmoticonView { + + private ViewPager emotPager; + private LinearLayout pageNumberLayout; + /** + * 总页数. + */ + private int pageCount; + + /** + * 每页显示的数量,Adapter保持一致. + */ + public static final int EMOJI_PER_PAGE = 27; // 最后一个是删除键 + public static final int STICKER_PER_PAGE = 8; + + private Context context; + private IEmoticonSelectedListener listener; + private EmoticonViewPaperAdapter pagerAdapter = new EmoticonViewPaperAdapter(); + + /** + * 所有表情贴图支持横向滑动切换 + */ + private int categoryIndex; // 当套贴图的在picker中的索引 + private boolean isDataInitialized = false; // 数据源只需要初始化一次,变更时再初始化 + private List categoryDataList; // 表情贴图数据源 + private List categoryPageNumberList; // 每套表情贴图对应的页数 + private int[] pagerIndexInfo = new int[2]; // 0:category index;1:pager index in category + private IEmoticonCategoryChanged categoryChangedCallback; // 横向滑动切换时回调picker + + public EmoticonView(Context context, IEmoticonSelectedListener mlistener, + ViewPager mCurPage, LinearLayout pageNumberLayout) { + this.context = context.getApplicationContext(); + this.listener = mlistener; + this.pageNumberLayout = pageNumberLayout; + this.emotPager = mCurPage; + + emotPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageSelected(int position) { + if (categoryDataList != null) { + // 显示所有贴图表情 + setCurStickerPage(position); + if (categoryChangedCallback != null) { + int currentCategoryChecked = pagerIndexInfo[0];// 当前那种类别被选中 + categoryChangedCallback.onCategoryChanged(currentCategoryChecked); + } + } else { + // 只显示表情 + setCurEmotionPage(position); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + }); + emotPager.setAdapter(pagerAdapter); + emotPager.setOffscreenPageLimit(1); + } + + public void setCategoryDataReloadFlag() { + isDataInitialized = false; + } + + public void showStickers(int index) { + // 判断是否需要变化 + if (isDataInitialized && getPagerInfo(emotPager.getCurrentItem()) != null + && pagerIndexInfo[0] == index && pagerIndexInfo[1] == 0) { + return; + } + + this.categoryIndex = index; + showStickerGridView(); + } + + public void showEmojis() { + showEmojiGridView(); + } + + private int getCategoryPageCount(StickerCategory category) { + if (category == null) { + return (int) Math.ceil(EmojiManager.getDisplayCount() / (float) EMOJI_PER_PAGE); + } else { + if (category.hasStickers()) { + List stickers = category.getStickers(); + return (int) Math.ceil(stickers.size() / (float) STICKER_PER_PAGE); + } else { + return 1; + } + } + } + + private void setCurPage(int page, int pageCount) { + int hasCount = pageNumberLayout.getChildCount(); + int forMax = Math.max(hasCount, pageCount); + + ImageView imgCur = null; + for (int i = 0; i < forMax; i++) { + if (pageCount <= hasCount) { + if (i >= pageCount) { + pageNumberLayout.getChildAt(i).setVisibility(View.GONE); + continue; + } else { + imgCur = (ImageView) pageNumberLayout.getChildAt(i); + } + } else { + if (i < hasCount) { + imgCur = (ImageView) pageNumberLayout.getChildAt(i); + } else { + imgCur = new ImageView(context); + imgCur.setBackgroundResource(R.drawable.nim_view_pager_indicator_selector); + pageNumberLayout.addView(imgCur); + } + } + + imgCur.setId(i); + imgCur.setSelected(i == page); // 判断当前页码来更新 + imgCur.setVisibility(View.VISIBLE); + } + } + + /** + * ******************************** 表情 ******************************* + */ + private void showEmojiGridView() { + pageCount = (int) Math.ceil(EmojiManager.getDisplayCount() / (float) EMOJI_PER_PAGE); + pagerAdapter.notifyDataSetChanged(); + resetEmotionPager(); + } + + private void resetEmotionPager() { + setCurEmotionPage(0); + emotPager.setCurrentItem(0, false); + } + + private void setCurEmotionPage(int position) { + setCurPage(position, pageCount); + } + + public OnItemClickListener emojiListener = new OnItemClickListener() { + public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) { + int position = emotPager.getCurrentItem(); + int pos = position; // 如果只有表情,那么用默认方式计算 + if (categoryDataList != null && categoryPageNumberList != null) { + // 包含贴图 + getPagerInfo(position); + pos = pagerIndexInfo[1]; + } + + int index = arg2 + pos * EMOJI_PER_PAGE; + + if (listener != null) { + int count = EmojiManager.getDisplayCount(); + if (arg2 == EMOJI_PER_PAGE || index >= count) { + listener.onEmojiSelected("/DEL"); + } else { + String text = EmojiManager.getDisplayText((int) arg3); + if (!TextUtils.isEmpty(text)) { + listener.onEmojiSelected(text); + } + } + } + } + }; + + /** + * ******************************** 贴图 ******************************* + */ + + private void showStickerGridView() { + initData(); + pagerAdapter.notifyDataSetChanged(); + + // 计算起始的pager index + int position = 0; + for (int i = 0; i < categoryPageNumberList.size(); i++) { + if (i == categoryIndex) { + break; + } + position += categoryPageNumberList.get(i); + } + + setCurStickerPage(position); + emotPager.setCurrentItem(position, false); + } + + private void initData() { + if (isDataInitialized) {//数据已经初始化,未变动不重新加载数据 + return; + } + + if (categoryDataList == null) { + categoryDataList = new ArrayList<>(); + } + + if (categoryPageNumberList == null) { + categoryPageNumberList = new ArrayList<>(); + } + + categoryDataList.clear(); + categoryPageNumberList.clear(); + + final StickerManager manager = StickerManager.getInstance(); + + categoryDataList.add(null); // 表情 + categoryPageNumberList.add(getCategoryPageCount(null)); + + List categories = manager.getCategories(); + + categoryDataList.addAll(categories); // 贴图 + for (StickerCategory c : categories) { + categoryPageNumberList.add(getCategoryPageCount(c)); + } + + pageCount = 0;//总页数 + for (Integer count : categoryPageNumberList) { + pageCount += count; + } + + isDataInitialized = true; + } + + // 给定pager中的索引,返回categoryIndex和positionInCategory + private int[] getPagerInfo(int position) { + if (categoryDataList == null || categoryPageNumberList == null) { + return pagerIndexInfo; + } + + int cIndex = categoryIndex; + int startIndex = 0; + int pageNumberPerCategory = 0; + for (int i = 0; i < categoryPageNumberList.size(); i++) { + pageNumberPerCategory = categoryPageNumberList.get(i); + if (position < startIndex + pageNumberPerCategory) { + cIndex = i; + break; + } + startIndex += pageNumberPerCategory; + } + + this.pagerIndexInfo[0] = cIndex; + this.pagerIndexInfo[1] = position - startIndex; + + return pagerIndexInfo; + } + + private void setCurStickerPage(int position) { + getPagerInfo(position); + int categoryIndex = pagerIndexInfo[0]; + int pageIndexInCategory = pagerIndexInfo[1]; + int categoryPageCount = categoryPageNumberList.get(categoryIndex); + + setCurPage(pageIndexInCategory, categoryPageCount); + } + + public void setCategoryChangCheckedCallback(IEmoticonCategoryChanged callback) { + this.categoryChangedCallback = callback; + } + + private OnItemClickListener stickerListener = new OnItemClickListener() { + public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) { + int position = emotPager.getCurrentItem(); + getPagerInfo(position); + int cIndex = pagerIndexInfo[0]; + int pos = pagerIndexInfo[1]; + StickerCategory c = categoryDataList.get(cIndex); + int index = arg2 + pos * STICKER_PER_PAGE; // 在category中贴图的index + + if (index >= c.getStickers().size()) { + LogUtil.i("sticker", "index " + index + " larger than size " + c.getStickers().size()); + return; + } + + if (listener != null) { + StickerManager manager = StickerManager.getInstance(); + List stickers = c.getStickers(); + StickerItem sticker = stickers.get(index); + StickerCategory real = manager.getCategory(sticker.getCategory()); + + if (real == null) { + return; + } + + listener.onStickerSelected(sticker.getCategory(), sticker.getName()); + } + } + }; + + + /** + * ***************************** PagerAdapter **************************** + */ + private class EmoticonViewPaperAdapter extends PagerAdapter { + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public int getCount() { + return pageCount == 0 ? 1 : pageCount; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + StickerCategory category; + int pos; + if (categoryDataList != null && categoryDataList.size() > 0 && categoryPageNumberList != null + && categoryPageNumberList.size() > 0) { + // 显示所有贴图&表情 + getPagerInfo(position); + int cIndex = pagerIndexInfo[0]; + category = categoryDataList.get(cIndex); + pos = pagerIndexInfo[1]; + } else { + // 只显示表情 + category = null; + pos = position; + } + + if (category == null) { + pageNumberLayout.setVisibility(View.VISIBLE); + GridView gridView = new GridView(context); + gridView.setOnItemClickListener(emojiListener); + gridView.setAdapter(new EmojiAdapter(context, pos * EMOJI_PER_PAGE)); + gridView.setNumColumns(7); + gridView.setHorizontalSpacing(5); + gridView.setVerticalSpacing(5); + gridView.setGravity(Gravity.CENTER); + gridView.setSelector(R.drawable.nim_emoji_item_selector); + container.addView(gridView); + return gridView; + } else { + pageNumberLayout.setVisibility(View.VISIBLE); + GridView gridView = new GridView(context); + gridView.setPadding(10, 0, 10, 0); + gridView.setOnItemClickListener(stickerListener); + gridView.setAdapter(new StickerAdapter(context, category, pos * STICKER_PER_PAGE)); + gridView.setNumColumns(4); + gridView.setHorizontalSpacing(5); + gridView.setGravity(Gravity.CENTER); + gridView.setSelector(R.drawable.nim_emoji_item_selector); + container.addView(gridView); + return gridView; + } + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + View layout = (View) object; + container.removeView(layout); + } + + public int getItemPosition(Object object) { + return POSITION_NONE; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/IEmoticonCategoryChanged.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/IEmoticonCategoryChanged.java new file mode 100644 index 0000000..d0ea736 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/IEmoticonCategoryChanged.java @@ -0,0 +1,5 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +public interface IEmoticonCategoryChanged { + void onCategoryChanged(int index); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/IEmoticonSelectedListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/IEmoticonSelectedListener.java new file mode 100644 index 0000000..b22fee9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/IEmoticonSelectedListener.java @@ -0,0 +1,7 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +public interface IEmoticonSelectedListener { + void onEmojiSelected(String key); + + void onStickerSelected(String categoryName, String stickerName); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/ImageSpanAlignCenter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/ImageSpanAlignCenter.java new file mode 100644 index 0000000..a898e96 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/ImageSpanAlignCenter.java @@ -0,0 +1,89 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.text.style.ImageSpan; + +import java.lang.ref.WeakReference; + +/** + * + */ + +public class ImageSpanAlignCenter extends ImageSpan { + + private static final char[] ELLIPSIS_NORMAL = {'\u2026'}; + private static final char[] ELLIPSIS_TWO_DOTS = {'\u2025'}; + + public ImageSpanAlignCenter(Context context, int resourceId) { + super(context, resourceId); + } + + public ImageSpanAlignCenter(Drawable d) { + super(d); + } + + @Override + public int getSize(Paint paint, CharSequence text, + int start, int end, + Paint.FontMetricsInt fm) { + Drawable d = getCachedDrawable(paint); + Rect rect = d.getBounds(); + + if (fm != null) { + Paint.FontMetricsInt fontMetrics = new Paint.FontMetricsInt(); + paint.getFontMetricsInt(fontMetrics); + + fm.ascent = fontMetrics.ascent; + fm.descent = fontMetrics.descent; + + fm.top = fontMetrics.top; + fm.bottom = fontMetrics.bottom; + } + return rect.right; + } + + @Override + public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, + int bottom, Paint paint) { + final String s = text.toString(); + String subS = s.substring(start, end); + if (ELLIPSIS_NORMAL[0] == subS.charAt(0) + || ELLIPSIS_TWO_DOTS[0] == subS.charAt(0)) { + canvas.save(); + canvas.drawText(subS, x, y, paint); + canvas.restore(); + } else { + Drawable d = getCachedDrawable(paint); + canvas.save(); + int transY; + Paint.FontMetricsInt fontMetrics = new Paint.FontMetricsInt(); + paint.getFontMetricsInt(fontMetrics); + transY = y + fontMetrics.ascent; + canvas.translate(x, transY); + d.draw(canvas); + canvas.restore(); + } + } + + private Drawable getCachedDrawable(Paint paint) { + WeakReference wr = mDrawableRef; + Drawable d = null; + + if (wr != null) + d = wr.get(); + + if (d == null) { + d = getDrawable(); + d.setBounds(new Rect(0, 0, paint.getFontMetricsInt(null), paint.getFontMetricsInt(null))); + mDrawableRef = new WeakReference(d); + } + + return d; + } + + private WeakReference mDrawableRef; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/MoonUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/MoonUtil.java new file mode 100644 index 0000000..5d3c4ec --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/MoonUtil.java @@ -0,0 +1,235 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.style.ClickableSpan; +import android.text.style.ImageSpan; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.recent.TeamMemberAitHelper; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MoonUtil { + private static final float DEF_SCALE = 0.6f; + private static final float SMALL_SCALE = 0.45F; + + public static void identifyFaceExpression(Context context, + View textView, String value, int align) { + identifyFaceExpression(context, textView, value, align, DEF_SCALE); + } + + public static void identifyFaceExpressionAndATags(Context context, + View textView, String value, int align) { + SpannableString mSpannableString = makeSpannableStringTags(context, value, DEF_SCALE, align); + viewSetText(textView, mSpannableString); + } + + /** + * 具体类型的view设置内容 + * + * @param textView + * @param mSpannableString + */ + private static void viewSetText(View textView, SpannableString mSpannableString) { + if (textView instanceof TextView) { + TextView tv = (TextView) textView; + tv.setText(mSpannableString); + } else if (textView instanceof EditText) { + EditText et = (EditText) textView; + et.setText(mSpannableString); + } + } + + public static void identifyFaceExpression(Context context, + View textView, String value, int align, float scale) { + SpannableString mSpannableString = replaceEmoticons(context, value, scale, align); + viewSetText(textView, mSpannableString); + } + + public static void identifyRecentVHFaceExpressionAndTags(Context context, View textView, + String value, int align, float scale) { + SpannableString mSpannableString = makeSpannableStringTags(context, value, scale, align, false); + TeamMemberAitHelper.replaceAitForeground(value, mSpannableString); + viewSetText(textView, mSpannableString); + } + + /** + * lstmsgviewholder类使用,只需显示a标签对应的文本 + */ + public static void identifyFaceExpressionAndTags(Context context, + View textView, String value, int align, float scale) { + SpannableString mSpannableString = makeSpannableStringTags(context, value, scale, align, false); + viewSetText(textView, mSpannableString); + } + + private static SpannableString replaceEmoticons(Context context, String value, float scale, int align) { + if (TextUtils.isEmpty(value)) { + value = ""; + } + + SpannableString mSpannableString = new SpannableString(value); + Matcher matcher = EmojiManager.getPattern().matcher(value); + while (matcher.find()) { + int start = matcher.start(); + int end = matcher.end(); + String emot = value.substring(start, end); + Drawable d = getEmotDrawable(context, emot, scale); + if (d != null) { + ImageSpan span = new ImageSpan(d, align); + mSpannableString.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + return mSpannableString; + } + + private static Pattern mATagPattern = Pattern.compile(".*?"); + + public static SpannableString makeSpannableStringTags(Context context, String value, float scale, int align) { + return makeSpannableStringTags(context, value, DEF_SCALE, align, true); + } + + public static SpannableString makeSpannableStringTags(Context context, String value, float scale, int align, boolean bTagClickable) { + ArrayList tagSpans = new ArrayList(); + if (TextUtils.isEmpty(value)) { + value = ""; + } + //a标签需要替换原始文本,放在moonutil类中 + Matcher aTagMatcher = mATagPattern.matcher(value); + + int start = 0; + int end = 0; + while (aTagMatcher.find()) { + start = aTagMatcher.start(); + end = aTagMatcher.end(); + String atagString = value.substring(start, end); + ATagSpan tagSpan = getTagSpan(atagString); + value = value.substring(0, start) + tagSpan.getTag() + value.substring(end); + tagSpan.setRange(start, start + tagSpan.getTag().length()); + tagSpans.add(tagSpan); + aTagMatcher = mATagPattern.matcher(value); + } + + + SpannableString mSpannableString = new SpannableString(value); + Matcher matcher = EmojiManager.getPattern().matcher(value); + while (matcher.find()) { + start = matcher.start(); + end = matcher.end(); + String emot = value.substring(start, end); + Drawable d = getEmotDrawable(context, emot, scale); + if (d != null) { + ImageSpan span = align == -1 ? new ImageSpanAlignCenter(d) : new ImageSpan(d, align); + mSpannableString.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + + if (bTagClickable) { + for (ATagSpan tagSpan : tagSpans) { + mSpannableString.setSpan(tagSpan, tagSpan.start, tagSpan.end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + + return mSpannableString; + } + + public static void replaceEmoticons(Context context, Editable editable, int start, int count) { + if (count <= 0 || editable.length() < start + count) + return; + + CharSequence s = editable.subSequence(start, start + count); + Matcher matcher = EmojiManager.getPattern().matcher(s); + while (matcher.find()) { + int from = start + matcher.start(); + int to = start + matcher.end(); + String emot = editable.subSequence(from, to).toString(); + Drawable d = getEmotDrawable(context, emot, SMALL_SCALE); + if (d != null) { + ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BOTTOM); + editable.setSpan(span, from, to, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + } + + private static Drawable getEmotDrawable(Context context, String text, float scale) { + Drawable drawable = EmojiManager.getDrawable(context, text); + + // scale + if (drawable != null) { + int width = (int) (drawable.getIntrinsicWidth() * scale); + int height = (int) (drawable.getIntrinsicHeight() * scale); + drawable.setBounds(0, 0, width, height); + } + + return drawable; + } + + private static ATagSpan getTagSpan(String text) { + String href = null; + String tag = null; + if (text.toLowerCase().contains("href")) { + int start = text.indexOf("\""); + int end = text.indexOf("\"", start + 1); + if (end > start) + href = text.substring(start + 1, end); + } + int start = text.indexOf(">"); + int end = text.indexOf("<", start); + if (end > start) + tag = text.substring(start + 1, end); + return new ATagSpan(tag, href); + + } + + private static class ATagSpan extends ClickableSpan { + private int start; + private int end; + private String mUrl; + private String tag; + + ATagSpan(String tag, String url) { + this.tag = tag; + this.mUrl = url; + } + + @Override + public void updateDrawState(TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(true); + } + + public String getTag() { + return tag; + } + + public void setRange(int start, int end) { + this.start = start; + this.end = end; + } + + @Override + public void onClick(View widget) { + try { + if (TextUtils.isEmpty(mUrl)) + return; + Uri uri = Uri.parse(mUrl); + String scheme = uri.getScheme(); + if (TextUtils.isEmpty(scheme)) { + mUrl = "http://" + mUrl; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerAdapter.java new file mode 100644 index 0000000..1b3cb58 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerAdapter.java @@ -0,0 +1,86 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.RequestOptions; +import com.netease.nim.uikit.R; + +/** + * 每屏显示的贴图 + */ +public class StickerAdapter extends BaseAdapter { + + private Context context; + private StickerCategory category; + private int startIndex; + + public StickerAdapter(Context mContext, StickerCategory category, int startIndex) { + this.context = mContext; + this.category = category; + this.startIndex = startIndex; + } + + public int getCount() {//获取每一页的数量 + int count = category.getStickers().size() - startIndex; + count = Math.min(count, EmoticonView.STICKER_PER_PAGE); + return count; + } + + @Override + public Object getItem(int position) { + return category.getStickers().get(startIndex + position); + } + + @Override + public long getItemId(int position) { + return startIndex + position; + } + + + public View getView(int position, View convertView, ViewGroup parent) { + StickerViewHolder viewHolder; + if (convertView == null) { + convertView = View.inflate(context, R.layout.nim_sticker_picker_view, null); + viewHolder = new StickerViewHolder(); + viewHolder.imageView = (ImageView) convertView.findViewById(R.id.sticker_thumb_image); + viewHolder.descLabel = (TextView) convertView.findViewById(R.id.sticker_desc_label); + convertView.setTag(viewHolder); + } else { + viewHolder = (StickerViewHolder) convertView.getTag(); + } + + int index = startIndex + position; + if (index >= category.getStickers().size()) { + return convertView; + } + + StickerItem sticker = category.getStickers().get(index); + if (sticker == null) { + return convertView; + } + + Glide.with(context) + .load(StickerManager.getInstance().getStickerUri(sticker.getCategory(), sticker.getName())) + .apply(new RequestOptions() + .error(R.drawable.nim_default_img_failed) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .dontAnimate()) + .into(viewHolder.imageView); + + viewHolder.descLabel.setVisibility(View.GONE); + + return convertView; + } + + class StickerViewHolder { + public ImageView imageView; + public TextView descLabel; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerCategory.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerCategory.java new file mode 100644 index 0000000..09d8bd7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerCategory.java @@ -0,0 +1,135 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.content.Context; +import android.content.res.AssetManager; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class StickerCategory implements Serializable { + private static final long serialVersionUID = -81692490861539040L; + + private String name; // 贴纸包名 + private String title; // 显示的标题 + private boolean system; // 是否是系统内置表情 + private int order = 0; // 默认顺序 + + private transient List stickers; + + public StickerCategory(String name, String title, boolean system, int order) { + this.title = title; + this.name = name; + this.system = system; + this.order = order; + + loadStickerData(); + } + + public boolean system() { + return system; + } + + public void setSystem(boolean system) { + this.system = system; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getStickers() { + return stickers; + } + + public boolean hasStickers() { + return stickers != null && stickers.size() > 0; + } + + public InputStream getCoverNormalInputStream(Context context) { + String filename = name + "_s_normal.png"; + return makeFileInputStream(context, filename); + } + + public InputStream getCoverPressedInputStream(Context context) { + String filename = name + "_s_pressed.png"; + return makeFileInputStream(context, filename); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getCount() { + if (stickers == null || stickers.isEmpty()) { + return 0; + } + + return stickers.size(); + } + + public int getOrder() { + return order; + } + + private InputStream makeFileInputStream(Context context, String filename) { + try { + if (system) { + AssetManager assetManager = context.getResources().getAssets(); + String path = "sticker/" + filename; + return assetManager.open(path); + } else { + // for future + } + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + public List loadStickerData() { + List stickers = new ArrayList<>(); + AssetManager assetManager = NimUIKit.getContext().getResources().getAssets(); + try { + String[] files = assetManager.list("sticker/" + name); + for (String file : files) { + stickers.add(new StickerItem(name, file)); + } + } catch (IOException e) { + e.printStackTrace(); + } + + this.stickers = stickers; + return stickers; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof StickerCategory)) { + return false; + } + if (o == this) { + return true; + } + StickerCategory r = (StickerCategory) o; + return r.getName().equals(getName()); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerItem.java new file mode 100644 index 0000000..d1fb0f4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerItem.java @@ -0,0 +1,33 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +public class StickerItem { + private String category;//类别名 + private String name; + + public StickerItem(String category, String name) { + this.category = category; + this.name = name; + } + + public String getIdentifier() { + return category + "/" + name; + } + + public String getCategory() { + return category; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (o != null && o instanceof StickerItem) { + StickerItem item = (StickerItem) o; + return item.getCategory().equals(category) && item.getName().equals(name); + } + + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerManager.java new file mode 100644 index 0000000..405fe40 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/emoji/StickerManager.java @@ -0,0 +1,123 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.emoji; + +import android.content.res.AssetManager; +import android.util.Log; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 贴图管理类 + */ +public class StickerManager { + private static final String TAG = "StickerManager"; + + private static StickerManager instance; + private static final String CATEGORY_AJMD = "ajmd"; + private static final String CATEGORY_XXY = "xxy"; + private static final String CATEGORY_LT = "lt"; + + /** + * 数据源 + */ + private List stickerCategories = new ArrayList<>(); + private Map stickerCategoryMap = new HashMap<>(); + private Map stickerOrder = new HashMap<>(3); + + public static StickerManager getInstance() { + if (instance == null) { + instance = new StickerManager(); + } + + return instance; + } + + public StickerManager() { + initStickerOrder(); + loadStickerCategory(); + } + + public void init() { + Log.i(TAG, "Sticker Manager init..."); + } + + private void initStickerOrder() { + // 默认贴图顺序 + stickerOrder.put(CATEGORY_AJMD, 1); + stickerOrder.put(CATEGORY_XXY, 2); + stickerOrder.put(CATEGORY_LT, 3); + } + + private boolean isSystemSticker(String category) { + return CATEGORY_XXY.equals(category) || + CATEGORY_AJMD.equals(category) || + CATEGORY_LT.equals(category); + } + + private int getStickerOrder(String categoryName) { + if (stickerOrder.containsKey(categoryName)) { + return stickerOrder.get(categoryName); + } else { + return 100; + } + } + + private void loadStickerCategory() { + AssetManager assetManager = NimUIKit.getContext().getResources().getAssets(); + try { + String[] files = assetManager.list("sticker"); + StickerCategory category; + for (String name : files) { + if (!FileUtil.hasExtentsion(name)) { + category = new StickerCategory(name, name, true, getStickerOrder(name)); + stickerCategories.add(category); + stickerCategoryMap.put(name, category); + } + } + // 排序 + Collections.sort(stickerCategories, new Comparator() { + @Override + public int compare(StickerCategory l, StickerCategory r) { + return l.getOrder() - r.getOrder(); + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public synchronized List getCategories() { + return stickerCategories; + } + + public synchronized StickerCategory getCategory(String name) { + return stickerCategoryMap.get(name); + } + + public String getStickerUri(String categoryName, String stickerName) { + StickerManager manager = StickerManager.getInstance(); + StickerCategory category = manager.getCategory(categoryName); + if (category == null) { + return null; + } + + if (isSystemSticker(categoryName)) { + if (!stickerName.contains(".png")) { + stickerName += ".png"; + } + + String path = "sticker/" + category.getName() + "/" + stickerName; + return "file:///android_asset/" + path; + } + + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/fragment/MessageFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/fragment/MessageFragment.java new file mode 100644 index 0000000..4a4e7d1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/fragment/MessageFragment.java @@ -0,0 +1,1904 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.fragment; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.app.AlertDialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.media.AudioManager; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.blankj.utilcode.util.GsonUtils; +import com.bumptech.glide.Glide; +import com.facebook.drawee.view.SimpleDraweeView; +import com.flyco.roundview.RoundLinearLayout; +import com.google.gson.Gson; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.messaging.EventBusGiftMessage; +import com.fengliyan.messaging.GiftAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.utils.ToastUtil; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.main.adapter.MsgCallListAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.news.manager.NewsManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.UIKitOptions; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.main.CustomPushContentProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.business.ait.AitManager; +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.fengliyan.tianlesue.im.uikit.business.session.actions.ImageAction; +import com.fengliyan.tianlesue.im.uikit.business.session.actions.VideoAction; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.business.session.module.ModuleProxy; +import com.fengliyan.tianlesue.im.uikit.business.session.module.input.InputPanel; +import com.fengliyan.tianlesue.im.uikit.business.session.module.list.MessageListPanelEx; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.CommonUtil; +import com.fengliyan.tianlesue.im.uikit.common.fragment.TFragment; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.model.chat.ImageCheckBean; +import com.fengliyan.tianlesue.model.chat.RecoverBean; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.ContactBean; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.model.news.ChatTipBean; +import com.fengliyan.tianlesue.model.news.IMCostBean; +import com.fengliyan.tianlesue.utils.AnimUtils; +import com.fengliyan.tianlesue.utils.FrameAnimation; +import com.fengliyan.tianlesue.utils.GlideEngine; +import com.fengliyan.tianlesue.utils.GlideUtils; +import com.fengliyan.tianlesue.utils.MaskImageView; +import com.fengliyan.tianlesue.utils.MeOnPermissionDescriptionListener; +import com.fengliyan.tianlesue.utils.MeOnResultCallbackListener; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.utils.camera2.BitmapUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.GuardDialog; +import com.fengliyan.tianlesue.view.main.AgoraWithFUVideoActivity; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.main.dialog.ConfirmWXAccountDialog; +import com.fengliyan.tianlesue.view.main.dialog.SvgaDialog; +import com.fengliyan.tianlesue.view.news.activity.ChatSettingActivity; +import com.fengliyan.tianlesue.view.settings.CaibeiRechargeActivity; +import com.fengliyan.tianlesue.view.settings.CertificationActivity; +import com.fengliyan.tianlesue.view.settings.MemberActivity; +import com.fengliyan.tianlesue.view.settings.RealNameActivity; +import com.fengliyan.tianlesue.view.settings.dialog.ChatCardRedPacketDialog; +import com.fengliyan.tianlesue.view.settings.dialog.SelectTypeDialog; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.dialog.BottomGiftDialog; +import com.fengliyan.uikit.dialog.DialogGiftBean; +import com.fengliyan.uikit.dialog.GiftListBean; +import com.fengliyan.uikit.toast.MaleToast; +import com.luck.picture.lib.basic.PictureSelector; +import com.luck.picture.lib.config.SelectMimeType; +import com.luck.picture.lib.config.SelectModeConfig; +import com.luck.picture.lib.style.PictureSelectorStyle; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomMessageConfig; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.MemberPushOption; +import com.netease.nimlib.sdk.msg.model.MessageReceipt; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.robot.model.RobotMsgType; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.greenrobot.event.EventBus; + +/** + * 聊天界面基类 + *

+ * Created by huangjun on 2015/2/1. + */ +public class MessageFragment extends TFragment implements ModuleProxy, SelectTypeDialog.OnSelectListener, MessageListPanelEx.RecoverListener, InputPanel.RecoverStateListener, View.OnClickListener, MsgCallListAdapter.OnClickedListener { + + private View rootView; + + private SessionCustomization customization; + + protected static final String TAG = "MessageActivity"; + + // p2p对方Account或者群id + protected String sessionId; + + protected SessionTypeEnum sessionType; + + // modules + protected InputPanel inputPanel; + protected MessageListPanelEx messageListPanel; + + protected AitManager aitManager; + + private boolean isShowEditBar; + private boolean isShowGiftAndVideo; + private RelativeLayout rl_message_root; + private LinearLayout lin_msg_dynamic; + private TextView tv_msg_like; + private TextView tv_msg_comment; + private TextView tv_msg_follow; + private ImageAction mImageAction; + private VideoAction mVideoAction; + private GuardDialog mGuardDialog; + private RelativeLayout rl_guard; + private RelativeLayout rl_guard_view; + private ImageView mIv_guard; + private ImageView ic_guard_close; + private SvgaDialog mSvgaDialog; + private boolean isResume; + private RoundLinearLayout wxContainer; + private TextView lookBtn; + private TextView copyBtn; + FrameAnimation guardAnimation; + private MaskImageView maskImageView; + private ImageView iv_msg_bg; + private ImageView iv_back; + private TextView tv_user_name; + private ImageView iv_interactive; + private ImageView iv_user_info; + private ConstraintLayout cl_info_card; + private TextView tv_user_info; + private TextView tv_user_act; + private TextView tv_user_auth; + private SimpleDraweeView iv_album1; + private SimpleDraweeView iv_album2; + private SimpleDraweeView iv_album3; + private SimpleDraweeView iv_album4; + private RecyclerView rv_call_list; + private MsgCallListAdapter mAdapter; + + private String title; + private String avatar; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + parseIntent(); + } + + void refreshWeChatStatus(ContactBean.WechatBean mMainPageBean) { + String sysID = UserManager.getGlobalConfigInfo().getConfig().getSysId(); + String serverId = UserManager.getGlobalConfigInfo().getConfig().getServId(); + String selfUserId = String.valueOf(UserManager.getUserInfo().getUser_id()); + String userId = sessionId; + if (sysID.equals(userId) || serverId.equals(userId) || userId.equals("11") || userId.equals(selfUserId) + || mMainPageBean.getGender() == 2 || mMainPageBean.getIf_forbidden() == 2 || ("oppo".equals(DeviceManager.getInstance().getApplicationMarket())) || mMainPageBean.getStatus() == 2) { + wxContainer.setVisibility(View.GONE); + } else { + wxContainer.setVisibility(View.VISIBLE); + } + copyBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ClipboardManager cm = (ClipboardManager) + getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(null, mMainPageBean.getContent())); + MaleToast.showMessage(getActivity(), "复制成功"); + } + }); + if (mMainPageBean.getStatus() != 1) { + lookBtn.setText("暂未填写"); + } else { + copyBtn.setText(String.format("%s 复制", mMainPageBean.getContent())); + } + lookBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ConfirmWXAccountDialog dialog = new ConfirmWXAccountDialog(getActivity(), mMainPageBean); + dialog.show(); + try { + int price = Integer.parseInt(mMainPageBean.getWechat_price()); + if (mMainPageBean.getGiftCoin() > price) { + lookBtn.setVisibility(View.GONE); + copyBtn.setVisibility(View.VISIBLE); + } + } catch (Exception e) { + } + } + }); + lookBtn.setClickable(mMainPageBean.getStatus() == 1); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + rootView = inflater.inflate(R.layout.nim_message_fragment, container, false); +// getTipData(); + EventBus.getDefault().register(this); + rl_message_root = rootView.findViewById(R.id.rl_message_root); + rl_guard = rootView.findViewById(R.id.rl_guard); + rl_guard_view = rootView.findViewById(R.id.rl_guard_view); + mIv_guard = rootView.findViewById(R.id.message_activity_shouhu); + ic_guard_close = rootView.findViewById(R.id.ic_guard_close); + wxContainer = rootView.findViewById(R.id.wxContainer); + lookBtn = rootView.findViewById(R.id.lookBtn); + copyBtn = rootView.findViewById(R.id.copyBtn); + maskImageView = rootView.findViewById(R.id.iv_background); + iv_msg_bg = rootView.findViewById(R.id.iv_msg_bg); + iv_back = rootView.findViewById(R.id.iv_back); + tv_user_name = rootView.findViewById(R.id.tv_user_name); + iv_interactive = rootView.findViewById(R.id.iv_interactive); + iv_user_info = rootView.findViewById(R.id.iv_user_info); + + lin_msg_dynamic = rootView.findViewById(R.id.lin_msg_dynamic); + tv_msg_like = rootView.findViewById(R.id.tv_msg_like); + tv_msg_comment = rootView.findViewById(R.id.tv_msg_comment); + tv_msg_follow = rootView.findViewById(R.id.tv_msg_follow); + + cl_info_card = rootView.findViewById(R.id.cl_info_card); + tv_user_info = rootView.findViewById(R.id.tv_user_info); + tv_user_act = rootView.findViewById(R.id.tv_user_act); + tv_user_auth = rootView.findViewById(R.id.tv_user_auth); + iv_album1 = rootView.findViewById(R.id.iv_album1); + iv_album2 = rootView.findViewById(R.id.iv_album2); + iv_album3 = rootView.findViewById(R.id.iv_album3); + iv_album4 = rootView.findViewById(R.id.iv_album4); + rv_call_list = rootView.findViewById(R.id.rv_call_list); + + LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false); + rv_call_list.setLayoutManager(layoutManager); + mAdapter = new MsgCallListAdapter(getActivity()); + mAdapter.setOnClickedListener(this); + rv_call_list.setAdapter(mAdapter); + SPUtils.saveString(getActivity(), ConsUser.USER_AVATAR_FRAME, ""); + rl_guard.post(new Runnable() { + @Override + public void run() { + x1 = rl_guard.getMeasuredWidth(); + y1 = rl_guard.getMeasuredHeight(); + } + }); + + mIv_guard.setOnTouchListener(new FloatingListener()); + mIv_guard.setOnClickListener(this); + ic_guard_close.setOnClickListener(this); + mSvgaDialog = new SvgaDialog(getContext()); + iv_back.setOnClickListener(this); + tv_user_name.setOnClickListener(this); + iv_interactive.setOnClickListener(this); + iv_user_info.setOnClickListener(this); + cl_info_card.setOnClickListener(this); + tv_msg_like.setOnClickListener(this); + tv_msg_comment.setOnClickListener(this); + tv_msg_follow.setOnClickListener(this); + return rootView; + } + + //开始触控的坐标,移动时的坐标(相对于屏幕左上角的坐标) + private int mTouchStartX, mTouchStartY, mTouchCurrentX, mTouchCurrentY; + //开始时的坐标和结束时的坐标(相对于自身控件的坐标) + private int mStartX, mStartY, mStopX, mStopY; + //判断悬浮窗口是否移动,这里做个标记,防止移动后松手触发了点击事件 + private boolean isMove; + private int x1, x2, y1, y2, maxX, maxY; + + private class FloatingListener implements View.OnTouchListener { + + @Override + public boolean onTouch(View v, MotionEvent event) { + int action = event.getAction(); + maxX = x1 - x2; + maxY = y1 - y2; + switch (action) { + case MotionEvent.ACTION_DOWN: + isMove = false; + mTouchStartX = (int) event.getRawX(); + mTouchStartY = (int) event.getRawY(); + mStartX = (int) event.getX(); + mStartY = (int) event.getY(); + break; + case MotionEvent.ACTION_MOVE: + mTouchCurrentX = (int) event.getRawX(); + mTouchCurrentY = (int) event.getRawY(); + int x = mTouchCurrentX - mTouchStartX; + int y = mTouchCurrentY - mTouchStartY; + float x1; + if (rl_guard_view.getX() + x < 0) { + x1 = 0; + } else if (rl_guard_view.getX() + x > maxX) { + x1 = maxX; + } else { + x1 = rl_guard_view.getX() + x; + } + float y1; + if (rl_guard_view.getY() + y < 0) { + y1 = 0; + } else if (rl_guard_view.getY() + x > maxY) { + y1 = maxY; + } else { + y1 = rl_guard_view.getY() + y; + } + rl_guard_view.setX(x1); + rl_guard_view.setY(y1); + mTouchStartX = mTouchCurrentX; + mTouchStartY = mTouchCurrentY; + break; + case MotionEvent.ACTION_UP: + mStopX = (int) event.getX(); + mStopY = (int) event.getY(); + if (Math.abs(mStartX - mStopX) >= 1 || Math.abs(mStartY - mStopY) >= 1) { + isMove = true; + } + break; + default: + break; + } + //如果是移动事件不触发OnClick事件,防止移动的时候一放手形成点击事件 + return isMove; + } + } + + private void getTipData() { + if (!TextUtils.isEmpty(sessionId)) { + if (!"2".equals(sessionId) && !"4".equals(sessionId) && !"11".equals(sessionId) && !"3".equals(sessionId) && !"5".equals(sessionId) + && !"6".equals(sessionId) && !"7".equals(sessionId) && !"8".equals(sessionId) && !"9".equals(sessionId) && !"10".equals(sessionId)) { + NewsManager.getChatTip((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChatTipBean result, String message) { + if (null != result) { + if (!TextUtils.isEmpty(result.getTip())) { + warmAnimator(result.getTip()); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + } + } + + /** + * 是否显示资料卡 + * + * @param show + */ + + private ObjectAnimator fadeOut; + + private void showUserInfoCard(boolean show, int i) { + if (show) { + if (fadeOut != null) { + fadeOut.cancel(); + } + iv_interactive.setImageResource(R.drawable.icon_arrow_down); + isInteractiveShow = true; + ObjectAnimator.ofFloat(cl_info_card, "translationY", 0F, -537F).setDuration(0).start(); + cl_info_card.setVisibility(View.VISIBLE); + ObjectAnimator fadeIn = ObjectAnimator.ofFloat(cl_info_card, "translationY", -537F, 0); + fadeIn.setDuration(1000).start(); + ObjectAnimator alphaIn = ObjectAnimator.ofFloat(cl_info_card, View.ALPHA, 1f); + alphaIn.setDuration(1000); // 设置动画持续时间为1000毫秒 + alphaIn.start(); // 启动动画 + } else { + iv_interactive.setImageResource(R.drawable.icon_arrow_up); + isInteractiveShow = false; + ObjectAnimator.ofFloat(cl_info_card, "translationY", 0F, -537F).setDuration(1000).start(); + fadeOut = ObjectAnimator.ofFloat(cl_info_card, View.ALPHA, 0f); + fadeOut.setDuration(500); // 设置动画持续时间为1000毫秒 + fadeOut.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + cl_info_card.setVisibility(View.GONE); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + fadeOut.start(); // 启动动画 + } + } + + /** + * 公告提示 + */ + private void warmAnimator(String tip) { + final TextView mRlTextWarm = rootView.findViewById(R.id.tv_text_warm); + mRlTextWarm.setText(tip); + ObjectAnimator.ofFloat(mRlTextWarm, "translationY", 0F, -120F).setDuration(0).start(); + mRlTextWarm.setVisibility(View.VISIBLE); + ObjectAnimator fadeIn = ObjectAnimator.ofFloat(mRlTextWarm, "translationY", -120F, 0); + fadeIn.setDuration(2000).start(); + ObjectAnimator alphaIn = ObjectAnimator.ofFloat(mRlTextWarm, View.ALPHA, 1f); + alphaIn.setDuration(2000); // 设置动画持续时间为500毫秒 + alphaIn.start(); // 启动动画 + + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + ObjectAnimator.ofFloat(mRlTextWarm, "translationY", 0F, -120F).setDuration(2000).start(); + ObjectAnimator fadeOut = ObjectAnimator.ofFloat(mRlTextWarm, View.ALPHA, 0f); + fadeOut.setDuration(2000); // 设置动画持续时间为500毫秒 + fadeOut.start(); // 启动动画 + } + }, 4000); + } + + /** + * ***************************** life cycle ******************************* + */ + + @Override + public void onPause() { + super.onPause(); + isResume = false; + NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE, SessionTypeEnum.None); + inputPanel.onPause(); + messageListPanel.onPause(); + } + + public void onEventMainThread(EventBusGiftMessage event) { + if (!TextUtils.isEmpty(sessionId)) { +// getWeChatInfo(sessionId); + } + } + + @Override + public void onResume() { + super.onResume(); + isResume = true; + messageListPanel.onResume(); + NIMClient.getService(MsgService.class).setChattingAccount(sessionId, sessionType); + getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC); // 默认使用扬声器播放 + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (mIv_guard != null) { + if (guardAnimation != null) { + guardAnimation.release(); + } + mIv_guard.setBackground(null); + + } + } + + @Override + public void onDestroy() { + SPUtils.saveInt(getContext(), ConsUser.DYNAMICS_TYPE, 0); + EventBus.getDefault().unregister(this); + super.onDestroy(); + messageListPanel.onDestroy(); + registerObservers(false); + if (inputPanel != null) { + inputPanel.onDestroy(); + } + if (aitManager != null) { + aitManager.reset(); + } + } + + public boolean onBackPressed() { + return inputPanel.collapse(true) || messageListPanel.onBackPressed(); + } + + public void refreshMessageList() { + messageListPanel.refreshMessageList(); + } + + private void parseIntent() { + Bundle arguments = getArguments(); + sessionId = arguments.getString(Extras.EXTRA_ACCOUNT); + sessionType = (SessionTypeEnum) arguments.getSerializable(Extras.EXTRA_TYPE); + IMMessage anchor = (IMMessage) arguments.getSerializable(Extras.EXTRA_ANCHOR); + + customization = (SessionCustomization) arguments.getSerializable(Extras.EXTRA_CUSTOMIZATION); + Container container = new Container(getActivity(), sessionId, sessionType, this); + + if (messageListPanel == null) { + messageListPanel = new MessageListPanelEx(container, rootView, anchor, false, false); + messageListPanel.setRecoverListener(this); + } else { + messageListPanel.reload(container, anchor); + } + +// if (SysSPUtils.getString(getActivity(), "sys_id").equals(sessionId)) { //系统通知,不显示下面的输入框 +// isShowEditBar = true; +// } +// +// if (SysSPUtils.getString(getActivity(), "serv_id").equals(sessionId)) { //如果是客服,不显示礼物和视频按钮 +// isShowGiftAndVideo = true; +// } + if (!TextUtils.isEmpty(sessionId)) { + requestBuddyInfo(); +// getWeChatInfo(sessionId); + if ("2".equals(sessionId) || "11".equals(sessionId)) { //系统通知,不显示下面的输入框 + isShowEditBar = true; + maskImageView.setVisibility(View.GONE); + iv_msg_bg.setVisibility(View.GONE); + tv_user_name.setEnabled(false); + tv_user_name.setTextColor(ContextCompat.getColor(getContext(), R.color.one_text)); + iv_interactive.setVisibility(View.GONE); + iv_user_info.setVisibility(View.INVISIBLE); + iv_back.setImageResource(R.drawable.sand_icon_back); + if ("11".equals(sessionId)) { + rl_message_root.setBackgroundResource(R.color.white); + if (SPUtils.getInt(getContext(), ConsUser.DYNAMICS_TYPE) == 0) { + lin_msg_dynamic.setVisibility(View.VISIBLE); + } else { + if (SPUtils.getInt(getContext(), ConsUser.DYNAMICS_TYPE) == 24) { + tv_user_name.setText("新增点赞"); + } else if (SPUtils.getInt(getContext(), ConsUser.DYNAMICS_TYPE) == 26) { + tv_user_name.setText("新增评论"); + } else if (SPUtils.getInt(getContext(), ConsUser.DYNAMICS_TYPE) == 16) { + tv_user_name.setText("新增关注"); + } + lin_msg_dynamic.setVisibility(View.GONE); + } + } + } else if ("4".equals(sessionId)) { //如果是客服,不显示礼物和视频按钮 + isShowGiftAndVideo = true; + getMainPageData(Integer.parseInt(sessionId)); +// maskImageView.setVisibility(View.GONE); +// iv_msg_bg.setVisibility(View.GONE); + } else { + getMainPageData(Integer.parseInt(sessionId)); + } + } +// getTipData(); //展示提示信息 + + if (inputPanel == null) { + inputPanel = new InputPanel(container, rootView, getActionList(), isShowEditBar, isShowGiftAndVideo, getActivity()); + inputPanel.setCustomization(customization); + inputPanel.setRecoverStateListener(this); + + //点击按钮 + inputPanel.setOnClickImage(new InputPanel.OnClickImage() { + @Override + public void onClickImage() { //图片 + PictureSelector.create(getActivity()).openGallery(SelectMimeType.ofAll()) + .setSelectorUIStyle(new PictureSelectorStyle()) + .isDisplayTimeAxis(true) + .setVideoPlayerEngine(null) + .isUseSystemVideoPlayer(false) + .setImageEngine(GlideEngine.createGlideEngine()) + .isWithSelectVideoImage(true) + .isPageStrategy(true) + .isMaxSelectEnabledMask(true) + .setSelectionMode(SelectModeConfig.SINGLE) + .isDisplayCamera(true) + .isPreviewImage(true) + .isPreviewVideo(true) + .isPreviewFullScreenMode(true) + .isPreviewZoomEffect(true) + .setPermissionDescriptionListener(new MeOnPermissionDescriptionListener()) + .forResult(new MeOnResultCallbackListener(getActivity(), sessionId, sessionType, new MeOnResultCallbackListener.SendMsgCallBack() { + @Override + public void sendMsgCallBack(IMMessage message) { + sendMessage(message); + } + })); + +// if (null != mImageAction) { +// mImageAction.onClick(); +// } + } + + @Override + public void onClickCamera() { //摄像 + if (mGuardDialog == null) getGuardInfo(1); + else mGuardDialog.show(); +// if (null != mVideoAction) { +// mVideoAction.onClick(); +// } + } + + @Override + public void onClickGift() { //礼物 + getGiftData(); + } + + @Override + public void onClickVideo() { //视频 + if (!isFastClick()) { + SelectTypeDialog selectTypeDialog = new SelectTypeDialog(getContext()); + selectTypeDialog.setSelectListener(MessageFragment.this); + selectTypeDialog.show(); + } else { + MaleToast.showMessage(getActivity(), "请稍后拨打"); + } + } + + @Override + public void onEmptyText() { + MaleToast.showMessage(getActivity(), "消息不能为空"); + } + + @Override + public void onCloseUserInfoCard() { + if (isInteractiveShow) { + showUserInfoCard(false, 1); + } + } + }); + } else { + inputPanel.reload(container, customization); + } + + initAitManager(); + + inputPanel.switchRobotMode(NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(sessionId) != null); + + registerObservers(true); + + if (customization != null) { + messageListPanel.setChattingBackground(customization.backgroundUri, customization.backgroundColor); + } + if ("2".equals(sessionId) || "4".equals(sessionId) || "11".equals(sessionId) || "3".equals(sessionId) || "5".equals(sessionId) + || "6".equals(sessionId) || "7".equals(sessionId) || "8".equals(sessionId) || "9".equals(sessionId) || "10".equals(sessionId)) { + rl_guard_view.setVisibility(View.GONE); + } else { + getGuardInfo(0); +// Animation animation = new ScaleAnimation(0.9f, 1.0f, 0.9f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); +// animation.setDuration(300);//动画时间 +// animation.setRepeatCount(-1);//动画的反复次数 +// animation.setRepeatMode(Animation.REVERSE); +// animation.setFillAfter(true);//设置为true,动画转化结束后被应用 +// mIv_guard.startAnimation(animation);//開始动画 + } + title = tv_user_name.getText().toString(); + } + + private void changeLight(ImageView imageView, int brightness) { + ColorMatrix cMatrix = new ColorMatrix(); + cMatrix.set(new float[]{1, 0, 0, 0, brightness, 0, 1, 0, 0, + brightness,// 改变亮度 + 0, 0, 1, 0, brightness, 0, 0, 0, 1, 0}); + imageView.setColorFilter(new ColorMatrixColorFilter(cMatrix)); + } + + //视频通话 + @Override + public void selectVideo() { + if (!TextUtils.isEmpty(sessionId)) { + getMainPageData(Integer.parseInt(sessionId), 0); + } + } + + //语音通话 + @Override + public void selectVoice() { + if (!TextUtils.isEmpty(sessionId)) { + getMainPageData(Integer.parseInt(sessionId), 1); + } + } + + private final int MIN_DELAY_TIME = 5000; // 两次点击间隔不能少于1000ms + private long lastClickTime; + + public boolean isFastClick() { + boolean flag = true; + long currentClickTime = System.currentTimeMillis(); + if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) { + flag = false; + } + lastClickTime = currentClickTime; + return flag; + } + + private void initAitManager() { + UIKitOptions options = NimUIKitImpl.getOptions(); + if (options.aitEnable) { + aitManager = new AitManager(getContext(), options.aitTeamMember && sessionType == SessionTypeEnum.Team ? sessionId : null, options.aitIMRobot); + inputPanel.addAitTextWatcher(aitManager); + aitManager.setTextChangeListener(inputPanel); + } + } + + /** + * ************************* 消息收发 ********************************** + */ + // 是否允许发送消息 + protected boolean isAllowSendMessage(final IMMessage message) { +// boolean isAllowSendMessage = false; +// if (null != message) { +// String sessionId = message.getSessionId(); +// if (!TextUtils.isEmpty(sessionId)) { +// if (sessionId.equals("4")) { +// isAllowSendMessage = true; +// }else { +// isAllowSendMessage = customization.isAllowSendMessage(message); +// } +// } +// } +// return isAllowSendMessage; + if (null == customization) { + return true; + } else { + return customization.isAllowSendMessage(message); + } + } + + private BottomGiftDialog mGiftDialog; + + // private BaseMessageDialog mConfirmDialog; + private void getWeChatInfo(final String userId) { + SettingManager.getWeChat((BaseActivity) getActivity(), userId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ContactBean.WechatBean result, String tips) { + refreshWeChatStatus(result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + /** + * @param userId + */ + private void getMainPageData(final int userId) { + MainManager.getMainPageData((BaseActivity) getActivity(), userId, "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + if (null != result) { + if (null != result.getInfo()) { + avatar = result.getInfo().getAvatar(); + String avatar = StrU.getResourcePath(result.getInfo().getAvatar(), getActivity()); + GlideUtils.showImage(getActivity(), iv_msg_bg, result.getInfo().getAvatar()); + Glide.with(getActivity()).load(avatar) + .apply(maskImageView.setGaussBlur()) + .into(maskImageView); + maskImageView.setAlpha(0.94f); + changeLight(iv_msg_bg, -255); + + if (StrU.isEmpty(result.getInfo().getCity()) && result.getInfo().getAge() == 0) { + tv_user_info.setText("基本资料:未知"); + } else { + String info = result.getInfo().getAge() == 0 ? "基本资料:未知 | " : "基本资料:" + result.getInfo().getAge() + "岁 | "; + info = StrU.isEmpty(result.getInfo().getCity()) ? info + "未知" : info + result.getInfo().getCity(); + tv_user_info.setText(info); + } + tv_user_act.setText(StrU.isEmpty(result.getInfo().getUpdate_time()) ? "最近活跃:未知" : "最近活跃:" + result.getInfo().getUpdate_time()); + if (StrU.equals("1", result.getInfo().getCamera_status())) { + tv_user_auth.setVisibility(View.VISIBLE); + } else { + tv_user_auth.setVisibility(View.GONE); + } + if (result.getInfo().getUser_frame() != null) { + SPUtils.saveString(getActivity(), ConsUser.USER_AVATAR_FRAME, GsonUtils.toJson(result.getInfo().getUser_frame())); + if (!StrU.isEmpty(result.getInfo().getUser_frame().getBubble_frame().getTo_img())) { + String[] strings = result.getInfo().getUser_frame().getBubble_frame().getTo_img().split("/"); + String path = strings[strings.length - 1]; + File pngFile = new File(ConstUrl.DEFAULT_PATH, path); + if (!pngFile.exists()) { + MainManager.downloadNewApp((BaseActivity) getActivity(), ConstUrl.IMAGE_URL + result.getInfo().getUser_frame().getBubble_frame().getTo_img(), + ConstUrl.DEFAULT_PATH + "/" + path, + new HttpCallback() { + @Override + public void onFailure(int httpStatusCode, String message, Throwable throwable) { + if (ConstUrl.LOGDEBUG) + Log.i("TAG", "onFailure: ---------->" + message); + } + + @Override + public void onSuccess(int httpStatusCode, String responseObject) { + if (ConstUrl.LOGDEBUG) + Log.i("TAG", "onSuccess: ------->" + responseObject); + messageListPanel.refreshMessageList(); + } + + @Override + public void onProgress(long bytesCount, long contentLength, boolean done) { + } + }); + } else { + messageListPanel.refreshMessageList(); + } + } else { + messageListPanel.refreshMessageList(); + } + } else { + SPUtils.saveString(getActivity(), ConsUser.USER_AVATAR_FRAME, ""); + } + } + if (result.getAlbum() != null && result.getAlbum().size() > 0) { + switch (result.getAlbum().size()) { + case 1: + iv_album1.setImageURI(StrU.getResourcePath(result.getAlbum().get(0), getContext())); + break; + case 2: + iv_album1.setImageURI(StrU.getResourcePath(result.getAlbum().get(0), getContext())); + iv_album2.setImageURI(StrU.getResourcePath(result.getAlbum().get(1), getContext())); + break; + case 3: + iv_album1.setImageURI(StrU.getResourcePath(result.getAlbum().get(0), getContext())); + iv_album2.setImageURI(StrU.getResourcePath(result.getAlbum().get(1), getContext())); + iv_album3.setImageURI(StrU.getResourcePath(result.getAlbum().get(2), getContext())); + break; + default: + case 4: + iv_album1.setImageURI(StrU.getResourcePath(result.getAlbum().get(0), getContext())); + iv_album2.setImageURI(StrU.getResourcePath(result.getAlbum().get(1), getContext())); + iv_album3.setImageURI(StrU.getResourcePath(result.getAlbum().get(2), getContext())); + iv_album4.setImageURI(StrU.getResourcePath(result.getAlbum().get(3), getContext())); + break; + } + } + if (!"4".equals(sessionId)) { + getChatWordList(); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + cl_info_card.setVisibility(View.GONE); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + /** + * @param userId + * @param callType 通话类型 0.视频 1.语音 + */ + private void getMainPageData(final int userId, int callType) { + MainManager.getMainPageData((BaseActivity) getActivity(), userId, "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + if (null != result) { + if (null != result.getAnchor()) { + int video_status = result.getAnchor().getVideo_status(); //视频状态 0 休息中 1 视频中 + int open_video_status; + if (callType == 0) { + open_video_status = result.getAnchor().getOpen_video_status(); //是否开启视频接听 0 否 1 是 + } else { + open_video_status = result.getAnchor().getOpen_voice_status(); //是否开启语音接听 0 否 1 是 + } + if (open_video_status == 0) { + MaleToast.showMessage(getActivity(), "对方开启了勿扰模式"); + } else { + if (video_status == 0) { +// if (null != result.getSkill()) { +// if (0 != result.getSkill().size()) { + getCallInfo(userId, 1, callType); +// } +// } + } else { + MaleToast.showMessage(getActivity(), "对方正在通话中"); + } + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private void getCallInfo(int uid, int skillId, int callType) { + MainManager.getCallInfo((BaseActivity) getActivity(), uid, skillId, callType, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(getActivity(), AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", true); + intent.putExtra("callType", callType); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + startActivity(intent); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + /** + * 礼物列表数据 + */ + private void getGiftData() { + MainManager.getGiftBeans((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + mGiftDialog = new BottomGiftDialog(getActivity(), + R.style.SelectiveDialog); + + mGiftDialog.setGiftListBean(result); + mGiftDialog.setOnGiftItemClickedListener(new BottomGiftDialog.OnGiftItemClickedListener() { + @Override + public void onGiftClicked(final DialogGiftBean bean) { + if (!TextUtils.isEmpty(sessionId)) { + sendGift(Integer.parseInt(sessionId), bean.getId(), bean.getEffect()); + } + } + + @Override + public void onWalletClicked() { + Intent intent = new Intent(getActivity(), CaibeiRechargeActivity.class); + startActivity(intent); + } + }); + mGiftDialog.show(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + /** + * 赠送礼物 + * + * @param toUid + * @param giftId + */ + private void sendGift(int toUid, int giftId, String giftUrl) { + MainManager.sendGift((BaseActivity) getActivity(), 1, toUid, giftId, 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + if (null != mGiftDialog) { + mGiftDialog.setCoin(result.getCoin() + ""); + mGiftDialog.dismiss(); + } + MaleToast.showMessage(getActivity(), "赠送成功"); +// mSvgaDialog.show(giftUrl); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "赠送失败"); + } + }); + } + + /** + * im扣费 + * + * @param type + * @param id + * @param content + * @param message + */ + private void imCost(final int type, String id, final String content, final IMMessage message, String is_greet) { + if (isInteractiveShow) { + showUserInfoCard(false, 2); + } + NewsManager.sendIMCost((BaseActivity) getActivity(), type, + id, content, is_greet, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, IMCostBean result, String tips) { + + final AlertDialog builder = new AlertDialog.Builder(getActivity()).create(); + + builder.setCancelable(false); + + if (SPUtils.getInt(getActivity(), ConsUser.GENDER) == 2) { //男生 + builder.setMessage("一条私信扣" + result.getCut_coin() + "金币,成为会员享免费特权!"); + + builder.setButton(DialogInterface.BUTTON_NEUTRAL, "不再提醒", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + builder.dismiss(); + StorageManager.getInstance(getActivity()) + .putInt("isDynamicNoticeCanceled", 1); + } + }); + + builder.setButton(DialogInterface.BUTTON_POSITIVE, "成为VIP", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + builder.dismiss(); + Intent intent = new Intent(getActivity(), MemberActivity.class); + getActivity().startActivity(intent); + } + }); + + builder.setButton(DialogInterface.BUTTON_NEGATIVE, "知道了", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + builder.dismiss(); + } + }); + + if (result.getChat_card() != null) { + if (TextUtils.equals("1", result.getChat_card().getIs_pop_up())) { + ChatCardRedPacketDialog dialog = new ChatCardRedPacketDialog(getContext(), result.getChat_card()); + dialog.show(); + } + } + + } else if (SPUtils.getInt(getActivity(), ConsUser.GENDER) == 1) { //女生 + builder.setMessage("本条消息扣除" + result.getCut_coin() + + "金币,还剩" + result.getCoin() + "金币,通过真人认证私信免费哦!"); + + builder.setButton(DialogInterface.BUTTON_NEUTRAL, "不再提醒", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + builder.dismiss(); + StorageManager.getInstance(getActivity()) + .putInt("isDynamicNoticeCanceled", 1); + } + }); + + builder.setButton(DialogInterface.BUTTON_POSITIVE, "真人认证", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + builder.dismiss(); + Intent intentApplyBigCast = new Intent(getActivity(), CertificationActivity.class); + getActivity().startActivity(intentApplyBigCast); + } + }); + builder.setButton(DialogInterface.BUTTON_NEGATIVE, "知道了", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + builder.dismiss(); + } + }); + } + + if (result.getIs_cut() == 1 + && 1 != StorageManager.getInstance(getActivity()).getInt("isDynamicNoticeCanceled") && !SPUtils.getBoolean(getActivity(), ConsUser.USER_VIP, false)) { + builder.show(); + + Button buttonNue = builder.getButton(DialogInterface.BUTTON_NEUTRAL); + buttonNue.setTextColor(getActivity().getResources().getColor(R.color.black)); + + Button buttonPos = builder.getButton(DialogInterface.BUTTON_POSITIVE); + buttonPos.setTextColor(getActivity().getResources().getColor(R.color.black)); + + Button buttonNeg = builder.getButton(DialogInterface.BUTTON_NEGATIVE); + buttonNeg.setTextColor(getActivity().getResources().getColor(R.color.black)); + } + + Map data = new HashMap<>(); + data.put("is_cut", result.getIs_cut()); + data.put("cut_coin", result.getCut_coin()); + data.put("coin", result.getCoin()); + data.put("is_chat_card", result.getUse_chat_card()); + data.put("income_coin", result.getIncome_coin()); +// data.put("is_greet", result.getIs_greet()); + data.put("is_greet", is_greet); + if (isRecover && type == 1) { + isRecover = false; + RecoverBean bean = new RecoverBean(); + bean.setMessageType(item.getMsgType().getValue()); + bean.setNickName(item.getFromNick()); + switch (item.getMsgType()) { + case image: + case video: + FileAttachment msgFileAttachment = (FileAttachment) item.getAttachment(); + if (!TextUtils.isEmpty(msgFileAttachment.getUrl())) { + bean.setValue(msgFileAttachment.getUrl()); + } + break; + case text: + bean.setValue(item.getContent()); + break; + case audio: + final AudioAttachment msgAttachment = (AudioAttachment) item.getAttachment(); + long duration = msgAttachment.getDuration(); + long seconds = TimeUtil.getSecondsByMilliseconds(duration); + if (seconds >= 0) { + bean.setValue(seconds + ""); + } + break; + } + data.put("quote", new Gson().toJson(bean)); + } + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "onSuccess: data----------->" + new Gson().toJson(data)); + message.setRemoteExtension(data); + boolean isRisk = result.getTo_risk_status() == 1 || result.getFrom_risk_status() == 1; + if (result.getFilter() == 0) { + sendImMessage(message, isRisk); + } else { + if (type == 1) { + message.setContent(result.getContent()); + sendImMessage(message, isRisk); + } +// send(message); + } +// getChatWordList(); + if (rv_call_list.getVisibility() == View.VISIBLE) { + rv_call_list.setVisibility(View.GONE); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + /** + * 只渲染,实际不发送 + * + * @param message + */ + private void send(IMMessage message) { + message.setStatus(MsgStatusEnum.success); + NIMClient.getService(MsgService.class).saveMessageToLocal(message, true); + } + + private void registerObservers(boolean register) { + MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class); + service.observeReceiveMessage(incomingMessageObserver, register); + // 已读回执监听 + if (NimUIKitImpl.getOptions().shouldHandleReceipt) { + service.observeMessageReceipt(messageReceiptObserver, register); + } + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(commandObserver, register); + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, register); + NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + } + + /** + * 消息接收观察者 + */ + Observer> incomingMessageObserver = new Observer>() { + @Override + public void onEvent(List messages) { + onMessageIncoming(messages); + } + }; + + private void onMessageIncoming(List messages) { + if (CommonUtil.isEmpty(messages)) { + return; + } + if (messages.get(0).getAttachment() instanceof GiftAttachment && isResume && messages.get(0).getSessionId().equals(sessionId)) { + mSvgaDialog.show(((GiftAttachment) messages.get(0).getAttachment()).getGift_effect()); + } + messageListPanel.onIncomingMessage(messages); + // 发送已读回执 + messageListPanel.sendReceipt(); + } + + /** + * 已读回执观察者 + */ + private Observer> messageReceiptObserver = new Observer>() { + @Override + public void onEvent(List messageReceipts) { + messageListPanel.receiveReceipt(); + } + }; + private BaseMessageDialog baseMessageDialog; + + private boolean isRealName() { + if (NoClearSPUtils.getInt(getContext(), ConsUser.CHAT_REAL_NAME_SWITCH, 0) > 0 && UserManager.getUserInfo().getReal_name_status() == 0) { + if (baseMessageDialog == null) { + baseMessageDialog = new BaseMessageDialog.Builder(getContext()).setMessage("通过实名认证才能使用该功能").setPositive("去实名").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + baseMessageDialog.dismiss(); + } + }).setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(getContext(), RealNameActivity.class); + startActivity(intent); + baseMessageDialog.dismiss(); + } + }).build(); + } + baseMessageDialog.show(); + return true; + } + return false; + } + + /** + * ********************** implements ModuleProxy ********************* + */ + @Override + public boolean sendMessage(IMMessage message) { + if (isRealName()) { + return true; + } +// if (null != message) { +// String sessionId = message.getSessionId(); +// if (!TextUtils.isEmpty(sessionId)) { +// if (sessionId.equals("4")) { +// sendImMessage(message); +// }else { +// if (message.getMsgType().getValue() == 0) { +// imCost(1, message.getSessionId(), message.getContent(), message); +// }else if (message.getMsgType().getValue() == 1) { +// imCost(2, message.getSessionId(), message.getContent(), message); +// }else if (message.getMsgType().getValue() == 3) { +// imCost(3, message.getSessionId(), message.getContent(), message); +// } +// } +// +// } +//// NIMClient.getService(MsgService.class).sendMessage(message, false); +// } +// sendImMessage(message); + if (null != message) { + if (message.getMsgType().getValue() == 0) { //文本 + imCost(1, message.getSessionId(), message.getContent(), message, "0"); + } else if (message.getMsgType().getValue() == 1) { //图片 + ImageAttachment attachment = (ImageAttachment) message.getAttachment(); + String path = attachment.getPath(); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = 2; + final Bitmap bitmap = BitmapFactory.decodeFile(path); + if (bitmap != null) { + String img = BitmapUtils.Bitmap2StrByBase64(bitmap); + SettingManager.imageCheck((BaseActivity) getActivity(), img, sessionId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ImageCheckBean result, String tips) { + if (result.getIs_upload() == 1) { + imCost(3, message.getSessionId(), message.getContent(), message, "0"); + } else { + MaleToast.showMessage(activity, "图片违规"); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + ToastUtil.showToast(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + ToastUtil.showToast(activity, "发送失败" + e.getMessage()); + + } + }); + } +// imCost(2, message.getSessionId(), message.getContent(), message); + + } else if (message.getMsgType().getValue() == 3) { //视频 +// imCost(3, message.getSessionId(), message.getContent(), message); + imCost(4, message.getSessionId(), message.getContent(), message, "0"); + } else if (message.getMsgType().getValue() == 2) { //语音 + imCost(2, message.getSessionId(), message.getContent(), message, "0"); + } + } + return true; + } + + private void sendImMessage(IMMessage message, boolean isRisk) { + if (isRisk && !StrU.equals("4", sessionId)) { + message.setStatus(MsgStatusEnum.success); + CustomMessageConfig config = new CustomMessageConfig(); + config.enableUnreadCount = false; + message.setConfig(config); + NIMClient.getService(MsgService.class).saveMessageToLocalEx(message, false, message.getTime()); + } else { + CustomMessageConfig config = new CustomMessageConfig(); + config.enablePush = true; + message.setConfig(config); + if (isAllowSendMessage(message)) { + appendTeamMemberPush(message); + message = changeToRobotMsg(message); + final IMMessage msg = message; + appendPushConfig(message); + // send message to server and save to db + NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + + } + + @Override + public void onFailed(int code) { + sendFailWithBlackList(code, msg); + } + + @Override + public void onException(Throwable exception) { + + } + }); + + } else { + // 替换成tip + message = MessageBuilder.createTipMessage(message.getSessionId(), message.getSessionType()); + message.setContent("该消息无法发送"); + message.setStatus(MsgStatusEnum.success); + NIMClient.getService(MsgService.class).saveMessageToLocal(message, false); + } + } + inputPanel.recoverSuccess(); + messageListPanel.onMsgSend(message); + if (aitManager != null) { + aitManager.reset(); + } + } + + // 被对方拉入黑名单后,发消息失败的交互处理 + private void sendFailWithBlackList(int code, IMMessage msg) { + if (code == ResponseCode.RES_IN_BLACK_LIST) { + // 如果被对方拉入黑名单,发送的消息前不显示重发红点 + msg.setStatus(MsgStatusEnum.success); + NIMClient.getService(MsgService.class).updateIMMessageStatus(msg); + messageListPanel.refreshMessageList(); + // 同时,本地插入被对方拒收的tip消息 + IMMessage tip = MessageBuilder.createTipMessage(msg.getSessionId(), msg.getSessionType()); + tip.setContent(getActivity().getString(R.string.black_list_send_tip)); + tip.setStatus(MsgStatusEnum.success); + CustomMessageConfig config = new CustomMessageConfig(); + config.enableUnreadCount = true; + config.enablePushNick = false; + config.enableUnreadCount = true; + tip.setConfig(config); + NIMClient.getService(MsgService.class).saveMessageToLocal(tip, true); + } + } + + private void appendTeamMemberPush(IMMessage message) { + if (aitManager == null) { + return; + } + if (sessionType == SessionTypeEnum.Team) { + List pushList = aitManager.getAitTeamMember(); + if (pushList == null || pushList.isEmpty()) { + return; + } + MemberPushOption memberPushOption = new MemberPushOption(); + memberPushOption.setForcePush(true); + memberPushOption.setForcePushContent(message.getContent()); + memberPushOption.setForcePushList(pushList); + message.setMemberPushOption(memberPushOption); + } + } + + private IMMessage changeToRobotMsg(IMMessage message) { + if (aitManager == null) { + return message; + } + if (message.getMsgType() == MsgTypeEnum.robot) { + return message; + } + if (isChatWithRobot()) { + if (message.getMsgType() == MsgTypeEnum.text && message.getContent() != null) { + String content = message.getContent().equals("") ? " " : message.getContent(); + message = MessageBuilder.createRobotMessage(message.getSessionId(), message.getSessionType(), message.getSessionId(), content, RobotMsgType.TEXT, content, null, null); + } + } else { + String robotAccount = aitManager.getAitRobot(); + if (TextUtils.isEmpty(robotAccount)) { + return message; + } + String text = message.getContent(); + String content = aitManager.removeRobotAitString(text, robotAccount); + content = content.equals("") ? " " : content; + message = MessageBuilder.createRobotMessage(message.getSessionId(), message.getSessionType(), robotAccount, text, RobotMsgType.TEXT, content, null, null); + } + return message; + } + + private boolean isChatWithRobot() { + return NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(sessionId) != null; + } + + private void appendPushConfig(IMMessage message) { + CustomPushContentProvider customConfig = NimUIKitImpl.getCustomPushContentProvider(); + if (customConfig == null) { + return; + } + String content = customConfig.getPushContent(message); + Map payload = customConfig.getPushPayload(message); + if (!TextUtils.isEmpty(content)) { + message.setPushContent(content); + } + if (payload != null) { + message.setPushPayload(payload); + } + } + + @Override + public void onInputPanelExpand() { + messageListPanel.scrollToBottom(); + } + + @Override + public void shouldCollapseInputPanel() { + inputPanel.collapse(false); + } + + @Override + public boolean isLongClickEnabled() { + return !inputPanel.isRecording(); + } + + @Override + public void onItemFooterClick(IMMessage message) { + if (aitManager == null) { + return; + } + if (messageListPanel.isSessionMode()) { + RobotAttachment attachment = (RobotAttachment) message.getAttachment(); + NimRobotInfo robot = NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(attachment.getFromRobotAccount()); + aitManager.insertAitRobot(robot.getAccount(), robot.getName(), inputPanel.getEditSelectionStart()); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (aitManager != null) { + aitManager.onActivityResult(requestCode, resultCode, data); + } + inputPanel.onActivityResult(requestCode, resultCode, data); + messageListPanel.onActivityResult(requestCode, resultCode, data); + } + + // 操作面板集合 + protected List getActionList() { + List actions = new ArrayList<>(); + + mImageAction = new ImageAction(); + mVideoAction = new VideoAction(); + + actions.add(mImageAction); + actions.add(mVideoAction); + //删除位置菜单栏 +// actions.add(new LocationAction()); + + if (customization != null && customization.actions != null) { + actions.addAll(customization.actions); + } + return actions; + } + +// //tag 监听到刷新消息 +// public void onEventMainThread(UpdateChatEvent event) { +// Log.d("nail","onEventMainThread"); +// +// refreshMessageList(); +// } + + /** + * 守护 + * + * @param user_id + * @param count + * @param price + */ + private void guard(final String user_id, int count, String price) { + MainManager.postGuard((BaseActivity) getActivity(), user_id, count, price, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + Toast.makeText(activity, "守护成功", Toast.LENGTH_SHORT).show(); + if (null != mGuardDialog) { + mGuardDialog.dismiss(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + mGuardDialog.dismiss(); + BaseApplication.getInstance().getRechargeInfo(activity, 0); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private void getGuardInfo(final int i) { + NewsManager.getGuardInfo((BaseActivity) getActivity(), sessionId, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + mGuardDialog = new GuardDialog(getActivity()); + mGuardDialog.setData(result.getGuard().getGuard_price(), result.getGuard().getFirst_diff_num() + "", avatar, result.getGuard().getAvatar()); + mGuardDialog.setOnClickGuard(new GuardDialog.OnClickGuard() { + @Override + public void onClickGuard(int count, String price) { + guard(sessionId, count, price); + } + }); + if (i == 1) { + mGuardDialog.show(); + } + rl_guard_view.setVisibility(View.GONE); + rl_guard_view.post(new Runnable() { + @Override + public void run() { + x2 = rl_guard_view.getMeasuredWidth(); + y2 = rl_guard_view.getMeasuredHeight(); + } + }); + guardAnimation = AnimUtils.startGuardAnimation(getActivity(), mIv_guard); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "守护信息获取失败: " + tip); + rl_guard_view.setVisibility(View.GONE); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "守护信息失败: " + e.getMessage()); + rl_guard_view.setVisibility(View.GONE); + } + }); + } + + private boolean isInteractiveShow = true; + + /** + * 获取文字招呼列表 + */ + private void getChatWordList() { + NewsManager.getChatWordList((BaseActivity) getActivity(), sessionId, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + if (result != null) { + if (StrU.equals("1", result.getIs_interactive())) { + iv_interactive.setImageResource(R.drawable.icon_arrow_up); + isInteractiveShow = false; + } else { + showUserInfoCard(true, 3); + messageListPanel.scrollToBottom(); + } +// if (messageListPanel.isShowCallList()) { +// rv_call_list.setVisibility(View.VISIBLE); +// return; +// } + if (StrU.equals("0", result.getIs_sent())) { + rv_call_list.setVisibility(View.VISIBLE); + if (result.getList() != null && result.getList().size() > 0) { + List list = result.getList(); + if (StrU.equals("1", result.getShow_add())) { + list.add(""); + } + mAdapter.setList(list); + } + } else { + rv_call_list.setVisibility(View.GONE); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "文字招呼列表获取失败: " + tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "文字招呼列表获取失败: " + e.getMessage()); + } + }); + } + + @Override + public void recoverMsg(IMMessage item) { + inputPanel.setRecover(item); + this.item = item; + } + + private boolean isRecover; + private IMMessage item; + + @Override + public void getRecoverState(boolean isRecover) { + this.isRecover = isRecover; + } + + + /** + * 命令消息接收观察者 + */ + private Observer commandObserver = new Observer() { + @Override + public void onEvent(CustomNotification message) { + if (!sessionId.equals(message.getSessionId()) || message.getSessionType() != SessionTypeEnum.P2P) { + return; + } + showCommandMessage(message); + } + }; + + /** + * 用户信息变更观察者 + */ + private UserInfoObserver userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + if (!TextUtils.isEmpty(sessionId)) { + if (!accounts.contains(sessionId)) { + return; + } + requestBuddyInfo(); + } + } + }; + + /** + * 好友资料变更(eg:关系) + */ + private ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + tv_user_name.setText(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + + @Override + public void onDeletedFriends(List accounts) { + tv_user_name.setText(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + + @Override + public void onAddUserToBlackList(List account) { + tv_user_name.setText(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + + @Override + public void onRemoveUserFromBlackList(List account) { + tv_user_name.setText(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + } + }; + + //对方输入监听 + protected void showCommandMessage(CustomNotification message) { + if (!isResume) { + return; + } + String content = message.getContent(); + try { + JSONObject json = JSON.parseObject(content); + int id = json.getIntValue("id"); + if (id == 1) { + // 正在输入 + String s = title + "(对方正在输入...)"; + tv_user_name.setText(s); + getHandler().postDelayed(() -> { + tv_user_name.setText(title); + }, 2000); + + } + } catch (Exception ignored) { + } + } + + //获取用户昵称 + private void requestBuddyInfo() { + if (!TextUtils.isEmpty(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P))) { + tv_user_name.setText(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P)); + return; + } + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(sessionId); + if (info != null && !TextUtils.isEmpty(info.getName())) { + tv_user_name.setText(info.getName()); + return; + } + List accounts = new ArrayList<>(); + accounts.add(sessionId); + NIMClient.getService(UserService.class).fetchUserInfo(accounts) + .setCallback(new RequestCallback>() { + @Override + public void onSuccess(List userInfos) { + try { + NimUserInfo user = userInfos.get(0); + tv_user_name.setText(user.getName()); + } catch (Exception e) { + } + } + + @Override + public void onFailed(int i) { + Log.e(",", ""); + } + + @Override + public void onException(Throwable throwable) { + Log.e(",", ""); + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.message_activity_shouhu: + if (!isMove) { + if (mGuardDialog == null) getGuardInfo(1); + else mGuardDialog.show(); + } + break; + case R.id.ic_guard_close: + rl_guard_view.setVisibility(View.GONE); + break; + case R.id.iv_back: + if (StrU.isFastClick()) { + if (getActivity() != null) { + getActivity().finish(); + } + } + break; + case R.id.tv_user_name: + case R.id.iv_interactive: + if (StrU.isFastClick()) { + if (isInteractiveShow) { + showUserInfoCard(false, 4); + } else { + showUserInfoCard(true, 5); + } + } + break; + case R.id.iv_user_info: + if (StrU.isFastClick()) { + if (!TextUtils.isEmpty(sessionId)) { + if (isInteractiveShow) { + showUserInfoCard(false, 6); + } + //跳转到个人中心 + Intent intent = new Intent(getActivity(), ChatSettingActivity.class); + intent.putExtra("userId", Integer.valueOf(sessionId)); + getActivity().startActivity(intent); + } else { + MaleToast.showFailureMsg(getActivity(), "请重试"); + } + } + break; + case R.id.cl_info_card: + if (!TextUtils.isEmpty(sessionId)) { + if (isInteractiveShow) { + showUserInfoCard(false, 7); + } + int uid = Integer.parseInt(sessionId); + Intent intent = new Intent(getContext(), MainPageActivity.class); + intent.putExtra("userId", uid); + startActivity(intent); + } + break; + case R.id.tv_msg_like: + SPUtils.saveInt(getContext(), ConsUser.DYNAMICS_TYPE, 24); + NimUIKit.startChat("11", getActivity()); + break; + case R.id.tv_msg_comment: + SPUtils.saveInt(getContext(), ConsUser.DYNAMICS_TYPE, 26); + NimUIKit.startChat("11", getActivity()); + break; + case R.id.tv_msg_follow: + SPUtils.saveInt(getContext(), ConsUser.DYNAMICS_TYPE, 16); + NimUIKit.startChat("11", getActivity()); + break; + } + } + + @Override + public void onSendCall(String content) { + IMMessage message = MessageBuilder.createTextMessage(sessionId, sessionType, content); + imCost(1, message.getSessionId(), message.getContent(), message, "1"); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/fragment/TeamMessageFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/fragment/TeamMessageFragment.java new file mode 100644 index 0000000..aeabe66 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/fragment/TeamMessageFragment.java @@ -0,0 +1,33 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.fragment; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.team.model.Team; + +/** + * Created by zhoujianghua on 2015/9/10. + */ +public class TeamMessageFragment extends MessageFragment { + + private Team team; + + @Override + public boolean isAllowSendMessage(IMMessage message) { + if (team == null) { + team = NimUIKit.getTeamProvider().getTeamById(sessionId); + } + + if (team == null || !team.isMyTeam()) { + ToastHelper.showToast(getActivity(), R.string.team_send_message_not_allow); + return false; + } + + return super.isAllowSendMessage(message); + } + + public void setTeam(Team team) { + this.team = team; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MessageHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MessageHelper.java new file mode 100644 index 0000000..96bec63 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MessageHelper.java @@ -0,0 +1,39 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.helper; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.MessageRevokeTip; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.model.CustomMessageConfig; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * Created by hzxuwen on 2016/8/19. + */ +public class MessageHelper { + + public static MessageHelper getInstance() { + return InstanceHolder.instance; + } + + static class InstanceHolder { + final static MessageHelper instance = new MessageHelper(); + } + + // 消息撤回 + public void onRevokeMessage(IMMessage item, String revokeAccount) { + if (item == null) { + return; + } + + IMMessage message = MessageBuilder.createTipMessage(item.getSessionId(), item.getSessionType()); + message.setContent(MessageRevokeTip.getRevokeTipContent(item, revokeAccount)); + message.setStatus(MsgStatusEnum.success); + CustomMessageConfig config = new CustomMessageConfig(); + config.enableUnreadCount = false; + message.setConfig(config); + NIMClient.getService(MsgService.class).saveMessageToLocalEx(message, true, item.getTime()); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MessageListPanelHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MessageListPanelHelper.java new file mode 100644 index 0000000..a00b289 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MessageListPanelHelper.java @@ -0,0 +1,52 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.helper; + +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.ArrayList; +import java.util.List; + +/** + * 聊天消息列表辅助类 + * 主要用于某些需求场景下需要往聊天消息列表中手动添加消息、删除消息、或者清空消息列表。 + * Created by huangjun on 2015/7/8. + */ +public class MessageListPanelHelper { + + private static MessageListPanelHelper instance; + + private List observers = new ArrayList<>(); + + public static MessageListPanelHelper getInstance() { + if (instance == null) { + instance = new MessageListPanelHelper(); + } + + return instance; + } + + public interface LocalMessageObserver { + void onAddMessage(IMMessage message); + + void onClearMessages(String account); + } + + public void registerObserver(LocalMessageObserver o, boolean register) { + if (register) { + observers.add(o); + } else { + observers.remove(o); + } + } + + public void notifyAddMessage(IMMessage msg) { + for (LocalMessageObserver o : observers) { + o.onAddMessage(msg); + } + } + + public void notifyClearMessages(String account) { + for (LocalMessageObserver o : observers) { + o.onClearMessages(account); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MsgBkImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MsgBkImageView.java new file mode 100644 index 0000000..e3483ef --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/MsgBkImageView.java @@ -0,0 +1,73 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.helper; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; + +import androidx.appcompat.widget.AppCompatImageView; + +public class MsgBkImageView extends AppCompatImageView { + public MsgBkImageView(Context context) { + super(context); + + init(); + } + + public MsgBkImageView(Context context, AttributeSet attrs) { + super(context, attrs); + + init(); + } + + public MsgBkImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + init(); + } + + private final void init() { + super.setScaleType(ScaleType.CENTER_CROP); + } + + @Override + public final void setScaleType(ScaleType scaleType) { + // REJECT + } + + @Override + protected void onDraw(Canvas canvas) { + Drawable dr = getDrawable(); + + if (dr == null) { + super.onDraw(canvas); + + return; + } + + int dwidth = dr.getBounds().width(); + int dheight = dr.getBounds().height(); + + int vwidth = getWidth() - getPaddingLeft() - getPaddingRight(); + int vheight = getHeight() - getPaddingTop() - getPaddingBottom(); + + float scale; + float dx = 0, dy = 0; + + if (dwidth * vheight > vwidth * dheight) { + scale = (float) vheight / (float) dheight; + dx = (vwidth - dwidth * scale) * 0.5f; + } else { + scale = (float) vwidth / (float) dwidth; + dy = (vheight - dheight * scale) * 0.5f; + } + + canvas.save(); + + canvas.translate(0, -(int) (dy + 0.5f)); + + super.onDraw(canvas); + + canvas.restore(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/SendImageHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/SendImageHelper.java new file mode 100644 index 0000000..1f16bba --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/SendImageHelper.java @@ -0,0 +1,158 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.helper; + +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Handler; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PickerContract; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.MD5; +import com.netease.nim.uikit.R; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class SendImageHelper { + public interface Callback { + void sendImage(File file, boolean isOrig); + } + + public static void sendImageAfterPreviewPhotoActivityResult(Intent data, Callback callback) { + final ArrayList selectedImageFileList = data.getStringArrayListExtra(Extras.EXTRA_SCALED_IMAGE_LIST); + final ArrayList origSelectedImageFileList = data.getStringArrayListExtra(Extras.EXTRA_ORIG_IMAGE_LIST); + + boolean isOrig = data.getBooleanExtra(Extras.EXTRA_IS_ORIGINAL, false); + for (int i = 0; i < selectedImageFileList.size(); i++) { + String imageFilepath = selectedImageFileList.get(i); + File imageFile = new File(imageFilepath); + String origImageFilePath = origSelectedImageFileList.get(i); + + if (isOrig) { + // 把原图按md5存放 + String origMD5 = MD5.getStreamMD5(origImageFilePath); + String extension = FileUtil.getExtensionName(origImageFilePath); + String origMD5Path = StorageUtil.getWritePath(origMD5 + "." + extension, + StorageType.TYPE_IMAGE); + AttachmentStore.copy(origImageFilePath, origMD5Path); + + // 把缩略图移到按原图计算的新md5目录下 + String thumbFilename = FileUtil.getFileNameFromPath(imageFilepath); + String thumbMD5Path = StorageUtil.getReadPath(thumbFilename, + StorageType.TYPE_THUMB_IMAGE); + String origThumbMD5Path = StorageUtil.getWritePath(origMD5 + "." + extension, + StorageType.TYPE_THUMB_IMAGE); + AttachmentStore.move(thumbMD5Path, origThumbMD5Path); + + if (callback != null) { + callback.sendImage(new File(origMD5Path), isOrig); + } + } else { + if (callback != null) { + callback.sendImage(imageFile, isOrig); + } + } + } + } + + public static void sendImageAfterSelfImagePicker(Context context, Intent data, final Callback callback) { + boolean isOrig = data.getBooleanExtra(Extras.EXTRA_IS_ORIGINAL, false); + + List photos = PickerContract.getPhotos(data); + if (photos == null) { + ToastHelper.showToastLong(context, R.string.picker_image_error); + return; + } + + for (PhotoInfo photoInfo : photos) { + new SendImageTask(context, isOrig, photoInfo, new Callback() { + + @Override + public void sendImage(File file, boolean isOrig) { + if (callback != null) { + callback.sendImage(file, isOrig); + } + } + }).execute(); + } + } + + // 从相册选择图片进行发送(Added by NYB) + public static class SendImageTask extends AsyncTask { + + private Context context; + private boolean isOrig; + private PhotoInfo info; + private Callback callback; + + public SendImageTask(Context context, boolean isOrig, PhotoInfo info, Callback callback) { + this.context = context; + this.isOrig = isOrig; + this.info = info; + this.callback = callback; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + @Override + protected File doInBackground(Void... params) { + String photoPath = info.getAbsolutePath(); + if (TextUtils.isEmpty(photoPath)) { + return null; + } + String extension = FileUtil.getExtensionName(photoPath); + // gif 强制设置成原图 + boolean gif = ImageUtil.isGif(extension); + isOrig |= gif; + if (isOrig) { + // 把原图按md5存放 + String origMD5 = MD5.getStreamMD5(photoPath); + String origMD5Path = StorageUtil.getWritePath(origMD5 + "." + extension, StorageType.TYPE_IMAGE); + AttachmentStore.copy(photoPath, origMD5Path); + // 生成缩略图 + if (!gif) { + File imageFile = new File(origMD5Path); + ImageUtil.makeThumbnail(imageFile); + } + return new File(origMD5Path); + } else { + File imageFile = new File(photoPath); + extension = FileUtil.getExtensionName(photoPath); + imageFile = ImageUtil.getScaledImageFileWithMD5(imageFile, extension); + if (imageFile == null) { + new Handler(context.getMainLooper()).post(new Runnable() { + @Override + public void run() { + ToastHelper.showToastLong(context, R.string.picker_image_error); + } + }); + return null; + } else { + ImageUtil.makeThumbnail(imageFile); + } + + return imageFile; + } + } + + @Override + protected void onPostExecute(File result) { + super.onPostExecute(result); + if (result != null && callback != null) { + callback.sendImage(result, isOrig); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/TeamNotificationHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/TeamNotificationHelper.java new file mode 100644 index 0000000..7cab8fc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/TeamNotificationHelper.java @@ -0,0 +1,269 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.helper; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.attachment.NotificationAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.team.constant.TeamAllMuteModeEnum; +import com.netease.nimlib.sdk.team.constant.TeamFieldEnum; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.constant.VerifyTypeEnum; +import com.netease.nimlib.sdk.team.model.MemberChangeAttachment; +import com.netease.nimlib.sdk.team.model.MuteMemberAttachment; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.UpdateTeamAttachment; + +import java.util.List; +import java.util.Map; + +/** + * 系统消息描述文本构造器。主要是将各个系统消息转换为显示的文本内容。
+ * Created by huangjun on 2015/3/11. + */ +public class TeamNotificationHelper { + private static ThreadLocal teamId = new ThreadLocal<>(); + + public static String getMsgShowText(final IMMessage message) { + String content = ""; + String messageTip = message.getMsgType().getSendMessageTip(); + if (messageTip.length() > 0) { + content += "[" + messageTip + "]"; + } else { + if (message.getSessionType() == SessionTypeEnum.Team && message.getAttachment() != null) { + content += getTeamNotificationText(message, message.getSessionId()); + } else { + content += message.getContent(); + } + } + + return content; + } + + public static String getTeamNotificationText(IMMessage message, String tid) { + return getTeamNotificationText(message.getSessionId(), message.getFromAccount(), (NotificationAttachment) message.getAttachment()); + } + + public static String getTeamNotificationText(String tid, String fromAccount, NotificationAttachment attachment) { + teamId.set(tid); + String text = buildNotification(tid, fromAccount, attachment); + teamId.set(null); + return text; + } + + private static String buildNotification(String tid, String fromAccount, NotificationAttachment attachment) { + String text; + switch (attachment.getType()) { + case InviteMember: + text = buildInviteMemberNotification(((MemberChangeAttachment) attachment), fromAccount); + break; + case KickMember: + text = buildKickMemberNotification(((MemberChangeAttachment) attachment)); + break; + case LeaveTeam: + text = buildLeaveTeamNotification(fromAccount); + break; + case DismissTeam: + text = buildDismissTeamNotification(fromAccount); + break; + case UpdateTeam: + text = buildUpdateTeamNotification(tid, fromAccount, (UpdateTeamAttachment) attachment); + break; + case PassTeamApply: + text = buildManagerPassTeamApplyNotification((MemberChangeAttachment) attachment); + break; + case TransferOwner: + text = buildTransferOwnerNotification(fromAccount, (MemberChangeAttachment) attachment); + break; + case AddTeamManager: + text = buildAddTeamManagerNotification((MemberChangeAttachment) attachment); + break; + case RemoveTeamManager: + text = buildRemoveTeamManagerNotification((MemberChangeAttachment) attachment); + break; + case AcceptInvite: + text = buildAcceptInviteNotification(fromAccount, (MemberChangeAttachment) attachment); + break; + case MuteTeamMember: + text = buildMuteTeamNotification((MuteMemberAttachment) attachment); + break; + default: + text = getTeamMemberDisplayName(fromAccount) + ": unknown message"; + break; + } + + return text; + } + + private static String getTeamMemberDisplayName(String account) { + return TeamHelper.getTeamMemberDisplayNameYou(teamId.get(), account); + } + + private static String buildMemberListString(List members, String fromAccount) { + StringBuilder sb = new StringBuilder(); + for (String account : members) { + if (!TextUtils.isEmpty(fromAccount) && fromAccount.equals(account)) { + continue; + } + sb.append(getTeamMemberDisplayName(account)); + sb.append(","); + } + sb.deleteCharAt(sb.length() - 1); + + return sb.toString(); + } + + private static String buildInviteMemberNotification(MemberChangeAttachment a, String fromAccount) { + StringBuilder sb = new StringBuilder(); + String selfName = getTeamMemberDisplayName(fromAccount); + + sb.append(selfName); + sb.append("邀请 "); + sb.append(buildMemberListString(a.getTargets(), fromAccount)); + Team team = NimUIKit.getTeamProvider().getTeamById(teamId.get()); + if (team == null || team.getType() == TeamTypeEnum.Advanced) { + sb.append(" 加入群"); + } else { + sb.append(" 加入讨论组"); + } + + return sb.toString(); + } + + private static String buildKickMemberNotification(MemberChangeAttachment a) { + StringBuilder sb = new StringBuilder(); + sb.append(buildMemberListString(a.getTargets(), null)); + Team team = NimUIKit.getTeamProvider().getTeamById(teamId.get()); + if (team == null || team.getType() == TeamTypeEnum.Advanced) { + sb.append(" 已被移出群"); + } else { + sb.append(" 已被移出讨论组"); + } + + return sb.toString(); + } + + private static String buildLeaveTeamNotification(String fromAccount) { + String tip; + Team team = NimUIKit.getTeamProvider().getTeamById(teamId.get()); + if (team == null || team.getType() == TeamTypeEnum.Advanced) { + tip = " 离开了群"; + } else { + tip = " 离开了讨论组"; + } + return getTeamMemberDisplayName(fromAccount) + tip; + } + + private static String buildDismissTeamNotification(String fromAccount) { + return getTeamMemberDisplayName(fromAccount) + " 解散了群"; + } + + private static String buildUpdateTeamNotification(String tid, String account, UpdateTeamAttachment a) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry field : a.getUpdatedFields().entrySet()) { + if (field.getKey() == TeamFieldEnum.Name) { + sb.append("名称被更新为 " + field.getValue()); + } else if (field.getKey() == TeamFieldEnum.Introduce) { + sb.append("群介绍被更新为 " + field.getValue()); + } else if (field.getKey() == TeamFieldEnum.Announcement) { + sb.append(TeamHelper.getTeamMemberDisplayNameYou(tid, account) + " 修改了群公告"); + } else if (field.getKey() == TeamFieldEnum.VerifyType) { + VerifyTypeEnum type = (VerifyTypeEnum) field.getValue(); + String authen = "群身份验证权限更新为"; + if (type == VerifyTypeEnum.Free) { + sb.append(authen + NimUIKit.getContext().getString(R.string.team_allow_anyone_join)); + } else if (type == VerifyTypeEnum.Apply) { + sb.append(authen + NimUIKit.getContext().getString(R.string.team_need_authentication)); + } else { + sb.append(authen + NimUIKit.getContext().getString(R.string.team_not_allow_anyone_join)); + } + } else if (field.getKey() == TeamFieldEnum.Extension) { + sb.append("群扩展字段被更新为 " + field.getValue()); + } /*else if (field.getKey() == TeamFieldEnum.Ext_Server) { + sb.append("群扩展字段(服务器)被更新为 " + field.getValue()); + }*/ else if (field.getKey() == TeamFieldEnum.ICON) { + sb.append("群头像已更新"); + } else if (field.getKey() == TeamFieldEnum.InviteMode) { + sb.append("群邀请他人权限被更新为 " + field.getValue()); + } else if (field.getKey() == TeamFieldEnum.TeamUpdateMode) { + sb.append("群资料修改权限被更新为 " + field.getValue()); + } else if (field.getKey() == TeamFieldEnum.BeInviteMode) { + sb.append("群被邀请人身份验证权限被更新为 " + field.getValue()); + } else if (field.getKey() == TeamFieldEnum.TeamExtensionUpdateMode) { + sb.append("群扩展字段修改权限被更新为 " + field.getValue()); + } else if (field.getKey() == TeamFieldEnum.AllMute) { + TeamAllMuteModeEnum teamAllMuteModeEnum = (TeamAllMuteModeEnum) field.getValue(); + if (teamAllMuteModeEnum == TeamAllMuteModeEnum.Cancel) { + sb.append("取消群全员禁言"); + } else { + sb.append("群全员禁言"); + } + } else { + sb.append("群" + field.getKey() + "被更新为 " + field.getValue()); + } + sb.append("\r\n"); + } + if (sb.length() < 2) { + return "未知通知"; + } + return sb.delete(sb.length() - 2, sb.length()).toString(); + } + + private static String buildManagerPassTeamApplyNotification(MemberChangeAttachment a) { + StringBuilder sb = new StringBuilder(); + sb.append("管理员通过用户 "); + sb.append(buildMemberListString(a.getTargets(), null)); + sb.append(" 的入群申请"); + + return sb.toString(); + } + + private static String buildTransferOwnerNotification(String from, MemberChangeAttachment a) { + StringBuilder sb = new StringBuilder(); + sb.append(getTeamMemberDisplayName(from)); + sb.append(" 将群转移给 "); + sb.append(buildMemberListString(a.getTargets(), null)); + + return sb.toString(); + } + + private static String buildAddTeamManagerNotification(MemberChangeAttachment a) { + StringBuilder sb = new StringBuilder(); + + sb.append(buildMemberListString(a.getTargets(), null)); + sb.append(" 被任命为管理员"); + + return sb.toString(); + } + + private static String buildRemoveTeamManagerNotification(MemberChangeAttachment a) { + StringBuilder sb = new StringBuilder(); + + sb.append(buildMemberListString(a.getTargets(), null)); + sb.append(" 被撤销管理员身份"); + + return sb.toString(); + } + + private static String buildAcceptInviteNotification(String from, MemberChangeAttachment a) { + StringBuilder sb = new StringBuilder(); + + sb.append(getTeamMemberDisplayName(from)); + sb.append(" 接受了 ").append(buildMemberListString(a.getTargets(), null)).append(" 的入群邀请"); + + return sb.toString(); + } + + private static String buildMuteTeamNotification(MuteMemberAttachment a) { + StringBuilder sb = new StringBuilder(); + + sb.append(buildMemberListString(a.getTargets(), null)); + sb.append("被管理员"); + sb.append(a.isMute() ? "禁言" : "解除禁言"); + + return sb.toString(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/VideoMessageHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/VideoMessageHelper.java new file mode 100644 index 0000000..74efbff --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/helper/VideoMessageHelper.java @@ -0,0 +1,267 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.helper; + +import android.Manifest; +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.DialogInterface; +import android.content.Intent; +import android.provider.MediaStore; +import android.text.TextUtils; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.CaptureVideoActivity; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.util.C; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.MD5; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.utils.PermissionUtil; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.settings.video.VideoSelectActivity; +import com.netease.nim.uikit.R; + +import java.io.File; +import java.util.List; + +/** + * Created by hzxuwen on 2015/4/10. + */ +public class VideoMessageHelper { + private File videoFile; + private String videoFilePath; + + private Activity activity; + private VideoMessageHelperListener listener; + + private int localRequestCode; + private int captureRequestCode; + private PermissionDialog permissionDialog; + + public VideoMessageHelper(Activity activity, VideoMessageHelperListener listener) { + this.activity = activity; + this.listener = listener; + } + + public interface VideoMessageHelperListener { + void onVideoPicked(File file, String md5); + } + + /** + * 显示视频拍摄或从本地相册中选取 + */ + public void showVideoSource(int local, int capture) { + this.localRequestCode = local; + this.captureRequestCode = capture; + CustomAlertDialog dialog = new CustomAlertDialog(activity); + dialog.setTitle(activity.getString(R.string.input_panel_video)); + dialog.addItem("拍摄视频", new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + showPermissionDialog(new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 0); + } + }); + dialog.addItem("从相册中选择视频", new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + showPermissionDialog(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1); + } + }); + dialog.show(); + } + + private void showPermissionDialog(String[] permission, int type) { + //权限允许 + permissionDialog = new PermissionDialog(activity, permission); + permissionDialog.show(); + XXPermissions.with(activity) + .permission(permission) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + if (type == 0) { + chooseVideoFromCamera(); + } else { + chooseVideoFromLocal(); + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog customAlertDialog = new com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog(activity); + customAlertDialog.setTitle("私语需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(activity); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + /************************************************* 视频操作S *******************************************/ + + /** + * 拍摄视频 + */ + protected void chooseVideoFromCamera() { + if (!StorageUtil.hasEnoughSpaceForWrite(activity, + StorageType.TYPE_VIDEO, true)) { + return; + } + videoFilePath = StorageUtil.getWritePath( + activity, StringUtil.get36UUID() + + C.FileSuffix.MP4, StorageType.TYPE_TEMP); + videoFile = new File(videoFilePath); + + // 启动视频录制 + CaptureVideoActivity.start(activity, videoFilePath, captureRequestCode); + } + + /** + * 从本地相册中选择视频 + */ + public void chooseVideoFromLocal() { +// if (Build.VERSION.SDK_INT >= 19) { +// chooseVideoFromLocalKitKat(); +// } else { +// chooseVideoFromLocalBeforeKitKat(); +// } + VideoSelectActivity.launchForResult(activity, VideoSelectActivity.TYPE_VIDEO_NOT_CUT, localRequestCode); + } + + /** + * API19 之后选择视频 + */ + protected void chooseVideoFromLocalKitKat() { + Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI); + intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); + try { + activity.startActivityForResult(intent, localRequestCode); + } catch (ActivityNotFoundException e) { + ToastHelper.showToast(activity, R.string.gallery_invalid); + } catch (SecurityException e) { + + } + } + + /** + * API19 之前选择视频 + */ + protected void chooseVideoFromLocalBeforeKitKat() { + Intent mIntent = new Intent(Intent.ACTION_GET_CONTENT); + mIntent.setType(C.MimeType.MIME_VIDEO_ALL); + mIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); + try { + activity.startActivityForResult(mIntent, localRequestCode); + } catch (ActivityNotFoundException e) { + ToastHelper.showToast(activity, R.string.gallery_invalid); + } + } + + /****************************视频选中后回调操作********************************************/ + + /** + * 获取本地相册视频回调操作 + */ + public void onGetLocalVideoResult(final Intent data) { + if (data == null) { + return; + } + String filePath = data.getStringExtra("VideoPath"); + if (StringUtil.isEmpty(filePath) || !checkVideoFile(filePath)) { + return; + } + + String md5 = MD5.getStreamMD5(filePath); + String filename = md5 + "." + FileUtil.getExtensionName(filePath); + String md5Path = StorageUtil.getWritePath(filename, StorageType.TYPE_VIDEO); + + if (AttachmentStore.copy(filePath, md5Path) != -1) { + if (listener != null) { + listener.onVideoPicked(new File(md5Path), md5); + } + } else { + ToastHelper.showToast(activity, R.string.video_exception); + } + } + + /** + * 拍摄视频后回调操作 + */ + public void onCaptureVideoResult(Intent data) { + + if (videoFile == null || !videoFile.exists()) { + //activity 可能会销毁重建,所以从这取一下 + String dataFilePath = data.getStringExtra(CaptureVideoActivity.EXTRA_DATA_FILE_NAME); + if (!TextUtils.isEmpty(dataFilePath)) { + videoFile = new File(dataFilePath); + } + } + + if (videoFile == null || !videoFile.exists()) { + return; + } + + //N930拍照取消也产生字节为0的文件 + if (videoFile.length() <= 0) { + videoFile.delete(); + return; + } + + String videoPath = videoFile.getPath(); + String md5 = MD5.getStreamMD5(videoPath); + String md5Path = StorageUtil.getWritePath(md5 + ".mp4", StorageType.TYPE_VIDEO); + + if (AttachmentStore.move(videoPath, md5Path)) { + if (listener != null) { + listener.onVideoPicked(new File(md5Path), md5); + } + } + } + + /** + * 检查文件 + * + * @param file 视频文件 + * @return boolean + */ + private boolean checkVideoFile(String file) { + if (!AttachmentStore.isFileExist(file)) { + return false; + } + + if (new File(file).length() > C.MAX_LOCAL_VIDEO_FILE_SIZE) { + ToastHelper.showToast(activity, R.string.im_choose_video_file_size_too_large); + return false; + } + + if (!StorageUtil.isInvalidVideoFile(file)) { + ToastHelper.showToast(activity, R.string.im_choose_video); + return false; + } + return true; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/Container.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/Container.java new file mode 100644 index 0000000..7788285 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/Container.java @@ -0,0 +1,23 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module; + +import android.app.Activity; + +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +/** + * Created by zhoujianghua on 2015/7/6. + */ +public class Container { + + public final Activity activity; + public final String account; + public final SessionTypeEnum sessionType; + public final ModuleProxy proxy; + + public Container(Activity activity, String account, SessionTypeEnum sessionType, ModuleProxy proxy) { + this.activity = activity; + this.account = account; + this.sessionType = sessionType; + this.proxy = proxy; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/ModuleProxy.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/ModuleProxy.java new file mode 100644 index 0000000..61f91e4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/ModuleProxy.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module; + +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * 会话窗口提供给子模块的代理接口。 + */ +public interface ModuleProxy { + // 发送消息 + boolean sendMessage(IMMessage msg); + + // 消息输入区展开时候的处理 + void onInputPanelExpand(); + + // 应当收起输入区 + void shouldCollapseInputPanel(); + + // 是否正在录音 + boolean isLongClickEnabled(); + + void onItemFooterClick(IMMessage message); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/MsgForwardFilter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/MsgForwardFilter.java new file mode 100644 index 0000000..b58a77b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/MsgForwardFilter.java @@ -0,0 +1,16 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module; + +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * 消息转发过滤器 + */ +public interface MsgForwardFilter { + /** + * 是否过滤该消息的转发 (默认不过滤) + * + * @param message 消息 + * @return 返回true为过滤,返回false则不过滤 + */ + boolean shouldIgnore(IMMessage message); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/MsgRevokeFilter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/MsgRevokeFilter.java new file mode 100644 index 0000000..70d35a0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/MsgRevokeFilter.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module; + +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * 消息撤回过滤器 + * Created by hzxuwen on 2016/8/22. + */ +public interface MsgRevokeFilter { + /** + * 是否过滤该消息的撤回 (默认不过滤) + * + * @param message 消息 + * @return 返回true为过滤,返回false则不过滤 + */ + boolean shouldIgnore(IMMessage message); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsGridviewAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsGridviewAdapter.java new file mode 100644 index 0000000..97f91c3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsGridviewAdapter.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module.input; + + +import android.content.Context; +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 com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.R; + +import java.util.List; + +public class ActionsGridviewAdapter extends BaseAdapter { + + private Context context; + + private List baseActions; + + public ActionsGridviewAdapter(Context context, List baseActions) { + this.context = context; + this.baseActions = baseActions; + } + + @Override + public int getCount() { + return baseActions.size(); + } + + @Override + public Object getItem(int position) { + return baseActions.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View itemlayout; + if (convertView == null) { + itemlayout = LayoutInflater.from(context).inflate(R.layout.nim_actions_item_layout, null); + } else { + itemlayout = convertView; + } + + BaseAction viewHolder = baseActions.get(position); + ((ImageView) itemlayout.findViewById(R.id.imageView)).setBackgroundResource(viewHolder.getIconResId()); + ((TextView) itemlayout.findViewById(R.id.textView)).setText(context.getString(viewHolder.getTitleId())); + return itemlayout; + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsPagerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsPagerAdapter.java new file mode 100644 index 0000000..274871f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsPagerAdapter.java @@ -0,0 +1,110 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module.input; + +import android.content.Context; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.GridView; + +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by hzxuwen on 2015/3/10. + */ +public class ActionsPagerAdapter extends PagerAdapter { + + private final int ITEM_COUNT_PER_GRID_VIEW = 8; + + private final Context context; + + private final List actions; + private final ViewPager viewPager; + private final int gridViewCount; + + public ActionsPagerAdapter(ViewPager viewPager, List actions) { + this.context = viewPager.getContext(); + this.actions = new ArrayList<>(actions); + this.viewPager = viewPager; + this.gridViewCount = (actions.size() + ITEM_COUNT_PER_GRID_VIEW - 1) / ITEM_COUNT_PER_GRID_VIEW; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + int end = (position + 1) * ITEM_COUNT_PER_GRID_VIEW > actions.size() ? actions + .size() : (position + 1) * ITEM_COUNT_PER_GRID_VIEW; + List subBaseActions = actions.subList(position + * ITEM_COUNT_PER_GRID_VIEW, end); + + GridView gridView = new GridView(context); + gridView.setAdapter(new ActionsGridviewAdapter(context, subBaseActions)); + if (actions.size() >= 4) { + gridView.setNumColumns(4); + + container.post(new Runnable() { + @Override + public void run() { + ViewGroup.LayoutParams layoutParams = viewPager.getLayoutParams(); + layoutParams.height = context.getResources().getDimensionPixelOffset( + R.dimen.message_bottom_function_viewpager_height); + viewPager.setLayoutParams(layoutParams); + } + }); + } else { + gridView.setNumColumns(actions.size()); + + container.post(new Runnable() { + @Override + public void run() { + ViewGroup.LayoutParams layoutParams = viewPager.getLayoutParams(); + layoutParams.height = context.getResources().getDimensionPixelOffset( + R.dimen.message_bottom_function_viewpager_height) / 2; + viewPager.setLayoutParams(layoutParams); + } + }); + } + gridView.setSelector(R.color.transparent); + gridView.setHorizontalSpacing(0); + gridView.setVerticalSpacing(0); + gridView.setGravity(Gravity.CENTER); + gridView.setTag(Integer.valueOf(position)); + gridView.setOnItemClickListener(new GridView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + int index = ((Integer) parent.getTag()) * ITEM_COUNT_PER_GRID_VIEW + position; + actions.get(index).onClick(); + } + }); + + container.addView(gridView); + return gridView; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + // + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public int getCount() { + return gridViewCount; + } + + @Override + public int getItemPosition(Object object) { + return POSITION_NONE; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsPanel.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsPanel.java new file mode 100644 index 0000000..ed3b9e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/ActionsPanel.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module.input; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.R; + +import java.util.List; + +/** + * 更多操作模块 + * Created by hzxuwen on 2015/6/17. + */ +public class ActionsPanel { + + // 初始化更多布局adapter + public static void init(View view, List actions) { + final ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewPager); + final ViewGroup indicator = (ViewGroup) view.findViewById(R.id.actions_page_indicator); + + ActionsPagerAdapter adapter = new ActionsPagerAdapter(viewPager, actions); + viewPager.setAdapter(adapter); + initPageListener(indicator, adapter.getCount(), viewPager); + } + + // 初始化更多布局PageListener + private static void initPageListener(final ViewGroup indicator, final int count, final ViewPager viewPager) { + viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageSelected(int position) { + setIndicator(indicator, count, position); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + setIndicator(indicator, count, 0); + } + + /** + * 设置页码 + */ + private static void setIndicator(ViewGroup indicator, int total, int current) { + if (total <= 1) { + indicator.removeAllViews(); + } else { + indicator.removeAllViews(); + for (int i = 0; i < total; i++) { + ImageView imgCur = new ImageView(indicator.getContext()); + imgCur.setId(i); + // 判断当前页码来更新 + if (i == current) { + imgCur.setBackgroundResource(R.drawable.nim_moon_page_selected); + } else { + imgCur.setBackgroundResource(R.drawable.nim_moon_page_unselected); + } + + indicator.addView(imgCur); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/InputPanel.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/InputPanel.java new file mode 100644 index 0000000..46d6147 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/input/InputPanel.java @@ -0,0 +1,1419 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module.input; + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.SystemClock; +import android.text.Editable; +import android.text.InputType; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.Chronometer; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.Permission; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.base.base.permission.AbsPermissionResultCallBack; +import com.fengliyan.base.base.permission.PermissionDialog; +import com.fengliyan.base.base.permission.PermissionHelper; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.UIKitOptions; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.business.ait.AitTextChangeListener; +import com.fengliyan.tianlesue.im.uikit.business.session.actions.BaseAction; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.EmoticonPickerView; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.IEmoticonSelectedListener; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.MoonUtil; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialogHelper; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.utils.ListStringSPUtils; +import com.fengliyan.tianlesue.utils.PermissionUtil; +import com.fengliyan.tianlesue.view.base.utils.view.DefaultMessageDialog; +import com.fengliyan.tianlesue.view.base.utils.view.EditDefaultMessageDialog; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.news.im.DefaultMessageAdapter; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.media.record.AudioRecorder; +import com.netease.nimlib.sdk.media.record.IAudioRecordCallback; +import com.netease.nimlib.sdk.media.record.RecordType; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.netease.nimlib.sdk.msg.model.CustomNotificationConfig; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.File; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +/** + * 底部文本编辑,语音等模块 + * Created by hzxuwen on 2015/6/16. + */ +public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallback, AitTextChangeListener { + private static final String TAG = "MsgSendLayout"; + private static final int SHOW_LAYOUT_DELAY = 200; + protected Container container; + protected View view; + protected Handler uiHandler; + protected View actionPanelBottomLayout; // 更多布局 + protected LinearLayout messageActivityBottomLayout; + protected EditText messageEditText;// 文本消息编辑框 + protected Button audioRecordBtn; // 录音按钮 + protected View audioAnimLayout; // 录音动画布局 + protected FrameLayout textAudioSwitchLayout; // 切换文本,语音按钮布局 + protected View switchToTextButtonInInputBar;// 文本消息选择按钮 + protected View switchToAudioButtonInInputBar;// 语音消息选择按钮 + protected View moreFuntionButtonInInputBar;// 更多消息选择按钮 + protected View sendMessageButtonInInputBar;// 发送消息按钮 + protected View emojiButtonInInputBar;// 发送消息按钮 + protected View messageInputBar; + protected RelativeLayout rl_recover; + protected TextView tv_recover_name; + protected TextView tv_recover_content; + protected ImageView iv_recover_close; + + private SessionCustomization customization; + // 表情 + protected EmoticonPickerView emoticonPickerView; // 贴图表情控件 + // 语音 + protected AudioRecorder audioMessageHelper; + private Chronometer time; + private TextView timerTip; + private LinearLayout timerTipContainer; + private boolean started = false; + private boolean cancelled = false; + private boolean touched = false; // 是否按着 + private boolean isKeyboardShowed = true; // 是否显示键盘 + private boolean isShowEditBar; //是否显示输入框 false为显示,true为不显示 + private boolean isShowGiftAndVideo; //是否显示礼物和视频按钮 false为显示,true为不显示 + + // state + private boolean actionPanelBottomLayoutHasSetup = false; + private boolean isTextAudioSwitchShow = true; + + // adapter + private List actions; + + // data + private long typingTime = 0; + + private boolean isRobotSession; + + private TextWatcher aitTextWatcher; + private View mEditImage; + private View mEditCamera; + private View mEditGift; + private View mEditVideo; + private ImageView mEditDefaultMessage; + private ImageView mEditAudio; + private Button mBtInputAudioRecord; + private RelativeLayout mRlInputAudioRecord; + private LinearLayout mLlDefaultMessageLayout; + private RecyclerView mRvDefaultMessage; + private Context mContext; + private LinearLayout mLlMessageAdd; + private ImageView mIvMessageSetting; + private RelativeLayout mRlDefaultMessageFinish; + private RelativeLayout mRlDefaultMessageAdd; + private DefaultMessageAdapter mDefaultMessageAdapter; + private List mDefaultMessageList; + private DefaultMessageDialog mDefaultMessageDialog; + private String mDefaultMessages; + private Gson mGson; + + public InputPanel(Container container, View view, List actions, boolean isTextAudioSwitchShow, boolean isShowEditBar, boolean isShowGiftAndVideo, Context context) { + this.container = container; + this.view = view; + this.actions = actions; + this.uiHandler = new Handler(); + this.isTextAudioSwitchShow = isTextAudioSwitchShow; + this.isShowEditBar = isShowEditBar; + this.isShowGiftAndVideo = isShowGiftAndVideo; + this.mContext = context; + init(); + } + + public InputPanel(Container container, View view, List actions, boolean isShowEditBar, boolean isShowGiftAndVideo, Context context) { + this(container, view, actions, true, isShowEditBar, isShowGiftAndVideo, context); + } + + public void onPause() { + // 停止录音 + if (audioMessageHelper != null) { + onEndAudioRecord(true); + } + } + + public void onDestroy() { + // release + if (audioMessageHelper != null) { + audioMessageHelper.destroyAudioRecorder(); + } + } + + public boolean collapse(boolean immediately) { + boolean respond = (emoticonPickerView != null && emoticonPickerView.getVisibility() == View.VISIBLE + || actionPanelBottomLayout != null && actionPanelBottomLayout.getVisibility() == View.VISIBLE); + + hideAllInputLayout(immediately); + + return respond; + } + + public void addAitTextWatcher(TextWatcher watcher) { + aitTextWatcher = watcher; + } + + private void init() { + initViews(); + initInputBarListener(); + initTextEdit(); + initAudioRecordButton(); + restoreText(false); + + for (int i = 0; i < actions.size(); ++i) { + actions.get(i).setIndex(i); + actions.get(i).setContainer(container); + } + } + + public void setCustomization(SessionCustomization customization) { + this.customization = customization; + if (customization != null) { + emoticonPickerView.setWithSticker(customization.withSticker); + } + } + + public void reload(Container container, SessionCustomization customization) { + this.container = container; + setCustomization(customization); + } + + private void initViews() { + // input bar + messageActivityBottomLayout = view.findViewById(R.id.messageActivityBottomLayout); + messageInputBar = view.findViewById(R.id.textMessageLayout); + switchToTextButtonInInputBar = view.findViewById(R.id.buttonTextMessage); + switchToAudioButtonInInputBar = view.findViewById(R.id.buttonAudioMessage); + moreFuntionButtonInInputBar = view.findViewById(R.id.buttonMoreFuntionInText); + emojiButtonInInputBar = view.findViewById(R.id.emoji_button); + sendMessageButtonInInputBar = view.findViewById(R.id.buttonSendMessage); + messageEditText = view.findViewById(R.id.editTextMessage); + mEditImage = view.findViewById(R.id.edit_image); + mEditCamera = view.findViewById(R.id.edit_camera); + mEditGift = view.findViewById(R.id.edit_gift); + mEditVideo = view.findViewById(R.id.edit_video); + //自定义默认消息按钮 + mEditDefaultMessage = view.findViewById(R.id.edit_default_message); + //录音按钮 + mEditAudio = view.findViewById(R.id.edit_audio); + + + // 语音 + audioRecordBtn = view.findViewById(R.id.audioRecord); + audioAnimLayout = view.findViewById(R.id.layoutPlayAudio); + time = view.findViewById(R.id.timer); + timerTip = view.findViewById(R.id.timer_tip); + timerTipContainer = view.findViewById(R.id.timer_tip_container); + + // 表情 + emoticonPickerView = view.findViewById(R.id.emoticon_picker_view); + + rl_recover = view.findViewById(R.id.rl_recover); + tv_recover_name = view.findViewById(R.id.tv_recover_name); + tv_recover_content = view.findViewById(R.id.tv_recover_content); + iv_recover_close = view.findViewById(R.id.iv_recover_close); + +// // 显示录音按钮 +// switchToTextButtonInInputBar.setVisibility(View.GONE); + switchToAudioButtonInInputBar.setVisibility(View.VISIBLE); +// +// // 文本录音按钮切换布局 + textAudioSwitchLayout = view.findViewById(R.id.switchLayout); +// if (isTextAudioSwitchShow) { +// textAudioSwitchLayout.setVisibility(View.VISIBLE); +// } else { +// textAudioSwitchLayout.setVisibility(View.GONE); +// } + + if (isShowEditBar) { + messageInputBar.setVisibility(View.GONE); + } else { + messageInputBar.setVisibility(View.VISIBLE); + } + + if (isShowGiftAndVideo) { + mEditGift.setVisibility(View.GONE); + mEditVideo.setVisibility(View.GONE); + } else { + mEditGift.setVisibility(View.VISIBLE); + mEditVideo.setVisibility(View.VISIBLE); + } + } + + private void initInputBarListener() { + switchToTextButtonInInputBar.setOnClickListener(clickListener); + switchToAudioButtonInInputBar.setOnClickListener(clickListener); + emojiButtonInInputBar.setOnClickListener(clickListener); + sendMessageButtonInInputBar.setOnClickListener(clickListener); + moreFuntionButtonInInputBar.setOnClickListener(clickListener); + mEditImage.setOnClickListener(clickListener); + mEditCamera.setOnClickListener(clickListener); + mEditGift.setOnClickListener(clickListener); + mEditVideo.setOnClickListener(clickListener); + mEditDefaultMessage.setOnClickListener(clickListener); + mEditAudio.setOnClickListener(clickListener); + iv_recover_close.setOnClickListener(clickListener); + } + + private void initTextEdit() { + messageEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + messageEditText.setOnTouchListener(new View.OnTouchListener() { + + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + switchToTextLayout(true); + } + return false; + } + }); + + messageEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { + + @Override + public void onFocusChange(View v, boolean hasFocus) { +// messageEditText.setHint(""); + checkSendButtonEnable(messageEditText); + } + }); + + messageEditText.addTextChangedListener(new TextWatcher() { + private int start; + private int count; + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + this.start = start; + this.count = count; + if (aitTextWatcher != null) { + aitTextWatcher.onTextChanged(s, start, before, count); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (aitTextWatcher != null) { + aitTextWatcher.beforeTextChanged(s, start, count, after); + } + } + + @Override + public void afterTextChanged(Editable s) { + checkSendButtonEnable(messageEditText); + MoonUtil.replaceEmoticons(container.activity, s, start, count); + + int editEnd = messageEditText.getSelectionEnd(); + messageEditText.removeTextChangedListener(this); + while (StringUtil.counterChars(s.toString()) > NimUIKitImpl.getOptions().maxInputTextLength && editEnd > 0) { + s.delete(editEnd - 1, editEnd); + editEnd--; + } + messageEditText.setSelection(editEnd); + messageEditText.addTextChangedListener(this); + + if (aitTextWatcher != null) { + aitTextWatcher.afterTextChanged(s); + } + + sendTypingCommand(); + } + }); + } + + + /** + * 发送“正在输入”通知 + */ + private void sendTypingCommand() { + if (container.account.equals(NimUIKit.getAccount())) { + return; + } + + if (container.sessionType == SessionTypeEnum.Team || container.sessionType == SessionTypeEnum.ChatRoom) { + return; + } + + if (System.currentTimeMillis() - typingTime > 5000L) { + typingTime = System.currentTimeMillis(); + CustomNotification command = new CustomNotification(); + command.setSessionId(container.account); + command.setSessionType(container.sessionType); + CustomNotificationConfig config = new CustomNotificationConfig(); + config.enablePush = false; + config.enableUnreadCount = false; + command.setConfig(config); + + JSONObject json = new JSONObject(); + json.put("id", "1"); + command.setContent(json.toString()); + + NIMClient.getService(MsgService.class).sendCustomNotification(command); + } + } + + /** + * ************************* 键盘布局切换 ******************************* + */ + + private View.OnClickListener clickListener = new View.OnClickListener() { + + @Override + public void onClick(View v) { + if (v == iv_recover_close) { + isRecover = false; + rl_recover.setVisibility(View.GONE); + if (recoverStateListener != null) { + recoverStateListener.getRecoverState(false); + } + } else if (v == switchToTextButtonInInputBar) { + switchToTextLayout(true);// 显示文本发送的布局 + } else if (v == sendMessageButtonInInputBar) { + onTextMessageSendButtonPressed(); + } else if (v == switchToAudioButtonInInputBar) { + switchToAudioLayout(); + } else if (v == moreFuntionButtonInInputBar) { + toggleActionPanelLayout(); + } else if (v == emojiButtonInInputBar) { + toggleEmojiLayout(); + } else if (v == mEditImage) { //点击图片按钮 + if (null != mOnClickImage) { + mOnClickImage.onClickImage(); + } + } else if (v == mEditCamera) { //点击摄像按钮 + if (null != mOnClickImage) { + mOnClickImage.onClickCamera(); + } + } else if (v == mEditGift) { //点击礼物按钮 + if (null != mOnClickImage) { + mOnClickImage.onClickGift(); + } + } else if (v == mEditVideo) { //点击视频 + if (null != mOnClickImage) { + mOnClickImage.onClickVideo(); + } + } else if (v == mEditDefaultMessage) { //点击默认消息按钮 + toggleDefaultMessageLayout(); + } else if (v == mEditAudio) { //点击我加的录音按钮 + PermissionDialog permissionDialog = new PermissionDialog(container.activity, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS}); + permissionDialog.show(); + //权限允许 + PermissionHelper.request(new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS}, + new AbsPermissionResultCallBack() { + @Override + public void onPermissionGranted() { +// recordAudioLayout(); + toggleRecordAudioLayout(); + permissionDialog.dismiss(); + } + }); + + } + } + }; + + private OnClickImage mOnClickImage; + + public void setOnClickImage(OnClickImage onClickImage) { + mOnClickImage = onClickImage; + } + + public interface OnClickImage { //把图片点击接口回调到messageFragment + void onClickImage(); + + void onClickCamera(); + + void onClickGift(); + + void onClickVideo(); + + void onEmptyText(); + + void onCloseUserInfoCard(); + } + + // 点击edittext,切换键盘和更多布局 + private void switchToTextLayout(boolean needShowInput) { + hideEmojiLayout(); + hideActionPanelLayout(); + hideRecordAudioLayout(); + hideDefaultMessage(); + + audioRecordBtn.setVisibility(View.GONE); + messageEditText.setVisibility(View.VISIBLE); + if (isRecover) { + rl_recover.setVisibility(View.VISIBLE); + } + sendMessageButtonInInputBar.setVisibility(View.VISIBLE); + switchToTextButtonInInputBar.setVisibility(View.GONE); + switchToAudioButtonInInputBar.setVisibility(View.VISIBLE); + + if (needShowInput) { + uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY); + if (null != mOnClickImage) { + mOnClickImage.onCloseUserInfoCard(); + } + } else { + hideInputMethod(); + } + } + + // 发送文本消息 + private void onTextMessageSendButtonPressed() { + String text = messageEditText.getText().toString(); + if (!TextUtils.isEmpty(text)) { + if (!TextUtils.isEmpty(text.trim())) { + IMMessage textMessage = createTextMessage(text); + + if (container.proxy.sendMessage(textMessage)) { + restoreText(true); + } + } else { + if (null != mOnClickImage) { + mOnClickImage.onEmptyText(); + } + } + } else { + if (null != mOnClickImage) { + mOnClickImage.onEmptyText(); + } + } + } + + protected IMMessage createTextMessage(String text) { + return MessageBuilder.createTextMessage(container.account, container.sessionType, text); + } + + // 切换成音频,收起键盘,按钮切换成键盘 + private void switchToAudioLayout() { + messageEditText.setVisibility(View.GONE); + sendMessageButtonInInputBar.setVisibility(View.GONE); + audioRecordBtn.setVisibility(View.VISIBLE); + if (isRecover) { + rl_recover.setVisibility(View.GONE); + } + hideInputMethod(); + hideEmojiLayout(); + hideActionPanelLayout(); + + switchToAudioButtonInInputBar.setVisibility(View.GONE); + switchToTextButtonInInputBar.setVisibility(View.VISIBLE); + } + + // 点击“+”号按钮,切换更多布局和键盘 + private void toggleActionPanelLayout() { + if (actionPanelBottomLayout == null || actionPanelBottomLayout.getVisibility() == View.GONE) { + showActionPanelLayout(); + } else { + hideActionPanelLayout(); + } + } + + //点击下面的语言按钮。展示录音按钮 + private void toggleRecordAudioLayout() { + if (mRlInputAudioRecord == null || mRlInputAudioRecord.getVisibility() == View.GONE) { + showAudioRecordLayout(); + } else { + hideRecordAudioLayout(); + } + } + + // 点击表情,切换到表情布局 + private void toggleEmojiLayout() { + if (emoticonPickerView == null || emoticonPickerView.getVisibility() == View.GONE) { + showEmojiLayout(); + } else { + hideEmojiLayout(); + } + } + + //点击默认消息,切换布局 + private void toggleDefaultMessageLayout() { + if (mLlDefaultMessageLayout == null || mLlDefaultMessageLayout.getVisibility() == View.GONE) { + showDefaultMessage(); + } else { + hideDefaultMessage(); + } + } + + //隐藏录音布局 + private void hideRecordAudioLayout() { + uiHandler.removeCallbacks(showAudioRecordLayoutRunable); + if (mRlInputAudioRecord != null) { + mRlInputAudioRecord.setVisibility(View.GONE); + } + } + + //隐藏默认消息列表 + private void hideDefaultMessage() { + uiHandler.removeCallbacks(showDefaultMessageLayoutRunable); + if (mLlDefaultMessageLayout != null) { + mLlDefaultMessageLayout.setVisibility(View.GONE); + } + } + + // 隐藏表情布局 + private void hideEmojiLayout() { + uiHandler.removeCallbacks(showEmojiRunnable); + if (emoticonPickerView != null) { + emoticonPickerView.setVisibility(View.GONE); + } + } + + // 隐藏更多布局 + private void hideActionPanelLayout() { + uiHandler.removeCallbacks(showMoreFuncRunnable); + if (actionPanelBottomLayout != null) { + actionPanelBottomLayout.setVisibility(View.GONE); + } + } + + // 隐藏键盘布局 + private void hideInputMethod() { + isKeyboardShowed = false; + uiHandler.removeCallbacks(showTextRunnable); + InputMethodManager imm = (InputMethodManager) container.activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(messageEditText.getWindowToken(), 0); + messageEditText.clearFocus(); + } + + // 隐藏语音布局 + private void hideAudioLayout() { + audioRecordBtn.setVisibility(View.GONE); + messageEditText.setVisibility(View.VISIBLE); + if (isRecover) { + rl_recover.setVisibility(View.VISIBLE); + } + sendMessageButtonInInputBar.setVisibility(View.VISIBLE); + switchToTextButtonInInputBar.setVisibility(View.VISIBLE); + switchToAudioButtonInInputBar.setVisibility(View.GONE); + } + + // 显示表情布局 + private void showEmojiLayout() { + hideInputMethod(); + hideActionPanelLayout(); + hideAudioLayout(); + + hideRecordAudioLayout(); + hideDefaultMessage(); + + messageEditText.requestFocus(); + uiHandler.postDelayed(showEmojiRunnable, 200); + emoticonPickerView.setVisibility(View.VISIBLE); + emoticonPickerView.show(this); + container.proxy.onInputPanelExpand(); + } + + // 初始化更多布局 + private void addActionPanelLayout() { + if (actionPanelBottomLayout == null) { + View.inflate(container.activity, R.layout.nim_message_activity_actions_layout, messageActivityBottomLayout); + actionPanelBottomLayout = view.findViewById(R.id.actionsLayout); + actionPanelBottomLayoutHasSetup = false; + } + initActionPanelLayout(); + } + + // 显示键盘布局 + private void showInputMethod(EditText editTextMessage) { + editTextMessage.requestFocus(); + //如果已经显示,则继续操作时不需要把光标定位到最后 + if (!isKeyboardShowed) { + editTextMessage.setSelection(editTextMessage.getText().length()); + isKeyboardShowed = true; + } + + InputMethodManager imm = (InputMethodManager) container.activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editTextMessage, 0); + + container.proxy.onInputPanelExpand(); + } + + // 显示更多布局 + private void showActionPanelLayout() { + addActionPanelLayout(); + hideEmojiLayout(); + hideInputMethod(); + + uiHandler.postDelayed(showMoreFuncRunnable, SHOW_LAYOUT_DELAY); + container.proxy.onInputPanelExpand(); + } + + //显示录音按钮 + private void showAudioRecordLayout() { + recordAudioLayout(); + hideDefaultMessage(); + hideEmojiLayout(); + hideInputMethod(); + hideActionPanelLayout(); + } + + //显示默认消息列表 + private void showDefaultMessage() { + defaultMessageLayout(); + hideRecordAudioLayout(); + hideEmojiLayout(); + hideInputMethod(); + hideActionPanelLayout(); + } + + private void recordAudioLayout() { + if (mRlInputAudioRecord == null) { + View.inflate(container.activity, R.layout.input_record_audio_layout, messageActivityBottomLayout); + mRlInputAudioRecord = view.findViewById(R.id.rl_input_audio_record); + mBtInputAudioRecord = view.findViewById(R.id.bt_input_audio_record); + initAudioRecordButton(); + } else { + uiHandler.postDelayed(showAudioRecordLayoutRunable, SHOW_LAYOUT_DELAY); + container.proxy.onInputPanelExpand(); + } + } + + private boolean isSetting = false; + + private void defaultMessageLayout() { + if (mLlDefaultMessageLayout == null) { + View.inflate(container.activity, R.layout.input_default_message_layout, messageActivityBottomLayout); + mLlDefaultMessageLayout = view.findViewById(R.id.ll_default_message_layout); + mRvDefaultMessage = view.findViewById(R.id.rv_default_message); + mLlMessageAdd = view.findViewById(R.id.ll_message_add); + mIvMessageSetting = view.findViewById(R.id.iv_message_setting); + mRlDefaultMessageFinish = view.findViewById(R.id.rl_default_message_finish); + mRlDefaultMessageAdd = view.findViewById(R.id.rl_default_message_add); + + mLlMessageAdd.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mDefaultMessageList != null) { + int size = mDefaultMessageList.size(); + if (size < 10) { + mDefaultMessageDialog = new DefaultMessageDialog(mContext); + mDefaultMessageDialog.setOnClickDefaultMessageDialog(new DefaultMessageDialog.OnClickDefaultMessageDialog() { + @Override + public void onClickFinishDialog() { + if (null != mDefaultMessageDialog) { + mDefaultMessageDialog.dismiss(); + } + } + + @Override + public void onClickSave(String text) { //保存 + if (!TextUtils.isEmpty(text)) { + if (mDefaultMessageList != null) { + mDefaultMessageList.add(text); + String data = mGson.toJson(mDefaultMessageList); + ListStringSPUtils.saveString(mContext, Constant.LIST_DEFAULT_MESSAGE, data); + mDefaultMessageAdapter.notifyDataSetChanged(); + } + } + if (null != mDefaultMessageDialog) { + mDefaultMessageDialog.dismiss(); + } + + } + + @Override + public void onClickSaveSend(String text) { + + if (!TextUtils.isEmpty(text)) { + if (mDefaultMessageList != null) { + //保存默认消息 + mDefaultMessageList.add(text); + String data = mGson.toJson(mDefaultMessageList); + ListStringSPUtils.saveString(mContext, Constant.LIST_DEFAULT_MESSAGE, data); + mDefaultMessageAdapter.notifyDataSetChanged(); + //发送默认消息 + IMMessage textMessage = createTextMessage(text); + if (container.proxy.sendMessage(textMessage)) { + restoreText(true); + } + } + } + + if (null != mDefaultMessageDialog) { + mDefaultMessageDialog.dismiss(); + } + } + }); + + mDefaultMessageDialog.show(); + } else { + MaleToast.showMessage(mContext, "最多添加10条"); + } + } + + + } + }); + //点击设置 + mIvMessageSetting.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mRlDefaultMessageAdd.setVisibility(View.GONE); + mRlDefaultMessageFinish.setVisibility(View.VISIBLE); + isSetting = true; + if (null != mDefaultMessageAdapter) { + mDefaultMessageAdapter.setType(1); + mDefaultMessageAdapter.notifyDataSetChanged(); + } + + } + }); + + mRlDefaultMessageFinish.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mRlDefaultMessageAdd.setVisibility(View.VISIBLE); + mRlDefaultMessageFinish.setVisibility(View.GONE); + isSetting = false; + if (null != mDefaultMessageAdapter) { + mDefaultMessageAdapter.setType(0); + mDefaultMessageAdapter.notifyDataSetChanged(); + } + } + }); + mDefaultMessageList = new ArrayList<>(); + mGson = new Gson(); + mDefaultMessages = ListStringSPUtils.getString(mContext, Constant.LIST_DEFAULT_MESSAGE); + if (TextUtils.isEmpty(mDefaultMessages) || mDefaultMessages.equals("[]")) { + mDefaultMessageList.add(Constant.DEFAULT_MESSAGE); + String data = mGson.toJson(mDefaultMessageList); + ListStringSPUtils.saveString(mContext, Constant.LIST_DEFAULT_MESSAGE, data); + } else { + Type listType = new TypeToken>() { + }.getType(); + mDefaultMessageList = mGson.fromJson(mDefaultMessages, listType); + } + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext); + mRvDefaultMessage.setLayoutManager(linearLayoutManager); + mDefaultMessageAdapter = new DefaultMessageAdapter(mContext); + mDefaultMessageAdapter.setData(mDefaultMessageList); + mDefaultMessageAdapter.setType(0); + mRvDefaultMessage.setAdapter(mDefaultMessageAdapter); + + mDefaultMessageAdapter.setOnClickItem(new DefaultMessageAdapter.onClickItem() { + + private EditDefaultMessageDialog mEditDefaultMessageDialog; + + @Override + public void onClickTextDetele(int position) { + mDefaultMessageList.remove(position); + String data = mGson.toJson(mDefaultMessageList); + ListStringSPUtils.saveString(mContext, Constant.LIST_DEFAULT_MESSAGE, data); + mDefaultMessageAdapter.notifyDataSetChanged(); + } + + @Override + public void onClickTextEdit(int position) { + mEditDefaultMessageDialog = new EditDefaultMessageDialog(mContext, mDefaultMessageList, position); + mEditDefaultMessageDialog.setOnClickDefaultMessageDialog(new EditDefaultMessageDialog.OnClickDefaultMessageDialog() { + @Override + public void onClickFinishDialog() { + if (mEditDefaultMessageDialog != null) { + mEditDefaultMessageDialog.dismiss(); + } + + } + + @Override + public void onClickSave(List defaultMessages, String text) { + String data = mGson.toJson(defaultMessages); + ListStringSPUtils.saveString(mContext, Constant.LIST_DEFAULT_MESSAGE, data); + mDefaultMessageAdapter.notifyDataSetChanged(); + + if (mEditDefaultMessageDialog != null) { + mEditDefaultMessageDialog.dismiss(); + } + } + + @Override + public void onClickSaveSend(List defaultMessages, String text) { + String data = mGson.toJson(defaultMessages); + ListStringSPUtils.saveString(mContext, Constant.LIST_DEFAULT_MESSAGE, data); + mDefaultMessageAdapter.notifyDataSetChanged(); + //发送默认消息 + IMMessage textMessage = createTextMessage(text); + if (container.proxy.sendMessage(textMessage)) { + restoreText(true); + } + + if (mEditDefaultMessageDialog != null) { + mEditDefaultMessageDialog.dismiss(); + } + } + }); + + mEditDefaultMessageDialog.show(); + } + + @Override + public void onClickItem(String text) { + if (!isSetting) { + //发送默认消息 + IMMessage textMessage = createTextMessage(text); + if (container.proxy.sendMessage(textMessage)) { + restoreText(true); + } + } + } + + }); + + } else { + uiHandler.postDelayed(showDefaultMessageLayoutRunable, SHOW_LAYOUT_DELAY); + container.proxy.onInputPanelExpand(); + } + } + + // 初始化具体more layout中的项目 + private void initActionPanelLayout() { + if (actionPanelBottomLayoutHasSetup) { + return; + } + + ActionsPanel.init(view, actions); + actionPanelBottomLayoutHasSetup = true; + } + + private Runnable showEmojiRunnable = new Runnable() { + @Override + public void run() { + emoticonPickerView.setVisibility(View.VISIBLE); + } + }; + + private Runnable showMoreFuncRunnable = new Runnable() { + @Override + public void run() { + actionPanelBottomLayout.setVisibility(View.VISIBLE); + } + }; + + private Runnable showAudioRecordLayoutRunable = new Runnable() { + @Override + public void run() { + if (mRlInputAudioRecord != null) { + mRlInputAudioRecord.setVisibility(View.VISIBLE); + } + } + }; + + private Runnable showDefaultMessageLayoutRunable = new Runnable() { + @Override + public void run() { + if (mLlDefaultMessageLayout != null) { + mLlDefaultMessageLayout.setVisibility(View.VISIBLE); + } + } + }; + + private Runnable showTextRunnable = new Runnable() { + @Override + public void run() { + showInputMethod(messageEditText); + } + }; + + private void restoreText(boolean clearText) { + if (clearText) { + messageEditText.setText(""); + } + + checkSendButtonEnable(messageEditText); + } + + /** + * 显示发送或更多 + * + * @param editText + */ + private void checkSendButtonEnable(EditText editText) { + if (isRobotSession) { + return; + } + String textMessage = editText.getText().toString(); + if (!TextUtils.isEmpty(StringUtil.removeBlanks(textMessage)) && editText.hasFocus()) { + moreFuntionButtonInInputBar.setVisibility(View.GONE); + sendMessageButtonInInputBar.setVisibility(View.VISIBLE); + } else { +// sendMessageButtonInInputBar.setVisibility(View.GONE); + sendMessageButtonInInputBar.setVisibility(View.VISIBLE); +// moreFuntionButtonInInputBar.setVisibility(View.VISIBLE); + moreFuntionButtonInInputBar.setVisibility(View.GONE); + } + } + + /** + * *************** IEmojiSelectedListener *************** + */ + @Override + public void onEmojiSelected(String key) { + Editable mEditable = messageEditText.getText(); + if (key.equals("/DEL")) { + messageEditText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + } else { + int start = messageEditText.getSelectionStart(); + int end = messageEditText.getSelectionEnd(); + start = (start < 0 ? 0 : start); + end = (start < 0 ? 0 : end); + mEditable.replace(start, end, key); + } + } + + private Runnable hideAllInputLayoutRunnable; + + @Override + public void onStickerSelected(String category, String item) { + Log.i("InputPanel", "onStickerSelected, category =" + category + ", sticker =" + item); + + if (customization != null) { + MsgAttachment attachment = customization.createStickerAttachment(category, item); + IMMessage stickerMessage = MessageBuilder.createCustomMessage(container.account, container.sessionType, "贴图消息", attachment); + container.proxy.sendMessage(stickerMessage); + } + } + + @Override + public void onTextAdd(String content, int start, int length) { + if (messageEditText.getVisibility() != View.VISIBLE || + (emoticonPickerView != null && emoticonPickerView.getVisibility() == View.VISIBLE)) { + switchToTextLayout(true); + } else { + uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY); + } + messageEditText.getEditableText().insert(start, content); + } + + @Override + public void onTextDelete(int start, int length) { + if (messageEditText.getVisibility() != View.VISIBLE) { + switchToTextLayout(true); + } else { + uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY); + } + int end = start + length - 1; + messageEditText.getEditableText().replace(start, end, ""); + } + + public int getEditSelectionStart() { + return messageEditText.getSelectionStart(); + } + + + /** + * 隐藏所有输入布局 + */ + private void hideAllInputLayout(boolean immediately) { + if (hideAllInputLayoutRunnable == null) { + hideAllInputLayoutRunnable = new Runnable() { + + @Override + public void run() { + hideInputMethod(); + hideActionPanelLayout(); + hideEmojiLayout(); + hideRecordAudioLayout(); + hideDefaultMessage(); + } + }; + } + long delay = immediately ? 0 : ViewConfiguration.getDoubleTapTimeout(); + uiHandler.postDelayed(hideAllInputLayoutRunnable, delay); + } + + /** + * ****************************** 语音 *********************************** + */ + private void initAudioRecordButton() { + audioRecordBtn.setOnTouchListener(new View.OnTouchListener() { + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + touched = true; + initAudioRecord(); + onStartAudioRecord(); + } else if (event.getAction() == MotionEvent.ACTION_CANCEL + || event.getAction() == MotionEvent.ACTION_UP) { + touched = false; + onEndAudioRecord(isCancelled(v, event)); + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + touched = true; + cancelAudioRecord(isCancelled(v, event)); + } + + return false; + } + }); + +// audioRecordBtn.setOnTouchListener(new View.OnTouchListener() { +// +// @Override +// public boolean onTouch(View v, MotionEvent event) { +// if (event.getAction() == MotionEvent.ACTION_DOWN) { +// touched = true; +// initAudioRecord(); +// onStartAudioRecord(); +// } else if (event.getAction() == MotionEvent.ACTION_CANCEL +// || event.getAction() == MotionEvent.ACTION_UP) { +// touched = false; +// onEndAudioRecord(isCancelled(v, event)); +// } else if (event.getAction() == MotionEvent.ACTION_MOVE) { +// touched = true; +// cancelAudioRecord(isCancelled(v, event)); +// } +// +// return false; +// } +// }); + +// mBtInputAudioRecord.setOnTouchListener(new View.OnTouchListener() { +// +// @Override +// public boolean onTouch(View v, MotionEvent event) { +// if (event.getAction() == MotionEvent.ACTION_DOWN) { +// touched = true; +// initAudioRecord(); +// onStartAudioRecord(); +// } else if (event.getAction() == MotionEvent.ACTION_CANCEL +// || event.getAction() == MotionEvent.ACTION_UP) { +// touched = false; +// onEndAudioRecord(isCancelled(v, event)); +// } else if (event.getAction() == MotionEvent.ACTION_MOVE) { +// touched = true; +// cancelAudioRecord(isCancelled(v, event)); +// } +// +// return false; +// } +// }); + } + + // 上滑取消录音判断 + private static boolean isCancelled(View view, MotionEvent event) { + int[] location = new int[2]; + view.getLocationOnScreen(location); + + if (event.getRawX() < location[0] || event.getRawX() > location[0] + view.getWidth() + || event.getRawY() < location[1] - 40) { + return true; + } + + return false; + } + + /** + * 初始化AudioRecord + */ + private void initAudioRecord() { + if (audioMessageHelper == null) { + UIKitOptions options = NimUIKitImpl.getOptions(); + audioMessageHelper = new AudioRecorder(container.activity, options.audioRecordType, options.audioRecordMaxTime, this); + } + } + + /** + * 开始语音录制 + */ + private void onStartAudioRecord() { + container.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + PermissionDialog permissionDialog = new PermissionDialog(container.activity, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS}); + permissionDialog.show(); + XXPermissions.with(container.activity) + .permission(Permission.RECORD_AUDIO) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + permissionDialog.dismiss(); + if (all) { + audioMessageHelper.startRecord(); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + permissionDialog.dismiss(); + if (never) { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(container.activity); + customAlertDialog.setTitle("私语需要开启录音权限,以便进行录制语音内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(container.activity); + } + }); + customAlertDialog.show(); + } + } + }); + + + cancelled = false; + } + + /** + * 结束语音录制 + * + * @param cancel + */ + private void onEndAudioRecord(boolean cancel) { + started = false; + container.activity.getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + audioMessageHelper.completeRecord(cancel); + // 下面两行自己加的 +// audioRecordBtn.setText(R.string.record_audio); +// audioRecordBtn.setBackgroundResource(R.drawable.nim_message_input_edittext_box);// +// mBtInputAudioRecord.setText(R.string.record_audio); +// mBtInputAudioRecord.setBackgroundResource(R.drawable.nim_message_input_edittext_box); + + stopAudioRecordAnim(); + } + + /** + * 取消语音录制 + * + * @param cancel + */ + private void cancelAudioRecord(boolean cancel) { + // reject + if (!started) { + return; + } + // no change + if (cancelled == cancel) { + return; + } + + cancelled = cancel; + updateTimerTip(cancel); + } + + /** + * 正在进行语音录制和取消语音录制,界面展示 + * + * @param cancel + */ + private void updateTimerTip(boolean cancel) { + if (cancel) { + timerTip.setText(R.string.recording_cancel_tip); + timerTipContainer.setBackgroundResource(R.drawable.nim_cancel_record_red_bg); + } else { + timerTip.setText(R.string.recording_cancel); + timerTipContainer.setBackgroundResource(0); + } + } + + /** + * 开始语音录制动画 + */ + private void playAudioRecordAnim() { + audioAnimLayout.setVisibility(View.VISIBLE); + time.setBase(SystemClock.elapsedRealtime()); + time.start(); + } + + /** + * 结束语音录制动画 + */ + private void stopAudioRecordAnim() { + audioAnimLayout.setVisibility(View.GONE); + time.stop(); + time.setBase(SystemClock.elapsedRealtime()); + } + + // 录音状态回调 + @Override + public void onRecordReady() { + + } + + @Override + public void onRecordStart(File audioFile, RecordType recordType) { + started = true; + if (!touched) { + return; + } + // 下面两行自己加的 +// audioRecordBtn.setText(R.string.record_audio_end); +// audioRecordBtn.setBackgroundResource(R.drawable.nim_message_input_edittext_box_pressed);// +// mBtInputAudioRecord.setText(R.string.record_audio_end); +// mBtInputAudioRecord.setBackgroundResource(R.drawable.nim_message_input_edittext_box_pressed); + + updateTimerTip(false); // 初始化语音动画状态 + playAudioRecordAnim(); + } + + @Override + public void onRecordSuccess(File audioFile, long audioLength, RecordType recordType) { + IMMessage audioMessage = MessageBuilder.createAudioMessage(container.account, container.sessionType, audioFile, audioLength); + container.proxy.sendMessage(audioMessage); + } + + @Override + public void onRecordFail() { + if (started) { + ToastHelper.showToast(container.activity, R.string.recording_error); + } + } + + @Override + public void onRecordCancel() { + + } + + @Override + public void onRecordReachedMaxTime(final int maxTime) { + stopAudioRecordAnim(); + EasyAlertDialogHelper.createOkCancelDiolag(container.activity, "", container.activity.getString(R.string.recording_max_time), false, new EasyAlertDialogHelper.OnDialogActionListener() { + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + audioMessageHelper.handleEndRecord(true, maxTime); + } + }).show(); + } + + public boolean isRecording() { + return audioMessageHelper != null && audioMessageHelper.isRecording(); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode != Activity.RESULT_OK) { + return; + } + int index = (requestCode << 16) >> 24; + if (index != 0) { + index--; + if (index < 0 | index >= actions.size()) { + LogUtil.d(TAG, "request code out of actions' range"); + return; + } + BaseAction action = actions.get(index); + if (action != null) { + action.onActivityResult(requestCode & 0xff, resultCode, data); + } + } + } + + public void switchRobotMode(boolean isRobot) { + isRobotSession = isRobot; + if (isRobot) { +// textAudioSwitchLayout.setVisibility(View.GONE); + emojiButtonInInputBar.setVisibility(View.GONE); + sendMessageButtonInInputBar.setVisibility(View.VISIBLE); + moreFuntionButtonInInputBar.setVisibility(View.GONE); + } else { +// textAudioSwitchLayout.setVisibility(View.VISIBLE); + emojiButtonInInputBar.setVisibility(View.VISIBLE); +// sendMessageButtonInInputBar.setVisibility(View.GONE); + sendMessageButtonInInputBar.setVisibility(View.VISIBLE); +// moreFuntionButtonInInputBar.setVisibility(View.VISIBLE); + moreFuntionButtonInInputBar.setVisibility(View.GONE); + } + } + + private boolean isRecover; + + public void setRecover(IMMessage item) { + isRecover = true; + if (recoverStateListener != null) { + recoverStateListener.getRecoverState(true); + } + rl_recover.setVisibility(View.VISIBLE); + tv_recover_name.setText(item.getFromNick()); + switch (item.getMsgType()) { + case image: + tv_recover_content.setText("[图片]"); + break; + case text: + tv_recover_content.setText(item.getContent()); + break; + case video: + tv_recover_content.setText("[视频]"); + break; + case audio: + final AudioAttachment msgAttachment = (AudioAttachment) item.getAttachment(); + long duration = msgAttachment.getDuration(); + long seconds = TimeUtil.getSecondsByMilliseconds(duration); + if (seconds >= 0) { + tv_recover_content.setText("[语音]" + seconds + "\""); + } else { + tv_recover_content.setText("[语音]"); + } + break; + } + } + + public void recoverSuccess() { + if (isRecover) { + isRecover = false; + if (recoverStateListener != null) { + recoverStateListener.getRecoverState(false); + } + rl_recover.setVisibility(View.GONE); + } + } + + private RecoverStateListener recoverStateListener; + + public void setRecoverStateListener(RecoverStateListener recoverStateListener) { + this.recoverStateListener = recoverStateListener; + } + + public interface RecoverStateListener { + void getRecoverState(boolean isRecover); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/IncomingMsgPrompt.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/IncomingMsgPrompt.java new file mode 100644 index 0000000..5361824 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/IncomingMsgPrompt.java @@ -0,0 +1,98 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module.list; + +import android.content.Context; +import android.os.Handler; +import android.text.TextUtils; +import android.text.style.ImageSpan; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.MoonUtil; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.TeamNotificationHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseFetchLoadAdapter; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +/** + * 新消息提醒模块 + * Created by hzxuwen on 2015/6/17. + */ +public class IncomingMsgPrompt { + // 底部新消息提示条 + private View newMessageTipLayout; + private TextView newMessageTipTextView; + private HeadImageView newMessageTipHeadImageView; + + private Context context; + private View view; + private RecyclerView messageListView; + private BaseFetchLoadAdapter adapter; + private Handler uiHandler; + + public IncomingMsgPrompt(Context context, View view, RecyclerView messageListView, BaseFetchLoadAdapter adapter, + Handler uiHandler) { + this.context = context; + this.view = view; + this.messageListView = messageListView; + this.adapter = adapter; + this.uiHandler = uiHandler; + } + + // 显示底部新信息提示条 + public void show(IMMessage newMessage) { + if (newMessageTipLayout == null) { + init(); + } + + if (!TextUtils.isEmpty(newMessage.getFromAccount())) { + newMessageTipHeadImageView.loadBuddyAvatar(newMessage.getFromAccount()); + } else { + newMessageTipHeadImageView.resetImageView(); + } + + MoonUtil.identifyFaceExpression(context, newMessageTipTextView, TeamNotificationHelper.getMsgShowText(newMessage), + ImageSpan.ALIGN_BOTTOM); + newMessageTipLayout.setVisibility(View.VISIBLE); + uiHandler.removeCallbacks(showNewMessageTipLayoutRunnable); + uiHandler.postDelayed(showNewMessageTipLayoutRunnable, 5 * 1000); + } + + public void onBackPressed() { + removeHandlerCallback(); + } + + // 初始化底部新信息提示条 + private void init() { + ViewGroup containerView = (ViewGroup) view.findViewById(R.id.message_activity_list_view_container); + View.inflate(context, R.layout.nim_new_message_tip_layout, containerView); + newMessageTipLayout = containerView.findViewById(R.id.new_message_tip_layout); + newMessageTipLayout.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + messageListView.scrollToPosition(adapter.getBottomDataPosition()); + newMessageTipLayout.setVisibility(View.GONE); + } + }); + newMessageTipTextView = (TextView) newMessageTipLayout.findViewById(R.id.new_message_tip_text_view); + newMessageTipHeadImageView = (HeadImageView) newMessageTipLayout.findViewById(R.id.new_message_tip_head_image_view); + } + + private Runnable showNewMessageTipLayoutRunnable = new Runnable() { + + @Override + public void run() { + newMessageTipLayout.setVisibility(View.GONE); + } + }; + + private void removeHandlerCallback() { + if (showNewMessageTipLayoutRunnable != null) { + uiHandler.removeCallbacks(showNewMessageTipLayoutRunnable); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/MessageListPanelEx.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/MessageListPanelEx.java new file mode 100644 index 0000000..c2e177c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/MessageListPanelEx.java @@ -0,0 +1,1310 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module.list; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.util.Pair; +import android.view.View; +import android.widget.ImageView; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.messaging.CustomAttachment; +import com.fengliyan.messaging.GiftAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.activity.ContactSelectActivity; +import com.fengliyan.tianlesue.im.uikit.business.preference.UserPreferences; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.LinkElement; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.VoiceTrans; +import com.fengliyan.tianlesue.im.uikit.business.session.audio.MessageAudioControl; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.MessageHelper; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.MessageListPanelHelper; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot.RobotLinkView; +import com.fengliyan.tianlesue.im.uikit.common.CommonUtil; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialogHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.IRecyclerView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener.OnItemClickListener; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore.MsgListFetchLoadMoreView; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ClipboardUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.NetworkUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.NIMSDK; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.AttachmentProgress; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum; +import com.netease.nimlib.sdk.msg.model.RevokeMsgNotification; +import com.netease.nimlib.sdk.msg.model.TeamMessageReceipt; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.robot.model.RobotMsgType; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * 基于RecyclerView的消息收发模块 + * Created by huangjun on 2016/12/27. + */ +public class MessageListPanelEx { + private static final String TAG = "MessageListPanelEx"; + + private static final int REQUEST_CODE_FORWARD_PERSON = 0x01; + private static final int REQUEST_CODE_FORWARD_TEAM = 0x02; + + // container + private Container container; + private View rootView; + + // message list view + private RecyclerView messageListView; + private List items; + private MsgAdapter adapter; + private ImageView ivBackground; + + // 新消息到达提醒 + private IncomingMsgPrompt incomingMsgPrompt; + private Handler uiHandler; + + // 仅显示消息记录,不接收和发送消息 + private boolean recordOnly; + // 从服务器拉取消息记录 + private boolean remote; + + // 语音转文字 + private VoiceTrans voiceTrans; + + // 待转发消息 + private IMMessage forwardMessage; + + // 背景图片缓存 + private static Pair background; + + //如果在发需要拍照 的消息时,拍照回来时页面可能会销毁重建,重建时会在MessageLoader 的构造方法中调一次 loadFromLocal + //而在发送消息后,list 需要滚动到底部,又会通过RequestFetchMoreListener 调用一次 loadFromLocal + //所以消息会重复 + private boolean mIsInitFetchingLocal; + + public MessageListPanelEx(Container container, View rootView, boolean recordOnly, boolean remote) { + this(container, rootView, null, recordOnly, remote); + } + + public MessageListPanelEx(Container container, View rootView, IMMessage anchor, boolean recordOnly, boolean remote) { + this.container = container; + this.rootView = rootView; + this.recordOnly = recordOnly; + this.remote = remote; + + init(anchor); + } + + public void onResume() { + setEarPhoneMode(UserPreferences.isEarPhoneModeEnable(), false); + } + + public void onPause() { + MessageAudioControl.getInstance(container.activity).stopAudio(); + } + + public void onDestroy() { + messageListView.setAdapter(null); + registerObservers(false); + } + + public boolean onBackPressed() { + uiHandler.removeCallbacks(null); + MessageAudioControl.getInstance(container.activity).stopAudio(); // 界面返回,停止语音播放 + if (voiceTrans != null && voiceTrans.isShow()) { + voiceTrans.hide(); + return true; + } + return false; + } + + public void reload(Container container, IMMessage anchor) { + this.container = container; + if (adapter != null) { + adapter.clearData(); + } + initFetchLoadListener(anchor); + } + + private void init(IMMessage anchor) { + initListView(anchor); + + this.uiHandler = new Handler(); + if (!recordOnly) { + incomingMsgPrompt = new IncomingMsgPrompt(container.activity, rootView, messageListView, adapter, uiHandler); + } + + registerObservers(true); + } + + private void initListView(IMMessage anchor) { + ivBackground = rootView.findViewById(R.id.message_activity_background); + + // RecyclerView + messageListView = rootView.findViewById(R.id.messageListView); + messageListView.setLayoutManager(new LinearLayoutManager(container.activity)); + messageListView.requestDisallowInterceptTouchEvent(true); + messageListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState != RecyclerView.SCROLL_STATE_IDLE) { + container.proxy.shouldCollapseInputPanel(); + } + } + }); + messageListView.setOverScrollMode(View.OVER_SCROLL_NEVER); + + // adapter + items = new ArrayList<>(); + adapter = new MsgAdapter(messageListView, items, container); + adapter.setFetchMoreView(new MsgListFetchLoadMoreView()); + adapter.setLoadMoreView(new MsgListFetchLoadMoreView()); + adapter.setEventListener(new MsgItemEventListener()); + initFetchLoadListener(anchor); + messageListView.setAdapter(adapter); + messageListView.addOnItemTouchListener(listener); + } + + private OnItemClickListener listener = new OnItemClickListener() { + @Override + public void onItemClick(IRecyclerView adapter, View view, int position) { + container.proxy.shouldCollapseInputPanel(); + } + + @Override + public void onItemLongClick(IRecyclerView adapter, View view, int position) { + } + + @Override + public void onItemChildClick(IRecyclerView adapter2, View view, int position) { + + if (!isSessionMode() || !(view instanceof RobotLinkView)) { + return; + } + + RobotLinkView robotLinkView = (RobotLinkView) view; + LinkElement element = robotLinkView.getElement(); + if (element == null) { + return; + } + if (LinkElement.TYPE_URL.equals(element.getType())) { + Intent intent = new Intent(); + intent.setAction("android.intent.action.VIEW"); + Uri content_url = Uri.parse(element.getTarget()); + intent.setData(content_url); + try { + container.activity.startActivity(intent); + } catch (ActivityNotFoundException e) { + ToastHelper.showToast(container.activity, "路径错误"); + } + + } else if (LinkElement.TYPE_BLOCK.equals(element.getType())) { + // 发送点击的block + IMMessage message = adapter.getItem(position); + if (message != null) { + String robotAccount = ((RobotAttachment) message.getAttachment()).getFromRobotAccount(); + IMMessage robotMsg = MessageBuilder.createRobotMessage(message.getSessionId(), + message.getSessionType(), + robotAccount, + robotLinkView.getShowContent(), + RobotMsgType.LINK, + "", + element.getTarget(), + element.getParams()); + container.proxy.sendMessage(robotMsg); + } + } + } + }; + + public boolean isSessionMode() { + return !recordOnly && !remote; + } + + private void initFetchLoadListener(IMMessage anchor) { + MessageLoader loader = new MessageLoader(anchor, remote); + if (recordOnly && !remote) { + // 双向Load + adapter.setOnFetchMoreListener(loader); + adapter.setOnLoadMoreListener(loader); + } else { + // 只下来加载old数据 + adapter.setOnFetchMoreListener(loader); + } + } + + // 刷新消息列表 + public void refreshMessageList() { + uiHandler.post(new Runnable() { + @Override + public void run() { + adapter.notifyDataSetChanged(); + } + }); + } + + public void scrollToBottom() { + uiHandler.postDelayed(new Runnable() { + @Override + public void run() { + doScrollToBottom(); + } + }, 200); + } + + private void doScrollToBottom() { + messageListView.scrollToPosition(adapter.getBottomDataPosition()); + } + + public void onIncomingMessage(List messages) { + boolean needScrollToBottom = isLastMessageVisible(); + boolean needRefresh = false; + List addedListItems = new ArrayList<>(messages.size()); + for (IMMessage message : messages) { + if (isMyMessage(message)) { + items.add(message); + addedListItems.add(message); + needRefresh = true; + } + } + if (needRefresh) { + sortMessages(items); + adapter.notifyDataSetChanged(); + } + + adapter.updateShowTimeItem(addedListItems, false, true); + + // incoming messages tip + IMMessage lastMsg = messages.get(messages.size() - 1); + if (isMyMessage(lastMsg)) { + if (needScrollToBottom) { + doScrollToBottom(); + } else if (incomingMsgPrompt != null && lastMsg.getSessionType() != SessionTypeEnum.ChatRoom) { + incomingMsgPrompt.show(lastMsg); + } + } + } + + private boolean isLastMessageVisible() { + LinearLayoutManager layoutManager = (LinearLayoutManager) messageListView.getLayoutManager(); + int lastVisiblePosition = layoutManager.findLastCompletelyVisibleItemPosition(); + return lastVisiblePosition >= adapter.getBottomDataPosition(); + } + + // 发送消息后,更新本地消息列表 + public void onMsgSend(IMMessage message) { + List addedListItems = new ArrayList<>(1); + addedListItems.add(message); + adapter.updateShowTimeItem(addedListItems, false, true); + + adapter.appendData(message); + + doScrollToBottom(); + } + + /** + * **************************** 排序 *********************************** + */ + private void sortMessages(List list) { + if (list.size() == 0) { + return; + } + Collections.sort(list, comp); + } + + private static Comparator comp = new Comparator() { + + @Override + public int compare(IMMessage o1, IMMessage o2) { + long time = o1.getTime() - o2.getTime(); + return time == 0 ? 0 : (time < 0 ? -1 : 1); + } + }; + + /** + * 消息状态变化观察者 + */ + private Observer messageStatusObserver = new Observer() { + @Override + public void onEvent(IMMessage message) { + Log.i(TAG, "onEvent: ----------->"); + if (isMyMessage(message)) { + onMessageStatusChange(message); + } + } + }; + + /** + * 消息附件上传/下载进度观察者 + */ + private Observer attachmentProgressObserver = new Observer() { + @Override + public void onEvent(AttachmentProgress progress) { + onAttachmentProgressChange(progress); + } + }; + + /** + * 消息撤回观察者 + */ + private Observer revokeMessageObserver = new Observer() { + @Override + public void onEvent(RevokeMsgNotification notification) { + if (notification == null || notification.getMessage() == null) { + return; + } + IMMessage message = notification.getMessage(); + if (!container.account.equals(message.getSessionId())) { + return; + } + + deleteItem(message, false); + MessageHelper.getInstance().onRevokeMessage(message, message.getFromAccount()); + } + }; + + /** + * 群消息已读回执观察者 + */ + private Observer> teamMessageReceiptObserver = new Observer>() { + @Override + public void onEvent(List teamMessageReceipts) { + for (TeamMessageReceipt teamMessageReceipt : teamMessageReceipts) { + int index = getItemIndex(teamMessageReceipt.getMsgId()); + if (index >= 0 && index < items.size()) { + refreshViewHolderByIndex(index); + } + } + } + }; + /** + * 用户信息观察者 + */ + private UserInfoObserver userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + if (container.sessionType == SessionTypeEnum.P2P) { + if (accounts.contains(container.account) || accounts.contains(NimUIKit.getAccount())) { + adapter.notifyDataSetChanged(); + } + } else { // 群的,简单的全部重刷 + adapter.notifyDataSetChanged(); + } + } + }; + /** + * 本地消息接收观察者 + */ + private MessageListPanelHelper.LocalMessageObserver incomingLocalMessageObserver = new MessageListPanelHelper.LocalMessageObserver() { + @Override + public void onAddMessage(IMMessage message) { + if (message == null || !container.account.equals(message.getSessionId())) { + return; + } + onMsgSend(message); + } + + @Override + public void onClearMessages(String account) { + items.clear(); + refreshMessageList(); + adapter.fetchMoreEnd(null, true); + } + }; + + /** + * ************************* 观察者 ******************************** + */ + private void registerObservers(boolean register) { + MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class); + service.observeMsgStatus(messageStatusObserver, register); + service.observeAttachmentProgress(attachmentProgressObserver, register); + service.observeRevokeMessage(revokeMessageObserver, register); + service.observeTeamMessageReceipt(teamMessageReceiptObserver, register); + + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, register); + MessageListPanelHelper.getInstance().registerObserver(incomingLocalMessageObserver, register); + } + + + private void onMessageStatusChange(IMMessage message) { + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + item.setStatus(message.getStatus()); + item.setAttachStatus(message.getAttachStatus()); + + // 处理语音、音视频通话 + if (item.getMsgType() == MsgTypeEnum.audio || item.getMsgType() == MsgTypeEnum.avchat) { + item.setAttachment(message.getAttachment()); // 附件可能更新了 + } + + // resend的的情况,可能时间已经变化了,这里要重新检查是否要显示时间 + List msgList = new ArrayList<>(1); + msgList.add(message); + adapter.updateShowTimeItem(msgList, false, true); + + refreshViewHolderByIndex(index); + } + } + + private void onAttachmentProgressChange(AttachmentProgress progress) { + int index = getItemIndex(progress.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + float value = (float) progress.getTransferred() / (float) progress.getTotal(); + adapter.putProgress(item, value); + refreshViewHolderByIndex(index); + } + } + + private boolean isMyMessage(IMMessage message) { + return message.getSessionType() == container.sessionType + && message.getSessionId() != null + && message.getSessionId().equals(container.account); + } + + /** + * 刷新单条消息 + */ + private void refreshViewHolderByIndex(final int index) { + uiHandler.post(new Runnable() { + @Override + public void run() { + if (index < 0) { + return; + } + adapter.notifyDataItemChanged(index); + } + }); + } + + private int getItemIndex(String uuid) { + for (int i = 0; i < items.size(); i++) { + IMMessage message = items.get(i); + if (TextUtils.equals(message.getUuid(), uuid)) { + return i; + } + } + return -1; + } + + public void setChattingBackground(String uriString, int color) { + if (uriString != null) { + Uri uri = Uri.parse(uriString); + if (uri.getScheme().equalsIgnoreCase("file") && uri.getPath() != null) { + ivBackground.setImageBitmap(getBackground(uri.getPath())); + } else if (uri.getScheme().equalsIgnoreCase("android.resource")) { + List paths = uri.getPathSegments(); + if (paths == null || paths.size() != 2) { + return; + } + String type = paths.get(0); + String name = paths.get(1); + String pkg = uri.getHost(); + int resId = container.activity.getResources().getIdentifier(name, type, pkg); + if (resId != 0) { + ivBackground.setBackgroundResource(resId); + } + } + } else if (color != 0) { + ivBackground.setBackgroundColor(color); + } + } + + /** + * ***************************************** 数据加载 ********************************************* + */ + private class MessageLoader implements BaseFetchLoadAdapter.RequestLoadMoreListener, BaseFetchLoadAdapter.RequestFetchMoreListener { + + private int loadMsgCount = NimUIKitImpl.getOptions().messageCountLoadOnce; + + private QueryDirectionEnum direction = null; + + private IMMessage anchor; + private boolean remote; + + private boolean firstLoad = true; + + public MessageLoader(IMMessage anchor, boolean remote) { + this.anchor = anchor; + this.remote = remote; + if (remote) { + loadFromRemote(); + } else { + if (anchor == null) { + loadFromLocal(QueryDirectionEnum.QUERY_OLD); + mIsInitFetchingLocal = true; + } else { + loadAnchorContext(); // 加载指定anchor的上下文 + } + } + } + + private RequestCallback> callback = new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List messages, Throwable exception) { + mIsInitFetchingLocal = false; + if (code != ResponseCode.RES_SUCCESS || exception != null) { + if (direction == QueryDirectionEnum.QUERY_OLD) { + adapter.fetchMoreFailed(); + } else if (direction == QueryDirectionEnum.QUERY_NEW) { + adapter.loadMoreFail(); + } + + return; + } + + if (messages != null) { + List iterator = new ArrayList<>(); + if (SPUtils.getInt(container.activity, ConsUser.DYNAMICS_TYPE) > 0 && TextUtils.equals("11", container.account)) { + for (IMMessage message : messages) { + CustomAttachment customAttachment = (CustomAttachment) message.getAttachment(); + if (customAttachment.getType() == SPUtils.getInt(container.activity, ConsUser.DYNAMICS_TYPE)) { + iterator.add(message); + } + } + } else { + iterator.addAll(messages); + } + onMessageLoaded(iterator); + } + } + }; + + private void loadAnchorContext() { + // query new, auto load old + direction = QueryDirectionEnum.QUERY_NEW; + NIMClient.getService(MsgService.class) + .queryMessageListEx(anchor(), direction, loadMsgCount, true) + .setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List messages, Throwable exception) { + if (code != ResponseCode.RES_SUCCESS || exception != null) { + return; + } + onAnchorContextMessageLoaded(messages); + } + }); + } + + private void loadFromLocal(QueryDirectionEnum direction) { + if (mIsInitFetchingLocal) { + return; + } + this.direction = direction; + NIMClient.getService(MsgService.class) + .queryMessageListEx(anchor(), direction, loadMsgCount, true) + .setCallback(callback); + } + + private void loadFromRemote() { + this.direction = QueryDirectionEnum.QUERY_OLD; + NIMClient.getService(MsgService.class) + .pullMessageHistory(anchor(), loadMsgCount, true) + .setCallback(callback); + } + + private IMMessage anchor() { + if (items.size() == 0) { + return anchor == null ? MessageBuilder.createEmptyMessage(container.account, container.sessionType, 0) : anchor; + } else { + int index = (direction == QueryDirectionEnum.QUERY_NEW ? items.size() - 1 : 0); + return items.get(index); + } + } + + private void onMessageLoaded(final List messages) { + if (messages == null) { + return; + } + for (int i = 0; i < messages.size(); i++) { + if (messages.get(i).getDirect() == MsgDirectionEnum.Out) { + isShowCallList = false; + break; + } + } + + boolean noMoreMessage = messages.size() < loadMsgCount; + + if (remote) { + Collections.reverse(messages); + } + + // 在第一次加载的过程中又收到了新消息,做一下去重 + if (firstLoad && items.size() > 0) { + for (IMMessage message : messages) { + int removeIndex = 0; + for (IMMessage item : items) { + if (item.isTheSame(message)) { + adapter.remove(removeIndex); + break; + } + removeIndex++; + } + } + } + + // 加入anchor + if (firstLoad && anchor != null) { + messages.add(anchor); + } + + // 在更新前,先确定一些标记 + List total = new ArrayList<>(items); + boolean isBottomLoad = direction == QueryDirectionEnum.QUERY_NEW; + if (isBottomLoad) { + total.addAll(messages); + } else { + total.addAll(0, messages); + } + // 更新要显示时间的消息 + adapter.updateShowTimeItem(total, true, firstLoad); + + // 更新已读回执标签 + updateReceipt(total); + + // 加载状态修改,刷新界面 + if (isBottomLoad) { + // 底部加载 + if (noMoreMessage) { + adapter.loadMoreEnd(messages, true); + } else { + adapter.loadMoreComplete(messages); + } + } else { + // 顶部加载 + if (noMoreMessage) { + adapter.fetchMoreEnd(messages, true); + } else { + adapter.fetchMoreComplete(messages); + } + } + + // 如果是第一次加载,updateShowTimeItem返回的就是lastShowTimeItem + if (firstLoad) { + doScrollToBottom(); + sendReceipt(); // 发送已读回执 + } + + // 通过历史记录加载的群聊消息,需要刷新一下已读未读最新数据 + if (container.sessionType == SessionTypeEnum.Team) { + NIMSDK.getTeamService().refreshTeamMessageReceipt(messages); + } + + firstLoad = false; + } + + private void onAnchorContextMessageLoaded(final List messages) { + if (messages == null) { + return; + } + + if (remote) { + Collections.reverse(messages); + } + + int loadCount = messages.size(); + if (firstLoad && anchor != null) { + messages.add(0, anchor); + } + + // 在更新前,先确定一些标记 + adapter.updateShowTimeItem(messages, true, firstLoad); // 更新要显示时间的消息 + updateReceipt(messages); // 更新已读回执标签 + + // new data + if (loadCount < loadMsgCount) { + adapter.loadMoreEnd(messages, true); + } else { + adapter.appendData(messages); + } + + firstLoad = false; + } + + @Override + public void onFetchMoreRequested() { + // 顶部加载历史数据 + if (remote) { + loadFromRemote(); + } else { + loadFromLocal(QueryDirectionEnum.QUERY_OLD); + } + } + + @Override + public void onLoadMoreRequested() { + // 底部加载新数据 + if (!remote) { + loadFromLocal(QueryDirectionEnum.QUERY_NEW); + } + } + } + + private class MsgItemEventListener implements MsgAdapter.ViewHolderEventListener { + + @Override + public void onFailedBtnClick(IMMessage message) { + if (message.getDirect() == MsgDirectionEnum.Out) { + // 发出的消息,如果是发送失败,直接重发,否则有可能是漫游到的多媒体消息,但文件下载 + if (message.getStatus() == MsgStatusEnum.fail) { + resendMessage(message); // 重发 + } else { + if (message.getAttachment() instanceof FileAttachment) { + FileAttachment attachment = (FileAttachment) message.getAttachment(); + if (TextUtils.isEmpty(attachment.getPath()) + && TextUtils.isEmpty(attachment.getThumbPath())) { + showReDownloadConfirmDlg(message); + } + } else { + resendMessage(message); + } + } + } else { + showReDownloadConfirmDlg(message); + } + } + + @Override + public boolean onViewHolderLongClick(View clickView, View viewHolderView, IMMessage item) { + if (container.proxy.isLongClickEnabled()) { + showLongClickAction(item); + } + return true; + } + + @Override + public void onFooterClick(IMMessage message) { + // 与 robot 对话 + container.proxy.onItemFooterClick(message); + } + + // 重新下载(对话框提示) + private void showReDownloadConfirmDlg(final IMMessage message) { + EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() { + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + // 正常情况收到消息后附件会自动下载。如果下载失败,可调用该接口重新下载 + if (message.getAttachment() != null && message.getAttachment() instanceof FileAttachment) + NIMClient.getService(MsgService.class).downloadAttachment(message, true); + } + }; + + final EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(container.activity, null, + container.activity.getString(R.string.repeat_download_message), true, listener); + dialog.show(); + } + + // 重发消息到服务器 + private void resendMessage(IMMessage message) { + // 重置状态为unsent + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + item.setStatus(MsgStatusEnum.sending); + deleteItem(item, true); + onMsgSend(item); + } + + NIMClient.getService(MsgService.class).sendMessage(message, true); + } + + /** + * ****************************** 长按菜单 ******************************** + */ + + // 长按消息Item后弹出菜单控制 + private void showLongClickAction(IMMessage selectedItem) { + onNormalLongClick(selectedItem); + } + + /** + * 长按菜单操作 + * + * @param item + */ + private void onNormalLongClick(IMMessage item) { + CustomAlertDialog alertDialog = new CustomAlertDialog(container.activity); + alertDialog.setCancelable(true); + alertDialog.setCanceledOnTouchOutside(true); + + prepareDialogItems(item, alertDialog); + alertDialog.show(); + } + + // 长按消息item的菜单项准备。如果消息item的MsgViewHolder处理长按事件(MsgViewHolderBase#onItemLongClick),且返回为true, + // 则对应项的长按事件不会调用到此处 + private void prepareDialogItems(final IMMessage selectedItem, CustomAlertDialog alertDialog) { + MsgTypeEnum msgType = selectedItem.getMsgType(); + + MessageAudioControl.getInstance(container.activity).stopAudio(); + + // 0 EarPhoneMode +// longClickItemEarPhoneMode(alertDialog, msgType); + // 1 resend +// longClickItemResend(selectedItem, alertDialog); + // 2 copy + longClickItemCopy(selectedItem, alertDialog, msgType); + // 3 revoke + if (enableRevokeButton(selectedItem)) { + longClickRevokeMsg(selectedItem, alertDialog); + } + if (selectedItem.getMsgType() == MsgTypeEnum.image || selectedItem.getMsgType() == MsgTypeEnum.video || selectedItem.getMsgType() == MsgTypeEnum.text || selectedItem.getMsgType() == MsgTypeEnum.audio) { + longClickRecoverMsg(selectedItem, alertDialog); + } + // 4 delete + longClickItemDelete(selectedItem, alertDialog); + // 5 trans +// longClickItemVoidToText(selectedItem, alertDialog, msgType); + +// if (!NimUIKitImpl.getMsgForwardFilter().shouldIgnore(selectedItem) && !recordOnly) { +// // 6 forward to person +// longClickItemForwardToPerson(selectedItem, alertDialog); +// // 7 forward to team +// longClickItemForwardToTeam(selectedItem, alertDialog); +// } + } + + private boolean enableRevokeButton(IMMessage selectedItem) { + if (selectedItem.getStatus() == MsgStatusEnum.success + && !(selectedItem.getAttachment() instanceof GiftAttachment) +// && !NimUIKitImpl.getMsgRevokeFilter().shouldIgnore(selectedItem) + && !recordOnly) { + if (selectedItem.getDirect() == MsgDirectionEnum.Out) { + return true; + } else if (NimUIKit.getOptions().enableTeamManagerRevokeMsg && selectedItem.getSessionType() == SessionTypeEnum.Team) { + TeamMember member = NimUIKit.getTeamProvider().getTeamMember(selectedItem.getSessionId(), NimUIKit.getAccount()); + return member != null && member.getType() == TeamMemberType.Owner || member.getType() == TeamMemberType.Manager; + } + } + return false; + } + + // 长按菜单项--重发 + private void longClickItemResend(final IMMessage item, CustomAlertDialog alertDialog) { + if (item.getStatus() != MsgStatusEnum.fail) { + return; + } + alertDialog.addItem(container.activity.getString(R.string.repeat_send_has_blank), new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + onResendMessageItem(item); + } + }); + } + + private void onResendMessageItem(IMMessage message) { + int index = getItemIndex(message.getUuid()); + if (index >= 0) { + showResendConfirm(message); // 重发确认 + } + } + + private void showResendConfirm(final IMMessage message) { + EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() { + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + resendMessage(message); + } + }; + final EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(container.activity, null, + container.activity.getString(R.string.repeat_send_message), true, listener); + dialog.show(); + } + + // 长按菜单项--复制 + private void longClickItemCopy(final IMMessage item, CustomAlertDialog alertDialog, MsgTypeEnum msgType) { + if (msgType == MsgTypeEnum.text + || (msgType == MsgTypeEnum.robot && item.getAttachment() != null && !((RobotAttachment) item.getAttachment()).isRobotSend())) { + alertDialog.addItem(container.activity.getString(R.string.copy_has_blank), new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + onCopyMessageItem(item); + } + }); + } + } + + private void onCopyMessageItem(IMMessage item) { + ClipboardUtil.clipboardCopyText(container.activity, item.getContent()); + } + + // 长按菜单项--删除 + private void longClickItemDelete(final IMMessage selectedItem, CustomAlertDialog alertDialog) { + if (recordOnly) { + return; + } + alertDialog.addItem(container.activity.getString(R.string.delete_has_blank), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + deleteItem(selectedItem, true); + } + }); + } + + // 长按菜单项 -- 音频转文字 + private void longClickItemVoidToText(final IMMessage item, CustomAlertDialog alertDialog, MsgTypeEnum msgType) { + if (msgType != MsgTypeEnum.audio) return; + + if (item.getDirect() == MsgDirectionEnum.In && item.getAttachStatus() != AttachStatusEnum.transferred) + return; + if (item.getDirect() == MsgDirectionEnum.Out && item.getAttachStatus() != AttachStatusEnum.transferred) + return; + + alertDialog.addItem(container.activity.getString(R.string.voice_to_text), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + onVoiceToText(item); + } + }); + } + + // 语音转文字 + private void onVoiceToText(IMMessage item) { + if (voiceTrans == null) + voiceTrans = new VoiceTrans(container.activity); + voiceTrans.voiceToText(item); + if (item.getDirect() == MsgDirectionEnum.In && item.getStatus() != MsgStatusEnum.read) { + item.setStatus(MsgStatusEnum.read); + NIMClient.getService(MsgService.class).updateIMMessageStatus(item); + adapter.notifyDataSetChanged(); + } + } + + // 长按菜单项 -- 听筒扬声器切换 + private void longClickItemEarPhoneMode(CustomAlertDialog alertDialog, MsgTypeEnum msgType) { + if (msgType != MsgTypeEnum.audio) { + return; + } + + String content = UserPreferences.isEarPhoneModeEnable() ? "切换成扬声器播放" : "切换成听筒播放"; + final String finalContent = content; + alertDialog.addItem(content, new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + ToastHelper.showToast(container.activity, finalContent); + setEarPhoneMode(!UserPreferences.isEarPhoneModeEnable(), true); + } + }); + } + + // 长按菜单项 -- 转发到个人 + private void longClickItemForwardToPerson(final IMMessage item, CustomAlertDialog alertDialog) { + alertDialog.addItem(container.activity.getString(R.string.forward_to_person), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + forwardMessage = item; + ContactSelectActivity.Option option = new ContactSelectActivity.Option(); + option.title = "选择转发的人"; + option.type = ContactSelectActivity.ContactSelectType.BUDDY; + option.multi = false; + option.maxSelectNum = 1; + NimUIKit.startContactSelector(container.activity, option, REQUEST_CODE_FORWARD_PERSON); + } + }); + } + + // 长按菜单项 -- 转发到群组 + private void longClickItemForwardToTeam(final IMMessage item, CustomAlertDialog alertDialog) { + alertDialog.addItem(container.activity.getString(R.string.forward_to_team), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + forwardMessage = item; + ContactSelectActivity.Option option = new ContactSelectActivity.Option(); + option.title = "选择转发的群"; + option.type = ContactSelectActivity.ContactSelectType.TEAM; + option.multi = false; + option.maxSelectNum = 1; + NimUIKit.startContactSelector(container.activity, option, REQUEST_CODE_FORWARD_TEAM); + } + }); + } + + // 长按菜单项 -- 撤回消息 + private void longClickRevokeMsg(final IMMessage item, CustomAlertDialog alertDialog) { + alertDialog.addItem(container.activity.getString(R.string.withdrawn_msg), new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + if (!NetworkUtil.isNetAvailable(container.activity)) { + ToastHelper.showToast(container.activity, R.string.network_is_not_available); + return; + } + NIMClient.getService(MsgService.class).revokeMessage(item).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + deleteItem(item, false); + MessageHelper.getInstance().onRevokeMessage(item, NimUIKit.getAccount()); + } + + @Override + public void onFailed(int code) { + if (code == ResponseCode.RES_OVERDUE) { + ToastHelper.showToast(container.activity, R.string.revoke_failed); + } else { + ToastHelper.showToast(container.activity, "revoke msg failed, code:" + code); + } + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + }); + } + + // 长按菜单项 -- 回复消息 + private void longClickRecoverMsg(final IMMessage item, CustomAlertDialog alertDialog) { + alertDialog.addItem(container.activity.getString(R.string.recover_msg), new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + if (!NetworkUtil.isNetAvailable(container.activity)) { + ToastHelper.showToast(container.activity, R.string.network_is_not_available); + return; + } + + if (recoverListener != null) { + recoverListener.recoverMsg(item); + } + } + }); + } + + } + + private void setEarPhoneMode(boolean earPhoneMode, boolean update) { + if (update) { + UserPreferences.setEarPhoneModeEnable(earPhoneMode); + } + MessageAudioControl.getInstance(container.activity).setEarPhoneModeEnable(earPhoneMode); + } + + private Bitmap getBackground(String path) { + if (background != null && path.equals(background.first) && background.second != null) { + return background.second; + } + + if (background != null && background.second != null) { + background.second.recycle(); + } + + Bitmap bitmap = null; + if (path.startsWith("/android_asset")) { + String asset = path.substring(path.indexOf("/", 1) + 1); + try { + InputStream ais = container.activity.getAssets().open(asset); + bitmap = BitmapDecoder.decodeSampled(ais, ScreenUtil.screenWidth, ScreenUtil.screenHeight); + ais.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + bitmap = BitmapDecoder.decodeSampled(path, ScreenUtil.screenWidth, ScreenUtil.screenHeight); + } + background = new Pair<>(path, bitmap); + return bitmap; + } + + + /** + * 收到已读回执(更新VH的已读label) + */ + public void receiveReceipt() { + updateReceipt(items); + refreshMessageList(); + } + + private void updateReceipt(final List messages) { + for (int i = messages.size() - 1; i >= 0; i--) { + if (receiveReceiptCheck(messages.get(i))) { + adapter.setUuid(messages.get(i).getUuid()); + break; + } + } + } + + private boolean receiveReceiptCheck(final IMMessage msg) { + return msg != null + && msg.getSessionType() == SessionTypeEnum.P2P + && msg.getDirect() == MsgDirectionEnum.Out + && msg.getMsgType() != MsgTypeEnum.tip + && msg.getMsgType() != MsgTypeEnum.notification + && msg.isRemoteRead(); + + } + + /** + * 发送已读回执(需要过滤) + */ + public void sendReceipt() { + // 查询全局已读回执功能开关配置 + if (!NimUIKitImpl.getOptions().shouldHandleReceipt) { + return; + } + + if (container.account == null || container.sessionType != SessionTypeEnum.P2P) { + return; + } + + IMMessage message = getLastReceivedMessage(); + if (!sendReceiptCheck(message)) { + return; + } + + NIMClient.getService(MsgService.class).sendMessageReceipt(container.account, message); + } + + private IMMessage getLastReceivedMessage() { + IMMessage lastMessage = null; + for (int i = items.size() - 1; i >= 0; i--) { + if (sendReceiptCheck(items.get(i))) { + lastMessage = items.get(i); + break; + } + } + + return lastMessage; + } + + private boolean sendReceiptCheck(final IMMessage msg) { + return msg != null + && msg.getDirect() == MsgDirectionEnum.In + && msg.getMsgType() != MsgTypeEnum.tip + && msg.getMsgType() != MsgTypeEnum.notification; + } + + // 删除消息 + private void deleteItem(IMMessage messageItem, boolean isRelocateTime) { + NIMClient.getService(MsgService.class).deleteChattingHistory(messageItem); + List messages = new ArrayList<>(); + for (IMMessage message : items) { + if (message.getUuid().equals(messageItem.getUuid())) { + continue; + } + messages.add(message); + } + updateReceipt(messages); + adapter.deleteItem(messageItem, isRelocateTime); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode != Activity.RESULT_OK) { + return; + } + final ArrayList selected = data.getStringArrayListExtra(ContactSelectActivity.RESULT_DATA); + if (CommonUtil.isEmpty(selected)) { + return; + } + switch (requestCode) { + case REQUEST_CODE_FORWARD_TEAM: + doForwardMessage(selected.get(0), SessionTypeEnum.Team); + break; + case REQUEST_CODE_FORWARD_PERSON: + doForwardMessage(selected.get(0), SessionTypeEnum.P2P); + break; + } + + } + + // 转发消息 + private void doForwardMessage(final String sessionId, SessionTypeEnum sessionTypeEnum) { + IMMessage message; + if (forwardMessage.getMsgType() == MsgTypeEnum.robot) { + message = buildForwardRobotMessage(sessionId, sessionTypeEnum); + } else { + message = MessageBuilder.createForwardMessage(forwardMessage, sessionId, sessionTypeEnum); + } + + if (message == null) { + ToastHelper.showToast(container.activity, "该类型不支持转发"); + return; + } + + NIMClient.getService(MsgService.class).sendMessage(message, false); + if (container.account.equals(sessionId)) { + onMsgSend(message); + } + } + + private IMMessage buildForwardRobotMessage(final String sessionId, SessionTypeEnum sessionTypeEnum) { + if (forwardMessage.getMsgType() == MsgTypeEnum.robot && forwardMessage.getAttachment() != null) { + RobotAttachment robotAttachment = (RobotAttachment) forwardMessage.getAttachment(); + if (robotAttachment.isRobotSend()) { + return null; // 机器人发的消息不能转发了 + } + return MessageBuilder.createTextMessage(sessionId, sessionTypeEnum, forwardMessage.getContent()); + } + + return null; + } + + private RecoverListener recoverListener; + + public void setRecoverListener(RecoverListener recoverListener) { + this.recoverListener = recoverListener; + } + + public interface RecoverListener { + void recoverMsg(IMMessage item); + } + + private boolean isShowCallList = true; + + public boolean isShowCallList() { + return isShowCallList; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/MsgAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/MsgAdapter.java new file mode 100644 index 0000000..6b178e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/module/list/MsgAdapter.java @@ -0,0 +1,292 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.module.list; + +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.module.Container; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderFactory; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.opensource.svgaplayer.SVGAImageView; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by huangjun on 2016/12/21. + */ +public class MsgAdapter extends BaseMultiItemFetchLoadAdapter { + + private Map, Integer> holder2ViewType; + + private ViewHolderEventListener eventListener; + private Map progresses; // 有文件传输,需要显示进度条的消息ID map + private String messageId; + private Container container; + + MsgAdapter(RecyclerView recyclerView, List data, Container container) { + super(recyclerView, data); + + timedItems = new HashSet<>(); + progresses = new HashMap<>(); + + // view type, view holder + holder2ViewType = new HashMap<>(); + List> holders = MsgViewHolderFactory.getAllViewHolders(); + int viewType = 0; + for (Class holder : holders) { + viewType++; + addItemType(viewType, R.layout.nim_message_item, holder); + holder2ViewType.put(holder, viewType); + } + + this.container = container; +// registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { +// @Override +// public void onChanged() { +// Log.e("TAG","AdapterData Change...."); +// } +// }); + } + + @Override + protected int getViewType(IMMessage message) { + return holder2ViewType.get(MsgViewHolderFactory.getViewHolderByType(message)); + } + + @Override + protected String getItemKey(IMMessage item) { + return item.getUuid(); + } + + public void setEventListener(ViewHolderEventListener eventListener) { + this.eventListener = eventListener; + } + + public ViewHolderEventListener getEventListener() { + return eventListener; + } + + public void deleteItem(IMMessage message, boolean isRelocateTime) { + if (message == null) { + return; + } + + int index = 0; + for (IMMessage item : getData()) { + if (item.isTheSame(message)) { + break; + } + ++index; + } + + if (index < getDataSize()) { + remove(index); + if (isRelocateTime) { + relocateShowTimeItemAfterDelete(message, index); + } +// notifyDataSetChanged(); // 可以不要!!! + } + } + + public float getProgress(IMMessage message) { + Float progress = progresses.get(message.getUuid()); + return progress == null ? 0 : progress; + } + + public void putProgress(IMMessage message, float progress) { + progresses.put(message.getUuid(), progress); + } + + /** + * *********************** 时间显示处理 *********************** + */ + + private Set timedItems; // 需要显示消息时间的消息ID + private IMMessage lastShowTimeItem; // 用于消息时间显示,判断和上条消息间的时间间隔 + + public boolean needShowTime(IMMessage message) { + return timedItems.contains(message.getUuid()); + } + + /** + * 列表加入新消息时,更新时间显示 + */ + public void updateShowTimeItem(List items, boolean fromStart, boolean update) { + IMMessage anchor = fromStart ? null : lastShowTimeItem; + for (IMMessage message : items) { + if (setShowTimeFlag(message, anchor)) { + anchor = message; + } + } + + if (update) { + lastShowTimeItem = anchor; + } + } + + /** + * 是否显示时间item + */ + private boolean setShowTimeFlag(IMMessage message, IMMessage anchor) { + boolean update = false; + + if (hideTimeAlways(message)) { + setShowTime(message, false); + } else { + if (anchor == null) { + setShowTime(message, true); + update = true; + } else { + long time = anchor.getTime(); + long now = message.getTime(); + + if (now - time == 0) { + // 消息撤回时使用 + setShowTime(message, true); + lastShowTimeItem = message; + update = true; + } else if (now - time < (NimUIKitImpl.getOptions().displayMsgTimeWithInterval)) { + setShowTime(message, false); + } else { + setShowTime(message, true); + update = true; + } + } + } + + return update; + } + + private void setShowTime(IMMessage message, boolean show) { + if (show) { + timedItems.add(message.getUuid()); + } else { + timedItems.remove(message.getUuid()); + } + } + + private void relocateShowTimeItemAfterDelete(IMMessage messageItem, int index) { + // 如果被删的项显示了时间,需要继承 + if (needShowTime(messageItem)) { + setShowTime(messageItem, false); + if (getDataSize() > 0) { + IMMessage nextItem; + if (index == getDataSize()) { + //删除的是最后一项 + nextItem = getItem(index - 1); + } else { + //删除的不是最后一项 + nextItem = getItem(index); + } + + // 增加其他不需要显示时间的消息类型判断 + if (hideTimeAlways(nextItem)) { + setShowTime(nextItem, false); + if (lastShowTimeItem != null && lastShowTimeItem != null + && lastShowTimeItem.isTheSame(messageItem)) { + lastShowTimeItem = null; + for (int i = getDataSize() - 1; i >= 0; i--) { + IMMessage item = getItem(i); + if (needShowTime(item)) { + lastShowTimeItem = item; + break; + } + } + } + } else { + setShowTime(nextItem, true); + if (lastShowTimeItem == null + || (lastShowTimeItem != null && lastShowTimeItem.isTheSame(messageItem))) { + lastShowTimeItem = nextItem; + } + } + } else { + lastShowTimeItem = null; + } + } + } + + private boolean hideTimeAlways(IMMessage message) { + if (message.getSessionType() == SessionTypeEnum.ChatRoom) { + return true; + } + switch (message.getMsgType()) { + case notification: + return true; + default: + return false; + } + } + + public interface ViewHolderEventListener { + // 长按事件响应处理 + boolean onViewHolderLongClick(View clickView, View viewHolderView, IMMessage item); + + // 发送失败或者多媒体文件下载失败指示按钮点击响应处理 + void onFailedBtnClick(IMMessage resendMessage); + + // viewholder footer按钮点击,如机器人继续会话 + void onFooterClick(IMMessage message); + } + + public void setUuid(String messageId) { + this.messageId = messageId; + } + + public String getUuid() { + return messageId; + } + + public Container getContainer() { + return container; + } + + @Override + public void onViewRecycled(BaseViewHolder holder) { + super.onViewRecycled(holder); + View svga_image_view1 = holder.getView(R.id.svga_image_view1); + View svga_image_view2 = holder.getView(R.id.svga_image_view2); + if (svga_image_view1 instanceof SVGAImageView) { + SVGAImageView svgImageView = (SVGAImageView) svga_image_view1; + svgImageView.stopAnimation(true); + svgImageView.clear(); + } + if (svga_image_view2 instanceof SVGAImageView) { + SVGAImageView svgImageView = (SVGAImageView) svga_image_view2; + svgImageView.stopAnimation(true); + svgImageView.clear(); + } + } +// +// @Override +// public void onViewAttachedToWindow(BaseViewHolder holder) { +// super.onViewAttachedToWindow(holder); +// View svga_image_view1 = holder.getView(R.id.svga_image_view1); +// View svga_image_view2 = holder.getView(R.id.svga_image_view2); +// if (svga_image_view1 instanceof SVGAImageView) { +// SVGAImageView svgImageView = (SVGAImageView) svga_image_view1; +// // 如果之前已设置过动画,则重新启动 +// if (svgImageView.getVisibility() == View.VISIBLE) { +// svgImageView.startAnimation(); +// } +// } +// if (svga_image_view2 instanceof SVGAImageView) { +// SVGAImageView svgImageView = (SVGAImageView) svga_image_view2; +// // 如果之前已设置过动画,则重新启动 +// if (svgImageView.getVisibility() == View.VISIBLE) { +// svgImageView.startAnimation(); +// } +// } +// } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/GiftViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/GiftViewHolder.java new file mode 100644 index 0000000..82f88ab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/GiftViewHolder.java @@ -0,0 +1,108 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.graphics.Color; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.messaging.GiftAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class GiftViewHolder extends MsgViewHolderBase { + + private FrameLayout rl_gift; + private LinearLayout lin_gift; + private TextView mTv_gift_name; + private SimpleDraweeView mSv_gift_logo; + private TextView mTv_gift_count; + private GiftAttachment mGiftAttachment; + + public GiftViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.gift_custom_message; + } + + @Override + protected void inflateContentView() { + rl_gift = view.findViewById(R.id.rl_gift); + lin_gift = view.findViewById(R.id.lin_gift); + mTv_gift_name = view.findViewById(R.id.tv_gift_name); + mSv_gift_logo = view.findViewById(R.id.sv_gift_logo); + mTv_gift_count = view.findViewById(R.id.tv_gift_count); + } + + @Override + protected void bindContentView() { + layoutDirection(); + if (message.getAttachment() == null) { + return; + } + mGiftAttachment = (GiftAttachment) message.getAttachment(); + switch (mGiftAttachment.getType()) { + case 14: + if (mGiftAttachment.getFrom_uid() == SPUtils.getInt(context, ConsUser.USER_ID)) { + mTv_gift_name.setText("送" + mGiftAttachment.getGift_name()); + } else { + mTv_gift_name.setText("收" + mGiftAttachment.getGift_name()); + } + + mSv_gift_logo.setImageURI(StrU.getResourcePath(mGiftAttachment.getGift_url(), context)); + mTv_gift_count.setText("x" + mGiftAttachment.getGift_count()); + break; + } + } + + private void layoutDirection() { + if (isReceivedMessage()) { + mTv_gift_name.setTextColor(Color.BLACK); + mTv_gift_count.setTextColor(Color.BLACK); + + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); + showBorder(info, false, contentContainer); + } else { + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); + boolean b = showBorder(info, true, contentContainer); + if (b) { + mTv_gift_name.setTextColor(Color.BLACK); + mTv_gift_count.setTextColor(Color.BLACK); + } else { + mTv_gift_name.setTextColor(Color.WHITE); + mTv_gift_count.setTextColor(Color.WHITE); + } + } +// setBackground(rl_gift); +// setBackground(lin_gift); + } + +// @Override +// protected int leftBackground() { +// return R.drawable.shape_news_gift_background; +// } +// +// @Override +// protected int rightBackground() { +// return R.drawable.shape_news_gift_background; +// } + + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderAudio.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderAudio.java new file mode 100644 index 0000000..bd2debb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderAudio.java @@ -0,0 +1,324 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.session.audio.MessageAudioControl; +import com.fengliyan.tianlesue.im.uikit.common.media.audioplayer.Playable; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +/** + * Created by zhoujianghua on 2015/8/5. + */ +public class MsgViewHolderAudio extends MsgViewHolderBase { + + public MsgViewHolderAudio(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + public static final int CLICK_TO_PLAY_AUDIO_DELAY = 500; + + private TextView durationLabel; + private View containerView; + private View unreadIndicator; + private ImageView animationView; + + private MessageAudioControl audioControl; + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_audio; + } + + @Override + protected void inflateContentView() { + durationLabel = findViewById(R.id.message_item_audio_duration); + containerView = findViewById(R.id.message_item_audio_container); + unreadIndicator = findViewById(R.id.message_item_audio_unread_indicator); + animationView = findViewById(R.id.message_item_audio_playing_animation); + animationView.setBackgroundResource(0); + audioControl = MessageAudioControl.getInstance(context); + } + + @Override + protected void bindContentView() { + layoutByDirection(); + + refreshStatus(); + + controlPlaying(); + } + + @Override + protected void onItemClick() { + if (audioControl != null) { + if (message.getDirect() == MsgDirectionEnum.In && message.getAttachStatus() != AttachStatusEnum.transferred) { + if (message.getAttachStatus() == AttachStatusEnum.fail || message.getAttachStatus() == AttachStatusEnum.def) { + NIMClient.getService(MsgService.class).downloadAttachment(message, false); + } + return; + } + + if (message.getStatus() != MsgStatusEnum.read) { + // 将未读标识去掉,更新数据库 + unreadIndicator.setVisibility(View.GONE); + } + + initPlayAnim(); // 设置语音播放动画 + + audioControl.startPlayAudioDelay(CLICK_TO_PLAY_AUDIO_DELAY, message, onPlayListener); + + audioControl.setPlayNext(!NimUIKitImpl.getOptions().disableAutoPlayNextAudio, adapter, message); + } + } + + private void layoutByDirection() { + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); + if (isReceivedMessage()) { + setGravity(animationView, Gravity.LEFT | Gravity.CENTER_VERTICAL); + setGravity(durationLabel, Gravity.RIGHT | Gravity.CENTER_VERTICAL); + durationLabel.setTextColor(Color.BLACK); + showBorder(info, false, containerView); + +// containerView.setBackgroundResource(NimUIKitImpl.getOptions().messageLeftBackground); + containerView.setPadding(ScreenUtil.dip2px(15), ScreenUtil.dip2px(8), ScreenUtil.dip2px(10), ScreenUtil.dip2px(8)); + animationView.setBackgroundResource(R.drawable.nim_audio_animation_list_left); + + } else { + setGravity(animationView, Gravity.RIGHT | Gravity.CENTER_VERTICAL); + setGravity(durationLabel, Gravity.LEFT | Gravity.CENTER_VERTICAL); + unreadIndicator.setVisibility(View.GONE); + +// containerView.setBackgroundResource(NimUIKitImpl.getOptions().messageRightBackground); + boolean b = showBorder(info, true, containerView); + if (b) { + durationLabel.setTextColor(Color.BLACK); + } else { + durationLabel.setTextColor(Color.WHITE); + } + + containerView.setPadding(ScreenUtil.dip2px(10), ScreenUtil.dip2px(8), ScreenUtil.dip2px(15), ScreenUtil.dip2px(8)); + animationView.setBackgroundResource(R.drawable.nim_audio_animation_list_right); + } + } + + private void refreshStatus() {// 消息状态 + AudioAttachment attachment = (AudioAttachment) message.getAttachment(); + MsgStatusEnum status = message.getStatus(); + AttachStatusEnum attachStatus = message.getAttachStatus(); + + // alert button + if (TextUtils.isEmpty(attachment.getPath())) { + if (attachStatus == AttachStatusEnum.fail || status == MsgStatusEnum.fail) { + alertButton.setVisibility(View.VISIBLE); + } else { + alertButton.setVisibility(View.GONE); + } + } + + // progress bar indicator + if (status == MsgStatusEnum.sending || attachStatus == AttachStatusEnum.transferring) { + progressBar.setVisibility(View.VISIBLE); + } else { + progressBar.setVisibility(View.GONE); + } + + // unread indicator + if (!NimUIKitImpl.getOptions().disableAudioPlayedStatusIcon + && isReceivedMessage() + && attachStatus == AttachStatusEnum.transferred + && status != MsgStatusEnum.read) { + unreadIndicator.setVisibility(View.VISIBLE); + if (isReceivedMessage()) { + leftVipBorderIndicator.setTranslationX(-Utils.dip2px(context, 24)); + } else { + rightVipBorderIndicator.setTranslationX(Utils.dip2px(context, 24)); + } + } else { + unreadIndicator.setVisibility(View.GONE); + } + } + + private void controlPlaying() { + final AudioAttachment msgAttachment = (AudioAttachment) message.getAttachment(); + long duration = msgAttachment.getDuration(); + setAudioBubbleWidth(duration); + + durationLabel.setTag(message.getUuid()); + + if (!isMessagePlaying(audioControl, message)) { + if (audioControl.getAudioControlListener() != null && + audioControl.getAudioControlListener().equals(onPlayListener)) { + audioControl.changeAudioControlListener(null); + } + + updateTime(duration); + stop(); + } else { + audioControl.changeAudioControlListener(onPlayListener); + play(); + } + } + + public static int getAudioMaxEdge() { + return (int) (0.6 * ScreenUtil.screenMin); + } + + public static int getAudioMinEdge() { + return (int) (0.1875 * ScreenUtil.screenMin); + } + + private void setAudioBubbleWidth(long milliseconds) { + long seconds = TimeUtil.getSecondsByMilliseconds(milliseconds); + + int currentBubbleWidth = calculateBubbleWidth(seconds, NimUIKitImpl.getOptions().audioRecordMaxTime); + ViewGroup.LayoutParams layoutParams = containerView.getLayoutParams(); + layoutParams.width = currentBubbleWidth; + containerView.setLayoutParams(layoutParams); + } + + private int calculateBubbleWidth(long seconds, int MAX_TIME) { + int maxAudioBubbleWidth = getAudioMaxEdge(); + int minAudioBubbleWidth = getAudioMinEdge(); + + int currentBubbleWidth; + if (seconds <= 0) { + currentBubbleWidth = minAudioBubbleWidth; + } else if (seconds > 0 && seconds <= MAX_TIME) { + currentBubbleWidth = (int) ((maxAudioBubbleWidth - minAudioBubbleWidth) * (2.0 / Math.PI) + * Math.atan(seconds / 10.0) + minAudioBubbleWidth); + } else { + currentBubbleWidth = maxAudioBubbleWidth; + } + + if (currentBubbleWidth < minAudioBubbleWidth) { + currentBubbleWidth = minAudioBubbleWidth; + } else if (currentBubbleWidth > maxAudioBubbleWidth) { + currentBubbleWidth = maxAudioBubbleWidth; + } + + return currentBubbleWidth; + } + + private void updateTime(long milliseconds) { + long seconds = TimeUtil.getSecondsByMilliseconds(milliseconds); + + if (seconds >= 0) { + durationLabel.setText(seconds + "\""); + } else { + durationLabel.setText(""); + } + } + + protected boolean isMessagePlaying(MessageAudioControl audioControl, IMMessage message) { + if (audioControl.getPlayingAudio() != null && audioControl.getPlayingAudio().isTheSame(message)) { + return true; + } else { + return false; + } + } + + private MessageAudioControl.AudioControlListener onPlayListener = new MessageAudioControl.AudioControlListener() { + + @Override + public void updatePlayingProgress(Playable playable, long curPosition) { + if (!isTheSame(message.getUuid())) { + return; + } + + if (curPosition > playable.getDuration()) { + return; + } + updateTime(curPosition); + } + + @Override + public void onAudioControllerReady(Playable playable) { + if (!isTheSame(message.getUuid())) { + return; + } + + play(); + } + + @Override + public void onEndPlay(Playable playable) { + if (!isTheSame(message.getUuid())) { + return; + } + + updateTime(playable.getDuration()); + + stop(); + } + + + }; + + private void play() { + if (animationView.getBackground() instanceof AnimationDrawable) { + AnimationDrawable animation = (AnimationDrawable) animationView.getBackground(); + animation.start(); + } + } + + private void stop() { + if (animationView.getBackground() instanceof AnimationDrawable) { + AnimationDrawable animation = (AnimationDrawable) animationView.getBackground(); + animation.stop(); + + endPlayAnim(); + } + } + + private void initPlayAnim() { + if (isReceivedMessage()) { + animationView.setBackgroundResource(R.drawable.nim_audio_animation_list_left); + } else { + animationView.setBackgroundResource(R.drawable.nim_audio_animation_list_right); + } + } + + private void endPlayAnim() { + if (isReceivedMessage()) { + animationView.setBackgroundResource(R.drawable.nim_audio_animation_list_left_3); + } else { + animationView.setBackgroundResource(R.drawable.nim_audio_animation_list_right_3); + } + } + + private boolean isTheSame(String uuid) { + String current = durationLabel.getTag().toString(); + return !TextUtils.isEmpty(uuid) && uuid.equals(current); + } + + @Override + protected int leftBackground() { + return 0; + } + + @Override + protected int rightBackground() { + return 0; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderBase.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderBase.java new file mode 100644 index 0000000..2e19dca --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderBase.java @@ -0,0 +1,967 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +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.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.blankj.utilcode.util.GsonUtils; +import com.bumptech.glide.Glide; +import com.facebook.drawee.view.SimpleDraweeView; +import com.flyco.roundview.RoundLinearLayout; +import com.flyco.roundview.RoundTextView; +import com.google.gson.Gson; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.business.session.module.list.MsgAdapter; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.fengliyan.tianlesue.model.chat.RecoverBean; +import com.fengliyan.tianlesue.model.settings.UserFrameBean; +import com.fengliyan.tianlesue.utils.NinePatchDrawableFactory; +import com.fengliyan.tianlesue.utils.PatchStretchBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.NIMSDK; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.opensource.svgaplayer.SVGAImageView; + +import java.io.File; +import java.util.Map; + +/** + * 会话窗口消息列表项的ViewHolder基类,负责每个消息项的外层框架,包括头像,昵称,发送/接收进度条,重发按钮等。
+ * 具体的消息展示项可继承该基类,然后完成具体消息内容展示即可。 + */ +public abstract class MsgViewHolderBase extends RecyclerViewHolder { + + public boolean showBorder(NimUserInfo userInfo, boolean isSelf, View targetView) { + boolean b = false; + if (userInfo != null) { + Map ext = userInfo.getExtensionMap(); + if (ext != null) { + //1 显示 + boolean hide_chat = true; + boolean hide_avatar = true; + boolean hide_man_avatar = true; + Object hide_chatObject = ext.get("hide_chat"); + Object hide_avatarObject = ext.get("hide_avatar"); + Object man_avatar_effect = ext.get("man_avatar_effect");//0 = 隐藏、1 = 显示 + if (hide_chatObject != null) { + hide_chat = (int) hide_chatObject == 0; + } + if (hide_avatarObject != null) { + hide_avatar = (int) hide_avatarObject == 0; + } + if (man_avatar_effect != null) { + hide_man_avatar = (int) man_avatar_effect == 0; + } + leftBorderImageView.setVisibility(View.INVISIBLE); + rightBorderImageView.setVisibility(View.INVISIBLE); + rightVipBorderIndicator.setVisibility(View.INVISIBLE); + leftVipBorderIndicator.setVisibility(View.INVISIBLE); + if (isSelf) { + if (!hide_avatar) { + rightBorderImageView.setVisibility(View.VISIBLE); + rightBorderImageView.setImageResource(R.mipmap.privilege_avatar_border); + rightVipBorderIndicator.setVisibility(View.VISIBLE); + rightVipBorderIndicator.setImageResource(R.drawable.bubble_vip_right); + rightVipBorderIndicator.setTranslationX(0); + } + if (hide_chat) { + targetView.setBackgroundResource(NimUIKitImpl.getOptions().messageRightBackground); + if (targetView instanceof TextView) { + ((TextView) targetView).setTextColor(Color.WHITE); + } + b = false; +// b = setBackground(targetView); + } else { + targetView.setBackgroundResource(NimUIKitImpl.getOptions().messageRightBackgroundVIP); + if (targetView instanceof TextView) { + ((TextView) targetView).setTextColor(Color.BLACK); + } + b = true; + } + if (!hide_man_avatar) { + rightBorderImageView.setVisibility(View.VISIBLE); + rightBorderImageView.setImageResource(R.mipmap.privilege_avatar_border_man); + rightVipBorderIndicator.setVisibility(View.VISIBLE); + rightVipBorderIndicator.setImageResource(R.drawable.bubble_vip_man); + rightVipBorderIndicator.setTranslationX(0); + rightVipBorderIndicator.setRotation(-15); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) rightVipBorderIndicator.getLayoutParams(); + params.setMargins(ScreenUtil.dip2px(-8), ScreenUtil.dip2px(4), 0, 0); + rightVipBorderIndicator.setLayoutParams(params); + targetView.setBackgroundResource(NimUIKitImpl.getOptions().messageRightBackgroundVIPMan); + if (targetView instanceof TextView) { + ((TextView) targetView).setTextColor(Color.BLACK); + } + b = true; + } + } else { + if (!hide_avatar) { + leftBorderImageView.setVisibility(View.VISIBLE); + leftBorderImageView.setImageResource(R.mipmap.privilege_avatar_border); + leftVipBorderIndicator.setVisibility(View.VISIBLE); + leftVipBorderIndicator.setImageResource(R.drawable.bubble_vip_left); + leftVipBorderIndicator.setTranslationX(0); + } + if (hide_chat) { + targetView.setBackgroundResource(NimUIKitImpl.getOptions().messageLeftBackground); + } else { + targetView.setBackgroundResource(NimUIKitImpl.getOptions().messageLeftBackgroundVip); + } + if (!hide_man_avatar) { + leftBorderImageView.setVisibility(View.VISIBLE); + leftBorderImageView.setImageResource(R.mipmap.privilege_avatar_border_man); + leftVipBorderIndicator.setVisibility(View.VISIBLE); + leftVipBorderIndicator.setImageResource(R.drawable.bubble_vip_man); + leftVipBorderIndicator.setTranslationX(0); + leftVipBorderIndicator.setRotation(15); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) leftVipBorderIndicator.getLayoutParams(); + params.setMargins(0, ScreenUtil.dip2px(4), ScreenUtil.dip2px(-8), 0); + leftVipBorderIndicator.setLayoutParams(params); + targetView.setBackgroundResource(NimUIKitImpl.getOptions().messageLeftBackgroundVipMan); + } + } + showGiftFrame(); +// if (targetView instanceof TextView) { + b = setBackground(targetView, b); +// } + return b; + } else { + leftBorderImageView.setVisibility(View.INVISIBLE); + rightBorderImageView.setVisibility(View.INVISIBLE); + rightVipBorderIndicator.setVisibility(View.INVISIBLE); + leftVipBorderIndicator.setVisibility(View.INVISIBLE); + showGiftFrame(); +// if (targetView instanceof TextView) { + setBackground(targetView, false); +// } + return false; + } + } else { + showGiftFrame(); +// if (targetView instanceof TextView) { + setBackground(targetView, false); +// } + } + return false; + } + + public MsgViewHolderBase(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + this.adapter = adapter; + } + + // basic + protected View view; + protected Context context; + protected BaseMultiItemFetchLoadAdapter adapter; + + // data + protected IMMessage message; + + // view + protected View alertButton; + protected TextView timeTextView; + protected ProgressBar progressBar; + protected TextView nameTextView; + protected FrameLayout contentContainer; + protected LinearLayout nameContainer; + protected TextView readReceiptTextView; + protected TextView ackMsgTextView; + + private HeadImageView avatarLeft; + private HeadImageView avatarRight; + public ImageView leftVipBorderIndicator; + public ImageView rightVipBorderIndicator; + public SimpleDraweeView leftBorderImageView; + public SimpleDraweeView rightBorderImageView; + public SVGAImageView svga_image_view1; + public SVGAImageView svga_image_view2; + public ImageView nameIconView; + + //tag显示扣除费用7的展示 + protected TextView mImageView; + + //聊天卡抵扣气泡 + protected RoundTextView mTvChatCardRight; + protected RoundTextView mTvChatCardLeft; + + //引用回复气泡 + protected RoundLinearLayout lin_chat_card_recover_right; + protected TextView tv_recover_name_right; + protected TextView tv_recover_content_right; + protected ImageView iv_recover_content_right; + protected RoundLinearLayout lin_chat_card_recover_left; + protected TextView tv_recover_name_left; + protected TextView tv_recover_content_left; + protected ImageView iv_recover_content_left; + + // contentContainerView的默认长按事件。如果子类需要不同的处理,可覆盖onItemLongClick方法 + // 但如果某些子控件会拦截触摸消息,导致contentContainer收不到长按事件,子控件也可在inflate时重新设置 + protected View.OnLongClickListener longClickListener; + + /// -- 以下接口可由子类覆盖或实现 + // 返回具体消息类型内容展示区域的layout res id + abstract protected int getContentResId(); + + // 在该接口中根据layout对各控件成员变量赋值 + abstract protected void inflateContentView(); + + // 在该接口操作BaseViewHolder中的数据,进行事件绑定,可选 + protected void bindHolder(BaseViewHolder holder) { + + } + + // 将消息数据项与内容的view进行绑定 + abstract protected void bindContentView(); + + // 内容区域点击事件响应处理。 + protected void onItemClick() { + } + + // 内容区域长按事件响应处理。该接口的优先级比adapter中有长按事件的处理监听高,当该接口返回为true时,adapter的长按事件监听不会被调用到。 + protected boolean onItemLongClick() { + return false; + } + + // 当是接收到的消息时,内容区域背景的drawable id + protected int leftBackground() { + return NimUIKitImpl.getOptions().messageLeftBackground; + } + + // 当是发送出去的消息时,内容区域背景的drawable id + protected int rightBackground() { + return NimUIKitImpl.getOptions().messageRightBackground; + } + + // 返回该消息是不是居中显示 + protected boolean isMiddleItem() { + return false; + } + + // 是否显示头像,默认为显示 + protected boolean isShowHeadImage() { + return true; + } + + // 是否显示时间,默认为显示 + protected boolean isShowTime() { + return true; + } + + // 是否显示气泡背景,默认为显示 + protected boolean isShowBubble() { + return true; + } + + // 是否显示已读,默认为显示 + protected boolean shouldDisplayReceipt() { + return true; + } + + /// -- 以下接口可由子类调用 + protected final MsgAdapter getMsgAdapter() { + return (MsgAdapter) adapter; + } + + protected boolean shouldDisplayNick() { + return message.getSessionType() == SessionTypeEnum.Team && isReceivedMessage() && !isMiddleItem(); + } + + + /** + * 下载附件/缩略图 + */ + protected void downloadAttachment() { + if (message.getAttachment() != null && message.getAttachment() instanceof FileAttachment) + NIMClient.getService(MsgService.class).downloadAttachment(message, true); + } + + // 设置FrameLayout子控件的gravity参数 + protected final void setGravity(View view, int gravity) { + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams(); + params.gravity = gravity; + } + + // 设置控件的长宽 + protected void setLayoutParams(int width, int height, View... views) { + for (View view : views) { + ViewGroup.LayoutParams maskParams = view.getLayoutParams(); + maskParams.width = width; + maskParams.height = height; + view.setLayoutParams(maskParams); + } + } + + // 根据layout id查找对应的控件 + protected T findViewById(int id) { + return (T) view.findViewById(id); + } + + // 判断消息方向,是否是接收到的消息 + protected boolean isReceivedMessage() { + return message.getDirect() == MsgDirectionEnum.In; + } + + /// -- 以下是基类实现代码 + @Override + public void convert(BaseViewHolder holder, IMMessage data, int position, boolean isScrolling) { + view = holder.getConvertView(); + context = holder.getContext(); + message = data; + + inflate(); + refresh(); + bindHolder(holder); + } + + protected final void inflate() { + timeTextView = findViewById(R.id.message_item_time); + avatarLeft = findViewById(R.id.message_item_portrait_left); + avatarRight = findViewById(R.id.message_item_portrait_right); + alertButton = findViewById(R.id.message_item_alert); + progressBar = findViewById(R.id.message_item_progress); + nameTextView = findViewById(R.id.message_item_nickname); + contentContainer = findViewById(R.id.message_item_content); + nameIconView = findViewById(R.id.message_item_name_icon); + nameContainer = findViewById(R.id.message_item_name_layout); + readReceiptTextView = findViewById(R.id.textViewAlreadyRead); + ackMsgTextView = findViewById(R.id.team_ack_msg); + leftVipBorderIndicator = findViewById(R.id.leftVipBorderIndicator); + rightVipBorderIndicator = findViewById(R.id.rightVipBorderIndicator); + leftBorderImageView = findViewById(R.id.leftBorderImageView); + rightBorderImageView = findViewById(R.id.rightBorderImageView); + svga_image_view1 = findViewById(R.id.svga_image_view1); + svga_image_view2 = findViewById(R.id.svga_image_view2); + mImageView = findViewById(R.id.coin_text); + mTvChatCardRight = findViewById(R.id.tv_chat_card_right); + mTvChatCardLeft = findViewById(R.id.tv_chat_card_left); + lin_chat_card_recover_right = findViewById(R.id.lin_chat_card_recover_right); + tv_recover_name_right = findViewById(R.id.tv_recover_name_right); + tv_recover_content_right = findViewById(R.id.tv_recover_content_right); + iv_recover_content_right = findViewById(R.id.iv_recover_content_right); + lin_chat_card_recover_left = findViewById(R.id.lin_chat_card_recover_left); + tv_recover_name_left = findViewById(R.id.tv_recover_name_left); + tv_recover_content_left = findViewById(R.id.tv_recover_content_left); + iv_recover_content_left = findViewById(R.id.iv_recover_content_left); + + // 这里只要inflate出来后加入一次即可 + if (contentContainer.getChildCount() == 0) { + View.inflate(view.getContext(), getContentResId(), contentContainer); + } + inflateContentView(); + } + + protected final void refresh() { + setHeadImageView(); + showAvatarFrame(); + showGiftFrame(); + setNameTextView(); + setTimeTextView(); + setStatus(); + setOnClickListener(); + setLongClickListener(); + setContent(); + if (SPUtils.getBoolean(context, ConsUser.USER_VIP, false)) { + if ((UserManager.getUserInfo().isWomen() && StrU.equals("0", SPUtils.getString(context, ConsUser.HIDE_READ_MSG))) || (!UserManager.getUserInfo().isWomen() && StrU.equals("1", SPUtils.getString(context, ConsUser.HIDE_READ_MSG)))) + setReadReceipt(); + } + setAckMsg(); + setCoinText(); + setRecoverView(); + + bindContentView(); + } + + void showLeftVipBorder() { + + } + + void showRightVipBorder() { + + } + + /** + * 显示扣除7费用的展示 + */ + private void setCoinText() { + if (isReceivedMessage()) { + mTvChatCardRight.setVisibility(View.GONE); + Map remoteExtension = message.getRemoteExtension(); + if (null != remoteExtension) { + if (null != remoteExtension.get("is_cut")) { + int data = (int) remoteExtension.get("is_cut"); + if (data == 1) { + if (remoteExtension.get("income_coin") != null) { + int income_coin = (int) remoteExtension.get("income_coin"); + if (income_coin != 0) { +// int coin = (int) (cut_coin * 0.65); + mImageView.setText("+" + income_coin); + mImageView.setVisibility(View.VISIBLE); + } else { + mImageView.setVisibility(View.GONE); + } + } + + } else { + mImageView.setVisibility(View.GONE); + } + } + if (null != remoteExtension.get("is_chat_card")) { + //是否使用聊天券:1 = 是、0 = 否 + int useChatCard = (int) remoteExtension.get("is_chat_card"); + if (useChatCard == 1) { + mTvChatCardLeft.setVisibility(View.VISIBLE); + } else { + mTvChatCardLeft.setVisibility(View.GONE); + } + } + } + } else { + mImageView.setVisibility(View.GONE); + mTvChatCardLeft.setVisibility(View.GONE); + Map remoteExtension = message.getRemoteExtension(); + if (null != remoteExtension) { + if (null != remoteExtension.get("is_chat_card")) { + //是否使用聊天券:1 = 是、0 = 否 + int useChatCard = (int) remoteExtension.get("is_chat_card"); + if (useChatCard == 1) { + mTvChatCardRight.setVisibility(View.VISIBLE); + } else { + mTvChatCardRight.setVisibility(View.GONE); + } + } + } + } + } + + /** + * 消息回复 + */ + private void setRecoverView() { + lin_chat_card_recover_left.setVisibility(View.GONE); + lin_chat_card_recover_right.setVisibility(View.GONE); + if (isReceivedMessage()) { + Map remoteExtension = message.getRemoteExtension(); + if (null != remoteExtension) { + if (null != remoteExtension.get("quote")) { + RecoverBean data = new Gson().fromJson(remoteExtension.get("quote").toString(), RecoverBean.class); + if (data != null) { + lin_chat_card_recover_left.setVisibility(View.VISIBLE); + tv_recover_name_left.setText(data.getNickName() + ":"); + if (data.getMessageType() == MsgTypeEnum.text.getValue()) { + tv_recover_content_left.setVisibility(View.VISIBLE); + tv_recover_content_left.setText(data.getValue()); + iv_recover_content_left.setVisibility(View.GONE); + } else if (data.getMessageType() == MsgTypeEnum.audio.getValue()) { + tv_recover_content_left.setVisibility(View.VISIBLE); + tv_recover_content_left.setText(data.getValue() + "\""); + iv_recover_content_left.setVisibility(View.VISIBLE); + iv_recover_content_left.setImageResource(R.drawable.ic_recover_audio); + ViewGroup.LayoutParams params = iv_recover_content_left.getLayoutParams(); + params.width = ViewGroup.LayoutParams.WRAP_CONTENT; + params.height = ViewGroup.LayoutParams.WRAP_CONTENT; + iv_recover_content_left.setLayoutParams(params); + } else if (data.getMessageType() == MsgTypeEnum.image.getValue() || data.getMessageType() == MsgTypeEnum.video.getValue()) { + tv_recover_content_left.setVisibility(View.GONE); + iv_recover_content_left.setVisibility(View.VISIBLE); + ViewGroup.LayoutParams params1 = iv_recover_content_left.getLayoutParams(); + params1.width = ScreenUtil.dip2px(30); + params1.height = ScreenUtil.dip2px(30); + iv_recover_content_left.setLayoutParams(params1); + Glide.with(context).asBitmap().error(R.drawable.nim_image_default).load(data.getValue()).into(iv_recover_content_left); + } + } else { + lin_chat_card_recover_left.setVisibility(View.GONE); + } + } + } + } else { + Map remoteExtension = message.getRemoteExtension(); + if (null != remoteExtension) { + if (null != remoteExtension.get("quote")) { + RecoverBean data = new Gson().fromJson(remoteExtension.get("quote").toString(), RecoverBean.class); + if (data != null) { + lin_chat_card_recover_right.setVisibility(View.VISIBLE); + tv_recover_name_right.setText(data.getNickName() + ":"); + if (data.getMessageType() == MsgTypeEnum.text.getValue()) { + tv_recover_content_right.setVisibility(View.VISIBLE); + tv_recover_content_right.setText(data.getValue()); + iv_recover_content_right.setVisibility(View.GONE); + } else if (data.getMessageType() == MsgTypeEnum.audio.getValue()) { + tv_recover_content_right.setVisibility(View.VISIBLE); + tv_recover_content_right.setText(data.getValue() + "\""); + iv_recover_content_right.setVisibility(View.VISIBLE); + iv_recover_content_right.setImageResource(R.drawable.ic_recover_audio); + ViewGroup.LayoutParams params = iv_recover_content_right.getLayoutParams(); + params.width = ViewGroup.LayoutParams.WRAP_CONTENT; + params.height = ViewGroup.LayoutParams.WRAP_CONTENT; + iv_recover_content_right.setLayoutParams(params); + } else if (data.getMessageType() == MsgTypeEnum.image.getValue() || data.getMessageType() == MsgTypeEnum.video.getValue()) { + tv_recover_content_right.setVisibility(View.GONE); + iv_recover_content_right.setVisibility(View.VISIBLE); + ViewGroup.LayoutParams params1 = iv_recover_content_right.getLayoutParams(); + params1.width = ScreenUtil.dip2px(30); + params1.height = ScreenUtil.dip2px(30); + iv_recover_content_right.setLayoutParams(params1); + Glide.with(context).asBitmap().error(R.drawable.nim_image_default).load(data.getValue()).into(iv_recover_content_right); + } + } else { + lin_chat_card_recover_right.setVisibility(View.GONE); + } + } + } + } + } + + public void refreshCurrentItem() { + if (message != null) { + refresh(); + } + } + + /** + * 设置时间显示 + */ + private void setTimeTextView() { + if (getMsgAdapter().needShowTime(message) && isShowTime()) { + timeTextView.setVisibility(View.VISIBLE); + } else { + timeTextView.setVisibility(View.GONE); + return; + } + + String text = TimeUtil.getTimeShowString(message.getTime(), false); + timeTextView.setText(text); + } + + /** + * 设置消息发送状态 + */ + private void setStatus() { + MsgStatusEnum status = message.getStatus(); + switch (status) { + case fail: + progressBar.setVisibility(View.GONE); + alertButton.setVisibility(View.VISIBLE); + break; + case sending: + progressBar.setVisibility(View.VISIBLE); + alertButton.setVisibility(View.GONE); + break; + default: + progressBar.setVisibility(View.GONE); + alertButton.setVisibility(View.GONE); + break; + } + } + + private void setHeadImageView() { + HeadImageView show = isReceivedMessage() ? avatarLeft : avatarRight; + HeadImageView hide = isReceivedMessage() ? avatarRight : avatarLeft; + hide.setVisibility(View.GONE); + if (!isShowHeadImage()) { + show.setVisibility(View.GONE); + return; + } + if (isMiddleItem()) { + show.setVisibility(View.GONE); + } else { + show.setVisibility(View.VISIBLE); + show.loadBuddyAvatar(message); + } + + } + + private void setOnClickListener() { + // 重发/重收按钮响应事件 + if (getMsgAdapter().getEventListener() != null) { + alertButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + getMsgAdapter().getEventListener().onFailedBtnClick(message); + } + }); + } + + // 内容区域点击事件响应, 相当于点击了整项 + contentContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onItemClick(); + } + }); + + // 头像点击事件响应 + if (NimUIKitImpl.getSessionListener() != null) { + View.OnClickListener portraitListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + NimUIKitImpl.getSessionListener().onAvatarClicked(context, message); + } + }; + + // tag,添加点击自己头像 + View.OnClickListener avatarRightListener = new View.OnClickListener() { + @Override + public void onClick(View view) { + NimUIKitImpl.getSessionListener().onAvatarRightClicked(context, message); + } + }; + avatarLeft.setOnClickListener(portraitListener); +// avatarRight.setOnClickListener(portraitListener); + avatarRight.setOnClickListener(avatarRightListener); + } + // 已读回执响应事件 + if (NimUIKitImpl.getSessionListener() != null) { + ackMsgTextView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + NimUIKitImpl.getSessionListener().onAckMsgClicked(context, message); + } + }); + } + } + + /** + * item长按事件监听 + */ + private void setLongClickListener() { + longClickListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + // 优先派发给自己处理, + if (!onItemLongClick()) { + if (getMsgAdapter().getEventListener() != null) { + getMsgAdapter().getEventListener().onViewHolderLongClick(contentContainer, view, message); + return true; + } + } + return false; + } + }; + // 消息长按事件响应处理 + contentContainer.setOnLongClickListener(longClickListener); + + // 头像长按事件响应处理 + if (NimUIKitImpl.getSessionListener() != null) { + View.OnLongClickListener longClickListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + NimUIKitImpl.getSessionListener().onAvatarLongClicked(context, message); + return true; + } + }; + avatarLeft.setOnLongClickListener(longClickListener); + avatarRight.setOnLongClickListener(longClickListener); + } + } + + private void setNameTextView() { + if (!shouldDisplayNick()) { + nameTextView.setVisibility(View.GONE); + return; + } + nameTextView.setVisibility(View.VISIBLE); + nameTextView.setText(getNameText()); + } + + + protected String getNameText() { + if (message.getSessionType() == SessionTypeEnum.Team) { + return TeamHelper.getTeamMemberDisplayName(message.getSessionId(), message.getFromAccount()); + } + return ""; + } + + private void setContent() { + if (!isShowBubble() && !isMiddleItem()) { + return; + } + + LinearLayout bodyContainer = (LinearLayout) view.findViewById(R.id.message_item_body); + RelativeLayout layout = view.findViewById(R.id.message_item_content_wapper); + // 调整container的位置 + int index = isReceivedMessage() ? 0 : 4; + if (bodyContainer.getChildAt(index) != layout) { + bodyContainer.removeView(layout); + bodyContainer.addView(layout, index); + } + + if (isMiddleItem()) { + setGravity(bodyContainer, Gravity.CENTER); + } else { + if (isReceivedMessage()) { + setGravity(bodyContainer, Gravity.LEFT); + if (null != message) { + MsgTypeEnum msgType = message.getMsgType(); + if (msgType.getValue() != 1 && msgType.getValue() != 3) { //图片和视频不显示背景 + contentContainer.setBackgroundResource(leftBackground()); + } + } + } else { + setGravity(bodyContainer, Gravity.RIGHT); + if (null != message) { + MsgTypeEnum msgType = message.getMsgType(); + if (msgType.getValue() != 1 && msgType.getValue() != 3) { + contentContainer.setBackgroundResource(rightBackground()); + } + } + } + } + } + + private void setReadReceipt() { + if (shouldDisplayReceipt() && !TextUtils.isEmpty(getMsgAdapter().getUuid()) && message.getUuid().equals(getMsgAdapter().getUuid())) { + readReceiptTextView.setText("已读"); + readReceiptTextView.setTextColor(Color.parseColor("#C2C2C2")); + readReceiptTextView.setVisibility(View.VISIBLE); + } else { + if (receiveReceiptCheck(message)) { + readReceiptTextView.setText("未读"); + readReceiptTextView.setTextColor(Color.parseColor("#60D975")); + readReceiptTextView.setVisibility(View.VISIBLE); + } else { + readReceiptTextView.setVisibility(View.GONE); + } + } + } + + private boolean receiveReceiptCheck(final IMMessage msg) { + return msg != null + && msg.getSessionType() == SessionTypeEnum.P2P + && msg.getDirect() == MsgDirectionEnum.Out + && msg.getMsgType() != MsgTypeEnum.tip + && msg.getMsgType() != MsgTypeEnum.notification + && !msg.isRemoteRead(); + } + + private void setAckMsg() { + if (message.getSessionType() == SessionTypeEnum.Team && message.needMsgAck()) { + if (isReceivedMessage()) { + // 收到的需要已读回执的消息,需要给个反馈 + ackMsgTextView.setVisibility(View.GONE); + NIMSDK.getTeamService().sendTeamMessageReceipt(message); + } else { + // 自己发的需要已读回执的消息,显示未读人数 + ackMsgTextView.setVisibility(View.VISIBLE); + if (message.getTeamMsgAckCount() == 0 && message.getTeamMsgUnAckCount() == 0) { + ackMsgTextView.setText("还未查看"); + } else { + ackMsgTextView.setText(message.getTeamMsgUnAckCount() + "人未读"); + } + } + } else { + ackMsgTextView.setVisibility(View.GONE); + } + } + + public void showAvatarFrame() { + NimUserInfo userInfo = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); + if (userInfo != null) { + Map ext = userInfo.getExtensionMap(); + if (ext != null) { + //1 显示 + boolean hide_avatar = true; + boolean hide_man_avatar = true; + Object hide_avatarObject = ext.get("hide_avatar"); + Object man_avatar_effect = ext.get("man_avatar_effect");//0 = 隐藏、1 = 显示 + if (hide_avatarObject != null) { + hide_avatar = (int) hide_avatarObject == 0; + } + if (man_avatar_effect != null) { + hide_man_avatar = (int) man_avatar_effect == 0; + } + leftBorderImageView.setVisibility(View.INVISIBLE); + rightBorderImageView.setVisibility(View.INVISIBLE); + if (!isReceivedMessage()) { + if (!hide_avatar) { + rightBorderImageView.setVisibility(View.VISIBLE); + rightBorderImageView.setImageResource(R.mipmap.privilege_avatar_border); + } + if (!hide_man_avatar) { + rightBorderImageView.setVisibility(View.VISIBLE); + rightBorderImageView.setImageResource(R.mipmap.privilege_avatar_border_man); + } + } else { + if (!hide_avatar) { + leftBorderImageView.setVisibility(View.VISIBLE); + leftBorderImageView.setImageResource(R.mipmap.privilege_avatar_border); + } + if (!hide_man_avatar) { + leftBorderImageView.setVisibility(View.VISIBLE); + leftBorderImageView.setImageResource(R.mipmap.privilege_avatar_border_man); + } + } + } else { + leftBorderImageView.setVisibility(View.INVISIBLE); + rightBorderImageView.setVisibility(View.INVISIBLE); + } + } + } + + private void showGiftFrame() { + if (!isShowHeadImage()) { + leftBorderImageView.setVisibility(View.INVISIBLE); + rightBorderImageView.setVisibility(View.INVISIBLE); + svga_image_view2.setVisibility(View.INVISIBLE); + rightVipBorderIndicator.setVisibility(View.INVISIBLE); + leftVipBorderIndicator.setVisibility(View.INVISIBLE); + svga_image_view1.setVisibility(View.INVISIBLE); + return; + } + String leftFrameStr = SPUtils.getString(context, ConsUser.USER_AVATAR_FRAME); + String rightFrameStr = SPUtils.getString(context, ConsUser.MY_AVATAR_FRAME); + if (!isReceivedMessage()) { + leftBorderImageView.setVisibility(View.GONE); + svga_image_view1.setVisibility(View.GONE); + if (!StrU.isEmpty(rightFrameStr)) { + UserFrameBean rightBean = GsonUtils.fromJson(rightFrameStr, UserFrameBean.class); + if (rightBean.getProfile_frame() != null) { +// if (!StrU.isEmpty(rightBean.getProfile_frame().getEffect())) { +// rightBorderImageView.setVisibility(View.VISIBLE); +// svga_image_view2.setVisibility(View.VISIBLE); +// ImageUtils.showSVGA(context, rightBean.getProfile_frame().getEffect(), svga_image_view2); +// } else { + if (!StrU.isEmpty(rightBean.getProfile_frame().getImg())) { + rightBorderImageView.setVisibility(View.VISIBLE); + rightBorderImageView.setImageURI(ConstUrl.IMAGE_URL + rightBean.getProfile_frame().getImg()); +// svga_image_view2.setVisibility(View.INVISIBLE); +// if (!StrU.isEmpty(rightBean.getProfile_frame().getEffect())) { +//// rightBorderImageView.setVisibility(View.VISIBLE); +// svga_image_view2.setVisibility(View.VISIBLE); +// ImageUtils.showSVGA(context, rightBean.getProfile_frame().getEffect(), svga_image_view2); +// } else { +// svga_image_view2.setVisibility(View.GONE); +// } + } else { + rightBorderImageView.setVisibility(View.GONE); + svga_image_view2.setVisibility(View.GONE); + } +// } + } else { + rightBorderImageView.setVisibility(View.GONE); + svga_image_view2.setVisibility(View.GONE); + } + } else { + rightBorderImageView.setVisibility(View.GONE); + svga_image_view2.setVisibility(View.GONE); + } + } else { + rightBorderImageView.setVisibility(View.GONE); + svga_image_view2.setVisibility(View.GONE); + if (!StrU.isEmpty(leftFrameStr)) { + UserFrameBean leftBean = GsonUtils.fromJson(leftFrameStr, UserFrameBean.class); + if (leftBean.getProfile_frame() != null) { +// if (!StrU.isEmpty(leftBean.getProfile_frame().getEffect())) { +// leftBorderImageView.setVisibility(View.VISIBLE); +// svga_image_view1.setVisibility(View.VISIBLE); +// ImageUtils.showSVGA(context, leftBean.getProfile_frame().getEffect(), svga_image_view1); +// } else { + if (!StrU.isEmpty(leftBean.getProfile_frame().getImg())) { + leftBorderImageView.setVisibility(View.VISIBLE); + leftBorderImageView.setImageURI(ConstUrl.IMAGE_URL + leftBean.getProfile_frame().getImg()); +// if (!StrU.isEmpty(leftBean.getProfile_frame().getEffect())) { +//// leftBorderImageView.setVisibility(View.VISIBLE); +// svga_image_view1.setVisibility(View.VISIBLE); +// ImageUtils.showSVGA(context, leftBean.getProfile_frame().getEffect(), svga_image_view1); +// } else { +// svga_image_view1.setVisibility(View.GONE); +// } + } + } +// } + } else { + leftBorderImageView.setVisibility(View.GONE); + svga_image_view1.setVisibility(View.GONE); + } + } + } + + public boolean setBackground(View targetView, boolean b) { + String leftFrameStr = SPUtils.getString(context, ConsUser.USER_AVATAR_FRAME); + String rightFrameStr = SPUtils.getString(context, ConsUser.MY_AVATAR_FRAME); + if (!isReceivedMessage()) { + if (!StrU.isEmpty(rightFrameStr)) { + UserFrameBean rightBean = GsonUtils.fromJson(rightFrameStr, UserFrameBean.class); + if (rightBean.getBubble_frame() != null) { + if (!StrU.isEmpty(rightBean.getBubble_frame().getImg())) { + rightVipBorderIndicator.setVisibility(View.GONE); + getStaticDrawableFromFile(context, rightBean.getBubble_frame().getImg(), targetView); + if (targetView instanceof TextView) { + ((TextView) targetView).setTextColor(Color.BLACK); + } + return true; + } else { + return b; + } + } else { + return b; + } + } else { + return b; + } + } else { + if (!StrU.isEmpty(leftFrameStr)) { + UserFrameBean leftBean = GsonUtils.fromJson(leftFrameStr, UserFrameBean.class); + if (leftBean.getBubble_frame() != null) { + if (!StrU.isEmpty(leftBean.getBubble_frame().getTo_img())) { + leftVipBorderIndicator.setVisibility(View.GONE); + getStaticDrawableFromFile(context, leftBean.getBubble_frame().getTo_img(), targetView); + } + } + } + return b; + } + } + + private void getStaticDrawableFromFile(Context context, String pngFileName, View targetView) { + String[] strings = pngFileName.split("/"); + String path = strings[strings.length - 1]; + File pngFile = new File(ConstUrl.DEFAULT_PATH, path); + if (!pngFile.exists()) { + return; + } + Drawable drawable = new NinePatchDrawableFactory(context) + .setDrawableFile(pngFile)//图片文件 + .setHorizontalStretchBean(new PatchStretchBean(24, 25))//水平拉伸区域 + .setVerticalStretchBean(new PatchStretchBean(16, 17))//垂直拉伸区域 + .setOriginSize(51, 36)//原始图片大小 +// .setPadding(new Rect(0, 0, 0, 0))//padding区域 + .setBitmapMapInDensity(1) + .setHorizontalMirror(false)//是否水平镜像,不是必须的 + .buildFromFile(); + targetView.setBackgroundResource(0); + targetView.setBackground(drawable); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderFactory.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderFactory.java new file mode 100644 index 0000000..ff8caf1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderFactory.java @@ -0,0 +1,89 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.attachment.LocationAttachment; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.attachment.NotificationAttachment; +import com.netease.nimlib.sdk.msg.attachment.VideoAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * 消息项展示ViewHolder工厂类。 + */ +public class MsgViewHolderFactory { + + private static HashMap, Class> viewHolders = new HashMap<>(); + + private static Class tipMsgViewHolder; + + static { + // built in + register(ImageAttachment.class, MsgViewHolderPicture.class); + register(AudioAttachment.class, MsgViewHolderAudio.class); + register(VideoAttachment.class, MsgViewHolderVideo.class); + register(LocationAttachment.class, MsgViewHolderLocation.class); + register(NotificationAttachment.class, MsgViewHolderNotification.class); + register(RobotAttachment.class, MsgViewHolderRobot.class); + } + + public static void register(Class attach, Class viewHolder) { + viewHolders.put(attach, viewHolder); + } + + public static void registerTipMsgViewHolder(Class viewHolder) { + tipMsgViewHolder = viewHolder; + } + + public static Class getViewHolderByType(IMMessage message) { + if (message.getMsgType() == MsgTypeEnum.text) { + return MsgViewHolderText.class; + } else if (message.getMsgType() == MsgTypeEnum.tip) { + return tipMsgViewHolder == null ? MsgViewHolderUnknown.class : tipMsgViewHolder; + } else { + Class viewHolder = null; + if (message.getAttachment() != null) { + Class clazz = message.getAttachment().getClass(); + while (viewHolder == null && clazz != null) { + viewHolder = viewHolders.get(clazz); + if (viewHolder == null) { + clazz = getSuperClass(clazz); + } + } + } + return viewHolder == null ? MsgViewHolderUnknown.class : viewHolder; + } + } + + private static Class getSuperClass(Class derived) { + Class sup = derived.getSuperclass(); + if (sup != null && MsgAttachment.class.isAssignableFrom(sup)) { + return sup; + } else { + for (Class itf : derived.getInterfaces()) { + if (MsgAttachment.class.isAssignableFrom(itf)) { + return itf; + } + } + } + return null; + } + + public static List> getAllViewHolders() { + List> list = new ArrayList<>(); + list.addAll(viewHolders.values()); + if (tipMsgViewHolder != null) { + list.add(tipMsgViewHolder); + } + list.add(MsgViewHolderUnknown.class); + list.add(MsgViewHolderText.class); + + return list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderLocation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderLocation.java new file mode 100644 index 0000000..b7c402b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderLocation.java @@ -0,0 +1,63 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.MsgThumbImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.msg.attachment.LocationAttachment; + +/** + * Created by zhoujianghua on 2015/8/7. + */ +public class MsgViewHolderLocation extends MsgViewHolderBase { + + public MsgViewHolderLocation(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + public MsgThumbImageView mapView; + + public TextView addressText; + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_location; + } + + @Override + protected void inflateContentView() { + mapView = (MsgThumbImageView) view.findViewById(R.id.message_item_location_image); + addressText = (TextView) view.findViewById(R.id.message_item_location_address); + } + + @Override + protected void bindContentView() { + final LocationAttachment location = (LocationAttachment) message.getAttachment(); + addressText.setText(location.getAddress()); + + int[] bound = ImageUtil.getBoundWithLength(getLocationDefEdge(), R.drawable.nim_location_bk, true); + int width = bound[0]; + int height = bound[1]; + + setLayoutParams(width, height, mapView); + setLayoutParams(width, (int) (0.38 * height), addressText); + + mapView.loadAsResource(R.drawable.nim_location_bk, R.drawable.nim_message_item_round_bg); + } + + @Override + protected void onItemClick() { + if (NimUIKitImpl.getLocationProvider() != null) { + LocationAttachment location = (LocationAttachment) message.getAttachment(); + NimUIKitImpl.getLocationProvider().openMap(context, location.getLongitude(), location.getLatitude(), location.getAddress()); + } + } + + public static int getLocationDefEdge() { + return (int) (0.5 * ScreenUtil.screenWidth); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderNotification.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderNotification.java new file mode 100644 index 0000000..365eff6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderNotification.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.text.method.LinkMovementMethod; +import android.text.style.ImageSpan; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.MoonUtil; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.TeamNotificationHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nim.uikit.R; + +public class MsgViewHolderNotification extends MsgViewHolderBase { + + public MsgViewHolderNotification(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + protected TextView notificationTextView; + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_notification; + } + + @Override + protected void inflateContentView() { + notificationTextView = (TextView) view.findViewById(R.id.message_item_notification_label); + } + + @Override + protected void bindContentView() { + handleTextNotification(getDisplayText()); + } + + protected String getDisplayText() { + return TeamNotificationHelper.getTeamNotificationText(message, message.getSessionId()); + } + + private void handleTextNotification(String text) { + MoonUtil.identifyFaceExpressionAndATags(context, notificationTextView, text, ImageSpan.ALIGN_BOTTOM); + notificationTextView.setMovementMethod(LinkMovementMethod.getInstance()); + } + + @Override + protected boolean isMiddleItem() { + return true; + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderPicture.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderPicture.java new file mode 100644 index 0000000..d7abe7e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderPicture.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.WatchMessagePictureActivity; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; + + +/** + * Created by zhoujianghua on 2015/8/4. + */ +public class MsgViewHolderPicture extends MsgViewHolderThumbBase { + + public MsgViewHolderPicture(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_picture; + } + + @Override + protected void onItemClick() { + WatchMessagePictureActivity.start(context, message); + } + + @Override + protected String thumbFromSourceFile(String path) { + return path; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderRobot.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderRobot.java new file mode 100644 index 0000000..e5158b5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderRobot.java @@ -0,0 +1,120 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.robot.model.RobotResponseContent; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot.RobotContentLinearLayout; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; + +import java.util.HashSet; +import java.util.Set; + +/** + * Created by hzchenkang on 2017/6/26. + */ + +public class MsgViewHolderRobot extends MsgViewHolderText implements RobotContentLinearLayout.ClickableChildView { + + // 机器人上行,即发送给机器人的消息展示 + private android.widget.LinearLayout containerIn; + + // 机器人下行,机器人回复消息展示 + private RobotContentLinearLayout robotContent; + + // 继续对话按钮 + private TextView holderFooterButton; + + // 机器人回复消息的视图中可点击按钮id + private Set onClickIds; + + public MsgViewHolderRobot(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_robot; + } + + @Override + protected void inflateContentView() { + containerIn = findViewById(R.id.robot_in); + robotContent = findViewById(R.id.robot_out); + robotContent.setBackgroundResource(NimUIKitImpl.getOptions().messageLeftBackground); + robotContent.setPadding(ScreenUtil.dip2px(15), ScreenUtil.dip2px(8), ScreenUtil.dip2px(10), ScreenUtil.dip2px(8)); + holderFooterButton = findViewById(R.id.tv_robot_session_continue); + holderFooterButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (getMsgAdapter().getEventListener() != null) { + getMsgAdapter().getEventListener().onFooterClick(MsgViewHolderRobot.this.message); + } + } + }); + bodyTextView = (TextView) containerIn.findViewById(R.id.nim_message_item_text_body); + } + + @Override + protected void bindContentView() { + onClickIds = new HashSet<>(); // for child to add + RobotAttachment attachment = (RobotAttachment) message.getAttachment(); + + if (attachment.isRobotSend()) { + // 下行 + containerIn.setVisibility(View.GONE); + robotContent.setVisibility(View.VISIBLE); + + // 正在聊天的不是机器人,则显示继续会话 + if (!message.getSessionId().equals(attachment.getFromRobotAccount())) { + holderFooterButton.setVisibility(View.VISIBLE); + } else { + holderFooterButton.setVisibility(View.GONE); + } + robotContent.bindContentView(this, new RobotResponseContent(attachment.getResponse())); + } else { + // 上行 + containerIn.setVisibility(View.VISIBLE); + robotContent.setVisibility(View.GONE); + holderFooterButton.setVisibility(View.GONE); + super.bindContentView(); + } + } + + @Override + protected String getNameText() { + RobotAttachment attachment = (RobotAttachment) message.getAttachment(); + if (attachment.isRobotSend()) { + String robotAccount = attachment.getFromRobotAccount(); + NimRobotInfo robotInfo = NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(robotAccount); + return robotInfo != null ? robotInfo.getName() : ""; + } + return ""; + } + + @Override + protected void bindHolder(BaseViewHolder holder) { + holder.getChildClickViewIds().clear(); + for (int id : onClickIds) { + holder.addOnClickListener(id); + } + + onClickIds.clear(); + } + + @Override + protected boolean shouldDisplayReceipt() { + return false; + } + + @Override + public void addClickableChildView(Class clazz, int id) { + onClickIds.add(id); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderText.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderText.java new file mode 100644 index 0000000..9664c96 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderText.java @@ -0,0 +1,99 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.graphics.Color; +import android.text.method.LinkMovementMethod; +import android.text.style.ImageSpan; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.MoonUtil; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +/** + * Created by zhoujianghua on 2015/8/4. + */ +public class MsgViewHolderText extends MsgViewHolderBase { + + protected TextView bodyTextView; +// protected TextView mImageView; + + public MsgViewHolderText(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_text; + } + + @Override + protected void inflateContentView() { + bodyTextView = findViewById(R.id.nim_message_item_text_body); +// mImageView = findViewById(R.id.coin_text); + } + + @Override + protected void bindContentView() { + layoutDirection(); + bodyTextView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onItemClick(); + } + }); + + MoonUtil.identifyFaceExpression(NimUIKit.getContext(), bodyTextView, getDisplayText(), ImageSpan.ALIGN_BOTTOM); + bodyTextView.setMovementMethod(LinkMovementMethod.getInstance()); + bodyTextView.setOnLongClickListener(longClickListener); + } + + private void layoutDirection() { + if (isReceivedMessage()) { + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); + bodyTextView.setBackgroundResource(NimUIKitImpl.getOptions().messageLeftBackground); + showBorder(info,false,bodyTextView); + bodyTextView.setTextColor(Color.BLACK); + bodyTextView.setPadding(ScreenUtil.dip2px(15), ScreenUtil.dip2px(8), ScreenUtil.dip2px(10), ScreenUtil.dip2px(8)); + +// Map remoteExtension = message.getRemoteExtension(); +// if (null != remoteExtension) { +// if (null != remoteExtension.get("is_cut")) { +// int data = (int) remoteExtension.get("is_cut"); +// if (data == 1) { +// mImageView.setVisibility(View.VISIBLE); +// }else { +// mImageView.setVisibility(View.GONE); +// } +// } +// } + } else { + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); + bodyTextView.setBackgroundResource(NimUIKitImpl.getOptions().messageRightBackground); + bodyTextView.setTextColor(Color.WHITE); + showBorder(info,true,bodyTextView); + bodyTextView.setPadding(ScreenUtil.dip2px(15), ScreenUtil.dip2px(8), ScreenUtil.dip2px(15), ScreenUtil.dip2px(8)); +// mImageView.setVisibility(View.GONE); + } + } + + @Override + protected int leftBackground() { + return 0; + } + + @Override + protected int rightBackground() { + return 0; + } + + protected String getDisplayText() { + return message.getContent(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderThumbBase.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderThumbBase.java new file mode 100644 index 0000000..5ea3050 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderThumbBase.java @@ -0,0 +1,131 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.MsgThumbImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.attachment.VideoAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; + +import java.io.File; + +/** + * Created by zhoujianghua on 2015/8/4. + */ +public abstract class MsgViewHolderThumbBase extends MsgViewHolderBase { + + public MsgViewHolderThumbBase(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + protected MsgThumbImageView thumbnail; + protected View progressCover; + protected TextView progressLabel; + + @Override + protected void inflateContentView() { + thumbnail = findViewById(R.id.message_item_thumb_thumbnail); + progressBar = findViewById(R.id.message_item_thumb_progress_bar); // 覆盖掉 + progressCover = findViewById(R.id.message_item_thumb_progress_cover); + progressLabel = findViewById(R.id.message_item_thumb_progress_text); + } + + @Override + protected void bindContentView() { + FileAttachment msgAttachment = (FileAttachment) message.getAttachment(); + String path = msgAttachment.getPath(); + String thumbPath = msgAttachment.getThumbPath(); + if (!TextUtils.isEmpty(thumbPath)) { + loadThumbnailImage(thumbPath, false, msgAttachment.getExtension()); + } else if (!TextUtils.isEmpty(path)) { + loadThumbnailImage(thumbFromSourceFile(path), true, msgAttachment.getExtension()); + } else { + loadThumbnailImage(null, false, msgAttachment.getExtension()); + if (message.getAttachStatus() == AttachStatusEnum.transferred + || message.getAttachStatus() == AttachStatusEnum.def) { + downloadAttachment(); + } + } + + refreshStatus(); + } + + private void refreshStatus() { + FileAttachment attachment = (FileAttachment) message.getAttachment(); + if (TextUtils.isEmpty(attachment.getPath()) && TextUtils.isEmpty(attachment.getThumbPath())) { + if (message.getAttachStatus() == AttachStatusEnum.fail || message.getStatus() == MsgStatusEnum.fail) { + alertButton.setVisibility(View.VISIBLE); + } else { + alertButton.setVisibility(View.GONE); + } + } + + if (message.getStatus() == MsgStatusEnum.sending + || (isReceivedMessage() && message.getAttachStatus() == AttachStatusEnum.transferring)) { + progressCover.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.VISIBLE); + progressLabel.setVisibility(View.VISIBLE); + progressLabel.setText(StringUtil.getPercentString(getMsgAdapter().getProgress(message))); + } else { + progressCover.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + progressLabel.setVisibility(View.GONE); + } + } + + private void loadThumbnailImage(String path, boolean isOriginal, String ext) { + setImageSize(path); + if (path != null) { + //thumbnail.loadAsPath(thumbPath, getImageMaxEdge(), getImageMaxEdge(), maskBg()); + thumbnail.loadAsPath(path, getImageMaxEdge(), getImageMaxEdge(), maskBg(), ext); + } else { + thumbnail.loadAsResource(R.drawable.nim_image_default, maskBg()); + } + } + + private void setImageSize(String thumbPath) { + int[] bounds = null; + if (thumbPath != null) { + bounds = BitmapDecoder.decodeBound(new File(thumbPath)); + } + if (bounds == null) { + if (message.getMsgType() == MsgTypeEnum.image) { + ImageAttachment attachment = (ImageAttachment) message.getAttachment(); + bounds = new int[]{attachment.getWidth(), attachment.getHeight()}; + } else if (message.getMsgType() == MsgTypeEnum.video) { + VideoAttachment attachment = (VideoAttachment) message.getAttachment(); + bounds = new int[]{attachment.getWidth(), attachment.getHeight()}; + } + } + + if (bounds != null) { + ImageUtil.ImageSize imageSize = ImageUtil.getThumbnailDisplaySize(bounds[0], bounds[1], getImageMaxEdge(), getImageMinEdge()); + setLayoutParams(imageSize.width, imageSize.height, thumbnail); + } + } + + private int maskBg() { + return R.drawable.nim_message_item_round_bg; + } + + public static int getImageMaxEdge() { + return (int) (165.0 / 320.0 * ScreenUtil.screenWidth); + } + + public static int getImageMinEdge() { + return (int) (76.0 / 320.0 * ScreenUtil.screenWidth); + } + + protected abstract String thumbFromSourceFile(String path); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderTip.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderTip.java new file mode 100644 index 0000000..6372ed7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderTip.java @@ -0,0 +1,86 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import android.text.TextUtils; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nim.uikit.R; + +/** + * Created by zhoujianghua on 2015/8/6. + */ +public class MsgViewHolderTip extends MsgViewHolderBase { + private static final String TAG = "MsgViewHolderTip"; + private TextView tv_tip_content; + + public MsgViewHolderTip(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_tip; + } + + @Override + protected void inflateContentView() { + tv_tip_content = view.findViewById(R.id.tv_tip_content); + } + + @Override + protected void bindContentView() { + if (!TextUtils.isEmpty(message.getContent())) { + tv_tip_content.setText(message.getContent()); + } + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderUnknown.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderUnknown.java new file mode 100644 index 0000000..6d939e6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderUnknown.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +/** + * Created by zhoujianghua on 2015/8/6. + */ +public class MsgViewHolderUnknown extends MsgViewHolderBase { + + public MsgViewHolderUnknown(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_unknown; + } + + @Override + protected boolean isShowHeadImage() { + if (message.getSessionType() == SessionTypeEnum.ChatRoom) { + return false; + } + return true; + } + + @Override + protected void inflateContentView() { + } + + @Override + protected void bindContentView() { + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderVideo.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderVideo.java new file mode 100644 index 0000000..ee7655d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/MsgViewHolderVideo.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.WatchVideoActivity; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.netease.nimlib.sdk.msg.attachment.VideoAttachment; + +/** + * Created by zhoujianghua on 2015/8/5. + */ +public class MsgViewHolderVideo extends MsgViewHolderThumbBase { + + public MsgViewHolderVideo(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.nim_message_item_video; + } + + @Override + protected void onItemClick() { + WatchVideoActivity.start(context, message); + } + + @Override + protected String thumbFromSourceFile(String path) { + VideoAttachment attachment = (VideoAttachment) message.getAttachment(); + String thumb = attachment.getThumbPathForSave(); + return BitmapDecoder.extractThumbnail(path, thumb) ? thumb : null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/media/DateViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/media/DateViewHolder.java new file mode 100644 index 0000000..4e2a0d6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/media/DateViewHolder.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.media; + +import android.view.View; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.netease.nim.uikit.R; + +/** + * Created by winnie on 2017/9/18. + */ + +public class DateViewHolder extends RecyclerView.ViewHolder { + + public TextView dateText; + + public DateViewHolder(View itemView) { + super(itemView); + dateText = (TextView) itemView.findViewById(R.id.date_tip); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/media/MediaViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/media/MediaViewHolder.java new file mode 100644 index 0000000..1674168 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/media/MediaViewHolder.java @@ -0,0 +1,25 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.media; + +import android.view.View; +import android.widget.ImageView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.netease.nim.uikit.R; + +/** + * Created by winnie on 2017/9/18. + */ + +public class MediaViewHolder extends RecyclerView.ViewHolder { + + public ImageView mediaImage; + + public ImageView playImage; + + public MediaViewHolder(View itemView) { + super(itemView); + mediaImage = (ImageView) itemView.findViewById(R.id.media_image); + playImage = (ImageView) itemView.findViewById(R.id.play_image); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotContentLinearLayout.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotContentLinearLayout.java new file mode 100644 index 0000000..a9e2d05 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotContentLinearLayout.java @@ -0,0 +1,151 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import androidx.annotation.Nullable; + +import com.fengliyan.tianlesue.im.uikit.business.robot.model.RobotBotContent; +import com.fengliyan.tianlesue.im.uikit.business.robot.model.RobotResponseContent; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.ImageElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.TextElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.LinkElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.TemplateRoot; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by hzchenkang on 2017/6/28. + * 适用于robot消息容器及LinkElement容器 + */ + +public class RobotContentLinearLayout extends LinearLayout { + + private List robotViews; + private RobotLinkViewStyle linkViewStyle; + + public RobotContentLinearLayout(Context context) { + this(context, null); + } + + public RobotContentLinearLayout(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + robotViews = new ArrayList<>(); + } + + public void setLinkStyle(RobotLinkViewStyle style) { + linkViewStyle = style; + } + + // 添加点击view 的id + public interface ClickableChildView { + void addClickableChildView(Class clazz, int id); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + for (RobotViewBase robotViewBase : robotViews) { + robotViewBase.onParentMeasured(getMeasuredWidth(), getMeasuredHeight()); + } + } + + /** + * 机器人消息容器 + */ + public void bindContentView(final ClickableChildView robot, final RobotResponseContent content) { + robotViews = new ArrayList<>(); + if (RobotResponseContent.FLAG_BOT.equals(content.getFlag())) { + // bot回复 + List botContents = content.getBotContents(); + for (RobotBotContent bot : botContents) { + if (RobotResponseContent.RES_TYPE_BOT_COMP.equals(bot.getType())) { + // 复合 + convertTemplateToViews(new TemplateRoot(bot.getBotMsg()), robot); + } else if (RobotResponseContent.RES_TYPE_BOT_TEXT.equals(bot.getType()) + || RobotResponseContent.RES_TYPE_BOT_QUICK.equals(bot.getType())) { + // 文本 + robotViews.add(RobotViewFactory.createRobotTextView(getContext(), null, bot.getBotMsg())); + } else if (RobotResponseContent.RES_TYPE_BOT_IMAGE.equals(bot.getType())) { + // 图片 + robotViews.add(RobotViewFactory.createRobotImageView(getContext(), null, bot.getBotMsg())); + } + } + } else if (RobotResponseContent.FLAG_FAQ.equals(content.getFlag())) { + // faq回复取匹配最高的 + String faqContent = content.getMaxScoreFaqContent(); + robotViews.add(RobotViewFactory.createRobotTextView(getContext(), null, faqContent)); + } + + bindChildContentViews(); + } + + private void convertTemplateToViews(final TemplateRoot template, final ClickableChildView robot) { + List robotLinearLayouts = template.getElements(); + if (robotLinearLayouts == null) { + return; + } + for (com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.LinearLayout robotLinearLayout : robotLinearLayouts) { + int size = robotLinearLayout.getElements().size(); + if (size <= 0) { + continue; + } + for (int i = 0; i < size; i++) { + RobotViewBase view; + Element e = robotLinearLayout.getElements().get(i); + if (e instanceof TextElement) { + view = RobotViewFactory.createRobotTextView(getContext(), (TextElement) e, null); + } else if (e instanceof ImageElement) { + view = RobotViewFactory.createRobotImageView(getContext(), (ImageElement) e, null); + } else if (e instanceof LinkElement) { + view = RobotViewFactory.createRobotLinkView(getContext(), (LinkElement) e); + if (linkViewStyle != null) { + ((RobotLinkView) view).setLinkViewStyle(linkViewStyle); + } + view.setId(GenerateViewID.generateViewId()); + robot.addClickableChildView(RobotLinkView.class, view.getId()); + } else { + continue; + } + + robotViews.add(view); + } + } + } + + private void bindChildContentViews() { + removeAllViews(); + for (RobotViewBase child : robotViews) { + LayoutParams params = child.createLayoutParams(); + if (params == null) { + params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + addView(child, params); + child.onBindContentView(); + } + } + + private static class GenerateViewID { + + private static final AtomicInteger sNextGeneratedId = new AtomicInteger(2000); + + static int generateViewId() { + for (; ; ) { + final int result = sNextGeneratedId.get(); + // aapt-generated IDs have the high byte nonzero; clamp to the range under that. + int newValue = result + 1; + if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. + if (sNextGeneratedId.compareAndSet(result, newValue)) { + return result; + } + } + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotImageView.java new file mode 100644 index 0000000..cf8f38a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotImageView.java @@ -0,0 +1,74 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot; + +import android.content.Context; +import android.text.TextUtils; +import android.view.ViewGroup; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.ImageElement; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.MsgThumbImageView; + + +/** + * Created by hzchenkang on 2017/6/26. + */ + +public class RobotImageView extends RobotViewBase { + + private MsgThumbImageView thumbnail; + + public RobotImageView(Context context, ImageElement element, String content) { + super(context, element, content); + } + + @Override + public int getResLayout() { + return R.layout.nim_message_robot_image; + } + + @Override + public void onInflate() { + thumbnail = (MsgThumbImageView) findViewById(R.id.message_item_thumb_thumbnail); + } + + @Override + public void onBindContentView() { + String url = content; + + if (element != null) { + url = element.getUrl(); + } + if (TextUtils.isEmpty(url)) { + return; + } + Glide.with(getContext()) + .asBitmap() + .load(url) + .apply(new RequestOptions() + .centerCrop() + .placeholder(R.drawable.nim_message_item_round_bg)) + .into(thumbnail); + } + + @Override + public void onParentMeasured(int width, int height) { + if (element != null) { + ViewGroup.LayoutParams params = thumbnail.getLayoutParams(); + +// if (element.isHeightUsePercent()) { +// params.height = element.getHeight() * height / 100; +// } else { +// params.height = element.getHeight(); +// } +// if (element.isWidthUsePercent()) { +// params.width = element.getWidth() * height / 100; +// } else { +// params.width = element.getWidth(); +// } +// thumbnail.setLayoutParams(params); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotLinkView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotLinkView.java new file mode 100644 index 0000000..71bf9f0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotLinkView.java @@ -0,0 +1,133 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot; + +import android.content.Context; +import android.view.Gravity; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.ImageElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.TextElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.LinkElement; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by hzchenkang on 2017/6/26. + */ + +public class RobotLinkView extends RobotViewBase { + + private LinearLayout container; + + private List robotViews; + + private RobotLinkViewStyle style; + + public RobotLinkView(Context context, LinkElement element) { + super(context, element, null); + robotViews = new ArrayList<>(); + initLinkViewStyle(); + applyViewStyle(); + } + + private void initLinkViewStyle() { + style = new RobotLinkViewStyle(); + style.setRobotTextColor(R.color.robot_link_element_text_blue); + style.setBackground(R.drawable.nim_robot_link_view_selector); + } + + public void setLinkViewStyle(RobotLinkViewStyle style) { + this.style = style; + applyViewStyle(); + } + + private void applyViewStyle() { + if (style != null) { + container.setBackgroundResource(style.getBackground()); + } + } + + @Override + public int getResLayout() { + return R.layout.nim_message_robot_link; + } + + @Override + public void onInflate() { + container = (LinearLayout) findViewById(R.id.robot_content_view); + } + + @Override + public void onBindContentView() { + if (element == null) { + return; + } + addChildViews(element); + bindChildContentViews(); + } + + @Override + public void onParentMeasured(int width, int height) { + + } + + @Override + public String getShowContent() { + if (element.getElements().size() == 1) { + Element e = element.getElements().get(0); + if (e instanceof TextElement) { + return ((TextElement) e).getContent(); + } + } + return "[复杂按钮模板触发消息]"; + } + + protected void addChildViews(LinkElement element) { + robotViews = new ArrayList<>(); + if (element == null) { + return; + } + List elements = element.getElements(); + for (Element e : elements) { + RobotViewBase v; + if (e instanceof TextElement) { + // 文本 + v = RobotViewFactory.createRobotTextView(getContext(), (TextElement) e, null); + if (style != null) { + ((RobotTextView) v).setTextColor(getContext().getResources().getColor((style.getRobotTextColor()))); + } + } else if (e instanceof ImageElement) { + // 图片 + v = RobotViewFactory.createRobotImageView(getContext(), (ImageElement) e, null); + } else { + continue; + } + robotViews.add(v); + } + } + + protected void bindChildContentViews() { + container.removeAllViews(); + for (RobotViewBase child : robotViews) { + LinearLayout.LayoutParams params = child.createLayoutParams(); + if (params == null) { + if (child instanceof RobotImageView) { + params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + int dp4 = ScreenUtil.dip2px(4); + params.setMargins(dp4, 2 * dp4, dp4, 2 * dp4); + } else { + params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + int dp4 = ScreenUtil.dip2px(4); + params.setMargins(dp4, 0, dp4, 0); + } + } + params.gravity = Gravity.CENTER_HORIZONTAL; + container.addView(child, params); + child.onBindContentView(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotLinkViewStyle.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotLinkViewStyle.java new file mode 100644 index 0000000..baa97d0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotLinkViewStyle.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot; + +/** + * Created by hzchenkang on 2017/9/4. + */ + +public class RobotLinkViewStyle { + private int robotTextColor; + private int background; + + public int getBackground() { + return background; + } + + public int getRobotTextColor() { + return robotTextColor; + } + + public void setBackground(int background) { + this.background = background; + } + + public void setRobotTextColor(int robotTextColor) { + this.robotTextColor = robotTextColor; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotTextView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotTextView.java new file mode 100644 index 0000000..09f621e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotTextView.java @@ -0,0 +1,69 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot; + +import android.content.Context; +import android.graphics.Color; +import android.text.TextUtils; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.TextElement; +import com.netease.nim.uikit.R; + +/** + * Created by hzchenkang on 2017/6/26. + */ + +public class RobotTextView extends RobotViewBase { + + private TextView textView; + + public RobotTextView(Context context, TextElement element, String content) { + super(context, element, content); + } + + @Override + public int getResLayout() { + return R.layout.nim_message_robot_text; + } + + @Override + public void onInflate() { + textView = (TextView) findViewById(R.id.tv_robot_text); + } + + private int color = -1; + + public void setTextColor(int colorRes) { + this.color = colorRes; + } + + @Override + public void onBindContentView() { + if (element != null) { + textView.setText(element.getContent()); + if (element.getColor() != null) { + try { + textView.setTextColor(Color.parseColor("#" + element.getColor())); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } else if (color != -1) { + textView.setTextColor(color); + } + } else if (!TextUtils.isEmpty(content)) { + textView.setText(content); + } + } + + @Override + public void onParentMeasured(int width, int height) { +// if (element != null) { +// ViewGroup.LayoutParams params = getLayoutParams(); +// if (element.isWidthUsePercent()) { +// params.width = element.getWidth() * width / 100; +// } else { +// params.width = element.getWidth(); +// } +// setLayoutParams(params); +// } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotViewBase.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotViewBase.java new file mode 100644 index 0000000..4a11ebf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotViewBase.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import androidx.annotation.Nullable; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.base.Element; + +/** + * Created by hzchenkang on 2017/6/26. + */ + +public abstract class RobotViewBase extends FrameLayout { + + protected T element; + + protected String content; + + public RobotViewBase(Context context, @Nullable AttributeSet attrs, T element, String content) { + super(context, attrs); + this.element = element; + this.content = content; + LayoutInflater.from(context).inflate(getResLayout(), this); + onInflate(); + } + + public RobotViewBase(Context context, T element, String content) { + this(context, null, element, content); + } + + public RobotViewBase(Context context) { + this(context, null, null); + } + + public T getElement() { + return element; + } + + protected abstract int getResLayout(); + + protected abstract void onInflate(); + + protected abstract void onBindContentView(); + + public abstract void onParentMeasured(int width, int height); + + protected LinearLayout.LayoutParams createLayoutParams() { + return null; + } + + public String getShowContent() { + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotViewFactory.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotViewFactory.java new file mode 100644 index 0000000..39a3d84 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/session/viewholder/robot/RobotViewFactory.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.business.session.viewholder.robot; + +import android.content.Context; + +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.ImageElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.element.TextElement; +import com.fengliyan.tianlesue.im.uikit.business.robot.parser.elements.group.LinkElement; + +/** + * Created by chenkang on 2017/6/29. + */ + +class RobotViewFactory { + + static RobotTextView createRobotTextView(Context context, TextElement element, String textMsg) { + return new RobotTextView(context, element, textMsg); + } + + static RobotImageView createRobotImageView(Context context, ImageElement element, String url) { + return new RobotImageView(context, element, url); + } + + static RobotLinkView createRobotLinkView(Context context, LinkElement element) { + return new RobotLinkView(context, element); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamAnnounceActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamAnnounceActivity.java new file mode 100644 index 0000000..fc5149f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamAnnounceActivity.java @@ -0,0 +1,300 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.view.View; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.ListView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.AnnouncementHelper; +import com.fengliyan.tianlesue.im.uikit.business.team.model.Announcement; +import com.fengliyan.tianlesue.im.uikit.business.team.viewholder.TeamAnnounceHolder; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapter; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapterDelegate; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.listview.ListViewUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.List; + +/** + * 群公告列表 + * Created by hzxuwen on 2015/3/18. + */ +public class AdvancedTeamAnnounceActivity extends UI implements TAdapterDelegate { + // constant + private final static String EXTRA_TID = "EXTRA_TID"; + private final static String EXTRA_AID = "EXTRA_AID"; + private final static int RES_ANNOUNCE_CREATE_CODE = 0x10; + public final static String RESULT_ANNOUNCE_DATA = "RESULT_ANNOUNCE_DATA"; + + // context + private Handler uiHandler; + + // data + private String teamId; + private String announceId; + private String announce; + + // view + private TextView announceTips; + private ListView announceListView; + private TAdapter mAdapter; + private List items; + + private boolean isMember = false; + + public static void start(Activity activity, String teamId) { + start(activity, teamId, null); + } + + public static void start(Activity activity, String teamId, String announceId) { + Intent intent = new Intent(); + intent.setClass(activity, AdvancedTeamAnnounceActivity.class); + intent.putExtra(EXTRA_TID, teamId); + if (announceId != null) { + intent.putExtra(EXTRA_AID, announceId); + } + activity.startActivity(intent); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_advanced_team_announce); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleId = R.string.team_annourcement; + setToolBar(R.id.toolbar, options); + + uiHandler = new Handler(getMainLooper()); + + parseIntentData(); + findViews(); + initActionbar(); + initAdapter(); + requestTeamData(); + requestMemberData(); + } + + /** + * ************************ TAdapterDelegate ************************** + */ + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public Class viewHolderAtPosition(int position) { + return TeamAnnounceHolder.class; + } + + @Override + public boolean enabled(int position) { + return false; + } + + /** + * ******************************初始化******************************* + */ + + private void parseIntentData() { + teamId = getIntent().getStringExtra(EXTRA_TID); + announceId = getIntent().getStringExtra(EXTRA_AID); + } + + private void findViews() { + announceListView = (ListView) findViewById(R.id.team_announce_listview); + announceTips = (TextView) findViewById(R.id.team_announce_tips); + } + + private void initActionbar() { + TextView toolbarView = findView(R.id.action_bar_right_clickable_textview); + toolbarView.setText(R.string.create); + toolbarView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AdvancedTeamCreateAnnounceActivity.startActivityForResult(AdvancedTeamAnnounceActivity.this, teamId, RES_ANNOUNCE_CREATE_CODE); + } + }); + } + + private void initAdapter() { + items = new ArrayList<>(); + mAdapter = new TAdapter(this, items, this); + announceListView.setAdapter(mAdapter); + announceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + + } + }); + announceListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }); + } + + private void requestTeamData() { + // 请求群信息 + Team t = NimUIKit.getTeamProvider().getTeamById(teamId); + if (t != null) { + updateAnnounceInfo(t); + } else { + NimUIKit.getTeamProvider().fetchTeamById(teamId, new SimpleCallback() { + @Override + public void onResult(boolean success, Team result, int code) { + if (success && result != null) { + updateAnnounceInfo(result); + } + } + }); + } + } + + private void requestMemberData() { + TeamMember teamMember = NimUIKit.getTeamProvider().getTeamMember(teamId, NimUIKit.getAccount()); + if (teamMember != null) { + updateTeamMember(teamMember); + } else { + // 请求群成员 + NimUIKit.getTeamProvider().fetchTeamMember(teamId, NimUIKit.getAccount(), new SimpleCallback() { + @Override + public void onResult(boolean success, TeamMember member, int code) { + if (success && member != null) { + updateTeamMember(member); + } + } + }); + } + } + + /** + * 更新公告信息 + * + * @param team 群 + */ + private void updateAnnounceInfo(Team team) { + if (team == null) { + ToastHelper.showToast(this, getString(R.string.team_not_exist)); + finish(); + } else { + announce = team.getAnnouncement(); + setAnnounceItem(); + } + } + + /** + * 判断是否是普通成员 + * + * @param teamMember 群成员 + */ + private void updateTeamMember(TeamMember teamMember) { + if (teamMember.getType() == TeamMemberType.Normal) { + isMember = true; + } + } + + /** + * 设置公告 + */ + private void setAnnounceItem() { + if (TextUtils.isEmpty(announce)) { + announceTips.setText(R.string.without_content); + announceTips.setVisibility(View.VISIBLE); + return; + } else { + announceTips.setVisibility(View.GONE); + } + + List list = AnnouncementHelper.getAnnouncements(teamId, announce, isMember ? 5 : Integer.MAX_VALUE); + if (list == null || list.isEmpty()) { + return; + } + + items.clear(); + items.addAll(list); + + mAdapter.notifyDataSetChanged(); + + jumpToIndex(list); + } + + /** + * 跳转到选中的公告 + * + * @param list 群公告列表 + */ + private void jumpToIndex(List list) { + if (TextUtils.isEmpty(announceId)) { + return; + } + + int jumpIndex = -1; + for (int i = 0; i < list.size(); i++) { + if (list.get(i).getId().equals(announceId)) { + jumpIndex = i; + break; + } + } + + if (jumpIndex >= 0) { + final int position = jumpIndex; + uiHandler.postDelayed(new Runnable() { + @Override + public void run() { + ListViewUtil.scrollToPosition(announceListView, position, 0); + } + }, 200); + } + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == Activity.RESULT_OK) { + switch (requestCode) { + case RES_ANNOUNCE_CREATE_CODE: + announceId = null; + items.clear(); + requestTeamData(); + break; + default: + break; + } + } + } + + @Override + public void onBackPressed() { + Intent intent = new Intent(); + intent.putExtra(RESULT_ANNOUNCE_DATA, announce); + setResult(Activity.RESULT_OK, intent); + finish(); + super.onBackPressed(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamCreateAnnounceActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamCreateAnnounceActivity.java new file mode 100644 index 0000000..2640db4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamCreateAnnounceActivity.java @@ -0,0 +1,172 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.text.InputFilter; +import android.text.TextUtils; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.AnnouncementHelper; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.DialogMaker; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.NetworkUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.constant.TeamFieldEnum; +import com.netease.nimlib.sdk.team.model.Team; + +/** + * 创建群公告界面 + * Created by hzxuwen on 2015/3/18. + */ +public class AdvancedTeamCreateAnnounceActivity extends UI { + + // constant + private final static String EXTRA_TID = "EXTRA_TID"; + + // data + private String teamId; + private String announce; + + // view + private EditText teamAnnounceTitle; + private EditText teamAnnounceContent; + private TextView toolbarView; + + public static void startActivityForResult(Activity activity, String teamId, int requestCode) { + Intent intent = new Intent(); + intent.setClass(activity, AdvancedTeamCreateAnnounceActivity.class); + intent.putExtra(EXTRA_TID, teamId); + activity.startActivityForResult(intent, requestCode); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_advanced_team_create_announce); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleId = R.string.team_annourcement; + setToolBar(R.id.toolbar, options); + + parseIntentData(); + findViews(); + initActionbar(); + } + + private void parseIntentData() { + teamId = getIntent().getStringExtra(EXTRA_TID); + } + + private void findViews() { + teamAnnounceTitle = (EditText) findViewById(R.id.team_announce_title); + teamAnnounceContent = (EditText) findViewById(R.id.team_announce_content); + teamAnnounceTitle.setFilters(new InputFilter[]{new InputFilter.LengthFilter(64)}); + teamAnnounceContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1024)}); + } + + private void initActionbar() { + toolbarView = findView(R.id.action_bar_right_clickable_textview); + toolbarView.setText(R.string.save); + toolbarView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + requestAnnounceData(); + } + }); + } + + private void requestAnnounceData() { + if (!NetworkUtil.isNetAvailable(this)) { + ToastHelper.showToast(this, R.string.network_is_not_available); + return; + } + + if (TextUtils.isEmpty(teamAnnounceTitle.getText().toString())) { + ToastHelper.showToast(AdvancedTeamCreateAnnounceActivity.this, R.string.team_announce_notice); + return; + } + + toolbarView.setEnabled(false); + // 请求群信息 + Team t = NimUIKit.getTeamProvider().getTeamById(teamId); + if (t != null) { + updateTeamData(t); + updateAnnounce(); + } else { + NimUIKit.getTeamProvider().fetchTeamById(teamId, new SimpleCallback() { + @Override + public void onResult(boolean success, Team result, int code) { + if (success && result != null) { + updateTeamData(result); + updateAnnounce(); + } else { + toolbarView.setEnabled(true); + } + } + }); + } + } + + /** + * 获得最新公告内容 + * + * @param team 群 + */ + private void updateTeamData(Team team) { + if (team == null) { + ToastHelper.showToast(this, getString(R.string.team_not_exist)); + showKeyboard(false); + finish(); + } else { + announce = team.getAnnouncement(); + } + } + + /** + * 创建公告更新到服务器 + */ + private void updateAnnounce() { + String announcement = AnnouncementHelper.makeAnnounceJson(announce, teamAnnounceTitle.getText().toString(), + teamAnnounceContent.getText().toString()); + NIMClient.getService(TeamService.class).updateTeam(teamId, TeamFieldEnum.Announcement, announcement).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + setResult(Activity.RESULT_OK); + showKeyboard(false); + finish(); + ToastHelper.showToast(AdvancedTeamCreateAnnounceActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + toolbarView.setEnabled(true); + ToastHelper.showToast(AdvancedTeamCreateAnnounceActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + toolbarView.setEnabled(true); + } + }); + } + + @Override + public void onBackPressed() { + showKeyboard(false); + super.onBackPressed(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamInfoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamInfoActivity.java new file mode 100644 index 0000000..dccc674 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamInfoActivity.java @@ -0,0 +1,1468 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.AbsListView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamMemberDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactIdFilter; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.activity.ContactSelectActivity; +import com.fengliyan.tianlesue.im.uikit.business.session.actions.PickImageAction; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.team.adapter.TeamMemberAdapter; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.AnnouncementHelper; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.business.team.model.Announcement; +import com.fengliyan.tianlesue.im.uikit.business.team.ui.TeamInfoGridView; +import com.fengliyan.tianlesue.im.uikit.business.team.viewholder.TeamMemberHolder; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapterDelegate; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.PickImageHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.DialogMaker; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.MenuDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nimlib.sdk.AbortableFuture; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.nos.NosService; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.constant.TeamBeInviteModeEnum; +import com.netease.nimlib.sdk.team.constant.TeamFieldEnum; +import com.netease.nimlib.sdk.team.constant.TeamInviteModeEnum; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.constant.TeamMessageNotifyTypeEnum; +import com.netease.nimlib.sdk.team.constant.TeamUpdateModeEnum; +import com.netease.nimlib.sdk.team.constant.VerifyTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * 高级群群资料页 + * Created by huangjun on 2015/3/17. + */ +public class AdvancedTeamInfoActivity extends UI implements + TAdapterDelegate, TeamMemberAdapter.AddMemberCallback, TeamMemberHolder.TeamMemberHolderEventListener { + + private static final int REQUEST_CODE_TRANSFER = 101; + private static final int REQUEST_CODE_MEMBER_LIST = 102; + private static final int REQUEST_CODE_CONTACT_SELECT = 103; + private static final int REQUEST_PICK_ICON = 104; + + private static final int ICON_TIME_OUT = 30000; + + // constant + private static final String TAG = "RegularTeamInfoActivity"; + + private static final String EXTRA_ID = "EXTRA_ID"; + public static final String RESULT_EXTRA_REASON = "RESULT_EXTRA_REASON"; + public static final String RESULT_EXTRA_REASON_QUIT = "RESULT_EXTRA_REASON_QUIT"; + public static final String RESULT_EXTRA_REASON_DISMISS = "RESULT_EXTRA_REASON_DISMISS"; + + private static final int TEAM_MEMBERS_SHOW_LIMIT = 5; + + // data + private TeamMemberAdapter adapter; + private String teamId; + private Team team; + private String creator; + private List memberAccounts; + private List members; + private List dataSource; + private MenuDialog dialog; + private MenuDialog authenDialog; + private MenuDialog inviteDialog; + private MenuDialog teamInfoUpdateDialog; + private MenuDialog teamInviteeDialog; + private MenuDialog teamNotifyDialog; + private List managerList; + private UserInfoObserver userInfoObserver; + private AbortableFuture uploadFuture; + + // view + private View headerLayout; + private HeadImageView teamHeadImage; + private TextView teamNameText; + private TextView teamIdText; + private TextView teamCreateTimeText; + + private TextView teamBusinessCard; // 我的群名片 + + private View layoutMime; + private View layoutTeamMember; + private TeamInfoGridView gridView; + private View layoutTeamName; + private View layoutTeamIntroduce; + private View layoutTeamAnnouncement; + private View layoutTeamExtension; + private View layoutAuthentication; + private View layoutNotificationConfig; + // 邀请他人权限 + private View layoutInvite; + private TextView inviteText; + // 群资料修改权限 + private View layoutInfoUpdate; + private TextView infoUpdateText; + // 被邀请人身份验证权限 + private View layoutInviteeAuthen; + private TextView inviteeAutenText; + + private TextView memberCountText; + private TextView introduceEdit; + private TextView announcementEdit; + private TextView extensionTextView; + private TextView authenticationText; + private TextView notificationConfigText; + + // state + private boolean isSelfAdmin = false; + private boolean isSelfManager = false; + + public static void start(Context context, String tid) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_ID, tid); + intent.setClass(context, AdvancedTeamInfoActivity.class); + context.startActivity(intent); + } + + /** + * ************************ TAdapterDelegate ************************** + */ + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public Class viewHolderAtPosition(int position) { + return TeamMemberHolder.class; + } + + @Override + public boolean enabled(int position) { + return false; + } + + /** + * ***************************** Life cycle ***************************** + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.nim_advanced_team_info_activity); + + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + + parseIntentData(); + findViews(); + initActionbar(); + initAdapter(); + loadTeamInfo(); + requestMembers(); + registerObservers(true); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (resultCode != Activity.RESULT_OK) { + return; + } + + switch (requestCode) { + case REQUEST_CODE_CONTACT_SELECT: + final ArrayList selected = data.getStringArrayListExtra(ContactSelectActivity.RESULT_DATA); + if (selected != null && !selected.isEmpty()) { + inviteMembers(selected); + } + break; + case REQUEST_CODE_TRANSFER: + final ArrayList target = data.getStringArrayListExtra(ContactSelectActivity.RESULT_DATA); + if (target != null && !target.isEmpty()) { + transferTeam(target.get(0)); + } + break; + case AdvancedTeamNicknameActivity.REQ_CODE_TEAM_NAME: + setBusinessCard(data.getStringExtra(AdvancedTeamNicknameActivity.EXTRA_NAME)); + break; + case AdvancedTeamMemberInfoActivity.REQ_CODE_REMOVE_MEMBER: + boolean isSetAdmin = data.getBooleanExtra(AdvancedTeamMemberInfoActivity.EXTRA_ISADMIN, false); + boolean isRemoveMember = data.getBooleanExtra(AdvancedTeamMemberInfoActivity.EXTRA_ISREMOVE, false); + String account = data.getStringExtra(EXTRA_ID); + refreshAdmin(isSetAdmin, account); + if (isRemoveMember) { + removeMember(account); + } + break; + case REQUEST_CODE_MEMBER_LIST: + boolean isMemberChange = data.getBooleanExtra(AdvancedTeamMemberActivity.EXTRA_DATA, false); + if (isMemberChange) { + requestMembers(); + } + break; + case REQUEST_PICK_ICON: + String path = data.getStringExtra(Extras.EXTRA_FILE_PATH); + updateTeamIcon(path); + break; + default: + break; + } + } + + @Override + public void onDestroy() { + if (dialog != null) { + dialog.dismiss(); + } + + if (authenDialog != null) { + authenDialog.dismiss(); + } + + registerObservers(false); + + super.onDestroy(); + } + + private void parseIntentData() { + teamId = getIntent().getStringExtra(EXTRA_ID); + } + + private void findViews() { + headerLayout = findViewById(R.id.team_info_header); + headerLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showSelector(R.string.set_head_image, REQUEST_PICK_ICON); + } + }); + + teamHeadImage = (HeadImageView) findViewById(R.id.team_head_image); + teamNameText = (TextView) findViewById(R.id.team_name); + teamIdText = (TextView) findViewById(R.id.team_id); + teamCreateTimeText = (TextView) findViewById(R.id.team_create_time); + + layoutMime = findViewById(R.id.team_mime_layout); + ((TextView) layoutMime.findViewById(R.id.item_title)).setText(R.string.my_team_card); + teamBusinessCard = (TextView) layoutMime.findViewById(R.id.item_detail); + layoutMime.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AdvancedTeamNicknameActivity.start(AdvancedTeamInfoActivity.this, teamBusinessCard.getText().toString()); + } + }); + + layoutTeamMember = findViewById(R.id.team_memeber_layout); + ((TextView) layoutTeamMember.findViewById(R.id.item_title)).setText(R.string.team_member); + memberCountText = (TextView) layoutTeamMember.findViewById(R.id.item_detail); + gridView = (TeamInfoGridView) findViewById(R.id.team_member_grid_view); + layoutTeamMember.setVisibility(View.GONE); + gridView.setVisibility(View.GONE); + memberCountText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AdvancedTeamMemberActivity.startActivityForResult(AdvancedTeamInfoActivity.this, teamId, REQUEST_CODE_MEMBER_LIST); + } + }); + + layoutTeamName = findViewById(R.id.team_name_layout); + ((TextView) layoutTeamName.findViewById(R.id.item_title)).setText(R.string.team_name); + layoutTeamName.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TeamPropertySettingActivity.start(AdvancedTeamInfoActivity.this, teamId, TeamFieldEnum.Name, team.getName()); + } + }); + + layoutTeamIntroduce = findViewById(R.id.team_introduce_layout); + ((TextView) layoutTeamIntroduce.findViewById(R.id.item_title)).setText(R.string.team_introduce); + introduceEdit = ((TextView) layoutTeamIntroduce.findViewById(R.id.item_detail)); + introduceEdit.setHint(R.string.team_introduce_hint); + layoutTeamIntroduce.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TeamPropertySettingActivity.start(AdvancedTeamInfoActivity.this, teamId, TeamFieldEnum.Introduce, team.getIntroduce()); + } + }); + + layoutTeamAnnouncement = findViewById(R.id.team_announcement_layout); + ((TextView) layoutTeamAnnouncement.findViewById(R.id.item_title)).setText(R.string.team_annourcement); + announcementEdit = ((TextView) layoutTeamAnnouncement.findViewById(R.id.item_detail)); + announcementEdit.setHint(R.string.team_announce_hint); + layoutTeamAnnouncement.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AdvancedTeamAnnounceActivity.start(AdvancedTeamInfoActivity.this, teamId); + } + }); + + layoutTeamExtension = findViewById(R.id.team_extension_layout); + ((TextView) layoutTeamExtension.findViewById(R.id.item_title)).setText(R.string.team_extension); + extensionTextView = ((TextView) layoutTeamExtension.findViewById(R.id.item_detail)); + extensionTextView.setHint(R.string.team_extension_hint); + layoutTeamExtension.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TeamPropertySettingActivity.start(AdvancedTeamInfoActivity.this, teamId, TeamFieldEnum.Extension, team.getExtension()); + } + }); + + // 群消息提醒设置 + initNotify(); + // 身份验证 + findLayoutAuthentication(); + // 邀请他人权限 + findLayoutInvite(); + // 群资料修改权限 + findLayoutInfoUpdate(); + // 被邀请人身份验证 + findLayoutInviteeAuthen(); + } + + /** + * 打开图片选择器 + */ + private void showSelector(int titleId, final int requestCode) { + PickImageHelper.PickImageOption option = new PickImageHelper.PickImageOption(); + option.titleResId = titleId; + option.multiSelect = false; + option.crop = true; + option.cropOutputImageWidth = 720; + option.cropOutputImageHeight = 720; + + PickImageHelper.pickImage(AdvancedTeamInfoActivity.this, requestCode, option); + } + + /** + * 群消息提醒设置 + */ + private void initNotify() { + layoutNotificationConfig = findViewById(R.id.team_notification_config_layout); + ((TextView) layoutNotificationConfig.findViewById(R.id.item_title)).setText(R.string.team_notification_config); + notificationConfigText = (TextView) layoutNotificationConfig.findViewById(R.id.item_detail); + layoutNotificationConfig.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showTeamNotifyMenu(); + } + }); + } + + + /** + * 身份验证布局初始化 + */ + private void findLayoutAuthentication() { + layoutAuthentication = findViewById(R.id.team_authentication_layout); + layoutAuthentication.setVisibility(View.GONE); + ((TextView) layoutAuthentication.findViewById(R.id.item_title)).setText(R.string.team_authentication); + authenticationText = ((TextView) layoutAuthentication.findViewById(R.id.item_detail)); + layoutAuthentication.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showTeamAuthenMenu(); + } + }); + } + + /** + * 邀请他人权限布局初始化 + */ + private void findLayoutInvite() { + layoutInvite = findViewById(R.id.team_invite_layout); + layoutInvite.setVisibility(View.GONE); + ((TextView) layoutInvite.findViewById(R.id.item_title)).setText(R.string.team_invite); + inviteText = ((TextView) layoutInvite.findViewById(R.id.item_detail)); + layoutInvite.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showTeamInviteMenu(); + } + }); + } + + /** + * 群资料修改权限布局初始化 + */ + private void findLayoutInfoUpdate() { + layoutInfoUpdate = findViewById(R.id.team_info_update_layout); + layoutInfoUpdate.setVisibility(View.GONE); + ((TextView) layoutInfoUpdate.findViewById(R.id.item_title)).setText(R.string.team_info_update); + infoUpdateText = ((TextView) layoutInfoUpdate.findViewById(R.id.item_detail)); + layoutInfoUpdate.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showTeamInfoUpdateMenu(); + } + }); + } + + + /** + * 被邀请人身份验证布局初始化 + */ + private void findLayoutInviteeAuthen() { + layoutInviteeAuthen = findViewById(R.id.team_invitee_authen_layout); + layoutInviteeAuthen.setVisibility(View.GONE); + ((TextView) layoutInviteeAuthen.findViewById(R.id.item_title)).setText(R.string.team_invitee_authentication); + inviteeAutenText = ((TextView) layoutInviteeAuthen.findViewById(R.id.item_detail)); + layoutInviteeAuthen.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showTeamInviteeAuthenMenu(); + } + }); + } + + private void initActionbar() { + TextView toolbarView = findView(R.id.action_bar_right_clickable_textview); + toolbarView.setText(R.string.menu); + toolbarView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showRegularTeamMenu(); + } + }); + } + + private void initAdapter() { + memberAccounts = new ArrayList<>(); + members = new ArrayList<>(); + dataSource = new ArrayList<>(); + managerList = new ArrayList<>(); + adapter = new TeamMemberAdapter(this, dataSource, this, null, this); + adapter.setEventListener(this); + + gridView.setSelector(R.color.transparent); + gridView.setOnScrollListener(new AbsListView.OnScrollListener() { + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + if (scrollState == 0) { + adapter.notifyDataSetChanged(); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }); + gridView.setAdapter(adapter); + } + + /** + * 初始化群组基本信息 + */ + private void loadTeamInfo() { + Team t = NimUIKit.getTeamProvider().getTeamById(teamId); + if (t != null) { + updateTeamInfo(t); + } else { + NimUIKit.getTeamProvider().fetchTeamById(teamId, new SimpleCallback() { + @Override + public void onResult(boolean success, Team result, int code) { + if (success && result != null) { + updateTeamInfo(result); + } else { + onGetTeamInfoFailed(); + } + } + }); + } + } + + private void onGetTeamInfoFailed() { + ToastHelper.showToast(this, getString(R.string.team_not_exist)); + finish(); + } + + /** + * 更新群信息 + * + * @param t + */ + private void updateTeamInfo(final Team t) { + this.team = t; + + if (team == null) { + ToastHelper.showToast(this, getString(R.string.team_not_exist)); + finish(); + return; + } else { + creator = team.getCreator(); + if (creator.equals(NimUIKit.getAccount())) { + isSelfAdmin = true; + } + + setTitle(team.getName()); + } + + teamHeadImage.loadTeamIconByTeam(team); + teamNameText.setText(team.getName()); + teamIdText.setText(team.getId()); + teamCreateTimeText.setText(TimeUtil.getTimeShowString(team.getCreateTime(), true)); + + ((TextView) layoutTeamName.findViewById(R.id.item_detail)).setText(team.getName()); + introduceEdit.setText(team.getIntroduce()); + extensionTextView.setText(team.getExtension()); + memberCountText.setText(String.format("共%d人", team.getMemberCount())); + + setAnnouncement(team.getAnnouncement()); + setAuthenticationText(team.getVerifyType()); + updateTeamNotifyText(team.getMessageNotifyType()); + updateInviteText(team.getTeamInviteMode()); + updateInfoUpateText(team.getTeamUpdateMode()); + updateBeInvitedText(team.getTeamBeInviteMode()); + } + + /** + * 更新群成员信息 + * + * @param m + */ + private void updateTeamMember(final List m) { + if (m != null && m.isEmpty()) { + return; + } + + updateTeamBusinessCard(m); + addTeamMembers(m, true); + } + + /** + * 更新我的群名片 + * + * @param m + */ + private void updateTeamBusinessCard(List m) { + for (TeamMember teamMember : m) { + if (teamMember != null && teamMember.getAccount().equals(NimUIKit.getAccount())) { + teamBusinessCard.setText(teamMember.getTeamNick() != null ? teamMember.getTeamNick() : ""); + } + } + } + + /** + * 添加群成员到列表 + * + * @param m 群成员列表 + * @param clear 是否清除 + */ + private void addTeamMembers(final List m, boolean clear) { + if (m == null || m.isEmpty()) { + return; + } + + isSelfManager = false; + isSelfAdmin = false; + + if (clear) { + this.members.clear(); + this.memberAccounts.clear(); + } + + // add + if (this.members.isEmpty()) { + this.members.addAll(m); + } else { + for (TeamMember tm : m) { + if (!this.memberAccounts.contains(tm.getAccount())) { + this.members.add(tm); + } + } + } + + // sort + Collections.sort(this.members, TeamHelper.teamMemberComparator); + + // accounts, manager, creator + this.memberAccounts.clear(); + this.managerList.clear(); + for (TeamMember tm : members) { + if (tm == null) { + continue; + } + if (tm.getType() == TeamMemberType.Manager) { + managerList.add(tm.getAccount()); + } + if (tm.getAccount().equals(NimUIKit.getAccount())) { + if (tm.getType() == TeamMemberType.Manager) { + isSelfManager = true; + } else if (tm.getType() == TeamMemberType.Owner) { + isSelfAdmin = true; + creator = NimUIKit.getAccount(); + } + } + this.memberAccounts.add(tm.getAccount()); + } + + updateAuthenView(); + updateTeamMemberDataSource(); + } + + /** + * 更新身份验证是否显示 + */ + private void updateAuthenView() { + if (isSelfAdmin || isSelfManager) { + layoutAuthentication.setVisibility(View.VISIBLE); + layoutInvite.setVisibility(View.VISIBLE); + layoutInfoUpdate.setVisibility(View.VISIBLE); + layoutInviteeAuthen.setVisibility(View.VISIBLE); + announcementEdit.setHint(R.string.without_content); + } else { + layoutAuthentication.setVisibility(View.GONE); + layoutInvite.setVisibility(View.GONE); + layoutInfoUpdate.setVisibility(View.GONE); + layoutInviteeAuthen.setVisibility(View.GONE); + introduceEdit.setHint(R.string.without_content); + announcementEdit.setHint(R.string.without_content); + } + } + + /** + * 更新成员信息 + */ + private void updateTeamMemberDataSource() { + if (members.size() > 0) { + gridView.setVisibility(View.VISIBLE); + layoutTeamMember.setVisibility(View.VISIBLE); + } else { + gridView.setVisibility(View.GONE); + layoutTeamMember.setVisibility(View.GONE); + return; + } + + dataSource.clear(); + + // add item + if (team.getTeamInviteMode() == TeamInviteModeEnum.All || isSelfAdmin || isSelfManager) { + dataSource.add(new TeamMemberAdapter.TeamMemberItem(TeamMemberAdapter.TeamMemberItemTag.ADD, null, null, + null)); + } + + // member item + int count = 0; + String identity = null; + for (String account : memberAccounts) { + int limit = TEAM_MEMBERS_SHOW_LIMIT; + if (team.getTeamInviteMode() == TeamInviteModeEnum.All || isSelfAdmin || isSelfManager) { + limit = TEAM_MEMBERS_SHOW_LIMIT - 1; + } + if (count < limit) { + identity = getIdentity(account); + dataSource.add(new TeamMemberAdapter.TeamMemberItem(TeamMemberAdapter.TeamMemberItemTag + .NORMAL, teamId, account, identity)); + } + count++; + } + + // refresh + adapter.notifyDataSetChanged(); + memberCountText.setText(String.format("共%d人", count)); + } + + private String getIdentity(String account) { + String identity; + if (creator.equals(account)) { + identity = TeamMemberHolder.OWNER; + } else if (managerList.contains(account)) { + identity = TeamMemberHolder.ADMIN; + } else { + identity = null; + } + return identity; + } + + /** + * *************************** 加载&变更数据源 ******************************** + */ + private void requestMembers() { + NimUIKit.getTeamProvider().fetchTeamMemberList(teamId, new SimpleCallback>() { + @Override + public void onResult(boolean success, List members, int code) { + if (success && members != null && !members.isEmpty()) { + updateTeamMember(members); + } + } + }); + } + + /** + * ************************** 群信息变更监听 ************************** + */ + /** + * 注册群信息更新监听 + * + * @param register + */ + private void registerObservers(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberObserver, register); + NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataObserver, register); + registerUserInfoChangedObserver(register); + } + + TeamMemberDataChangedObserver teamMemberObserver = new TeamMemberDataChangedObserver() { + + @Override + public void onUpdateTeamMember(List m) { + for (TeamMember mm : m) { + for (TeamMember member : members) { + if (mm.getAccount().equals(member.getAccount())) { + members.set(members.indexOf(member), mm); + break; + } + } + } + addTeamMembers(m, false); + } + + @Override + public void onRemoveTeamMember(List members) { + for (TeamMember member : members) { + removeMember(member.getAccount()); + } + } + }; + + TeamDataChangedObserver teamDataObserver = new TeamDataChangedObserver() { + @Override + public void onUpdateTeams(List teams) { + for (Team team : teams) { + if (team.getId().equals(teamId)) { + updateTeamInfo(team); + updateTeamMemberDataSource(); + break; + } + } + } + + @Override + public void onRemoveTeam(Team team) { + if (team.getId().equals(teamId)) { + AdvancedTeamInfoActivity.this.team = team; + finish(); + } + } + }; + + /** + * ******************************* Action ********************************* + */ + + /** + * 从联系人选择器发起邀请成员 + */ + @Override + public void onAddMember() { + ContactSelectActivity.Option option = TeamHelper.getContactSelectOption(memberAccounts); + NimUIKit.startContactSelector(AdvancedTeamInfoActivity.this, option, REQUEST_CODE_CONTACT_SELECT); + } + + /** + * 从联系人选择器选择群转移对象 + */ + private void onTransferTeam() { + if (memberAccounts.size() <= 1) { + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.team_transfer_without_member); + return; + } + + ContactSelectActivity.Option option = new ContactSelectActivity.Option(); + option.title = "选择群转移的对象"; + option.type = ContactSelectActivity.ContactSelectType.TEAM_MEMBER; + option.teamId = teamId; + option.multi = false; + option.maxSelectNum = 1; + ArrayList includeAccounts = new ArrayList<>(); + includeAccounts.addAll(memberAccounts); + option.itemFilter = new ContactIdFilter(includeAccounts, false); + NimUIKit.startContactSelector(this, option, REQUEST_CODE_TRANSFER); + dialog.dismiss(); + } + + /** + * 邀请群成员 + * + * @param accounts 邀请帐号 + */ + private void inviteMembers(ArrayList accounts) { + NIMClient.getService(TeamService.class).addMembers(teamId, accounts).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List failedAccounts) { + if (failedAccounts == null || failedAccounts.isEmpty()) { + ToastHelper.showToast(AdvancedTeamInfoActivity.this, "添加群成员成功"); + } else { + TeamHelper.onMemberTeamNumOverrun(failedAccounts, AdvancedTeamInfoActivity.this); + } + } + + @Override + public void onFailed(int code) { + if (code == ResponseCode.RES_TEAM_INVITE_SUCCESS) { + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.team_invite_members_success); + } else { + ToastHelper.showToast(AdvancedTeamInfoActivity.this, "invite members failed, code=" + code); + Log.e(TAG, "invite members failed, code=" + code); + } + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + + /** + * 转让群 + * + * @param account 转让的帐号 + */ + private void transferTeam(final String account) { + TeamMember member = NimUIKit.getTeamProvider().getTeamMember(teamId, account); + if (member == null) { + ToastHelper.showToast(AdvancedTeamInfoActivity.this, "成员不存在"); + return; + } + if (member.isMute()) { + ToastHelper.showToastLong(AdvancedTeamInfoActivity.this, "该成员已被禁言,请先取消禁言"); + return; + } + NIMClient.getService(TeamService.class).transferTeam(teamId, account, false) + .setCallback(new RequestCallback>() { + @Override + public void onSuccess(List members) { + creator = account; + updateTeamMember(NimUIKit.getTeamProvider().getTeamMemberList(teamId)); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.team_transfer_success); + } + + @Override + public void onFailed(int code) { + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.team_transfer_failed); + Log.e(TAG, "team transfer failed, code=" + code); + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + + /** + * 非群主退出群 + */ + private void quitTeam() { + DialogMaker.showProgressDialog(this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).quitTeam(teamId).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.quit_team_success); + setResult(Activity.RESULT_OK, new Intent().putExtra(RESULT_EXTRA_REASON, RESULT_EXTRA_REASON_QUIT)); + finish(); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.quit_team_failed); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 群主解散群(直接退出) + */ + private void dismissTeam() { + DialogMaker.showProgressDialog(this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).dismissTeam(teamId).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + setResult(Activity.RESULT_OK, new Intent().putExtra(RESULT_EXTRA_REASON, RESULT_EXTRA_REASON_DISMISS)); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.dismiss_team_success); + finish(); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.dismiss_team_failed); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * ******************************* Event ********************************* + */ + /** + * 显示菜单 + */ + private void showRegularTeamMenu() { + List btnNames = new ArrayList<>(); + if (isSelfAdmin) { + btnNames.add(getString(R.string.dismiss_team)); + btnNames.add(getString(R.string.transfer_team)); + btnNames.add(getString(R.string.cancel)); + } else { + btnNames.add(getString(R.string.quit_team)); + btnNames.add(getString(R.string.cancel)); + } + dialog = new MenuDialog(this, btnNames, new MenuDialog.MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + if (name.equals(getString(R.string.quit_team))) { + quitTeam(); + } else if (name.equals(getString(R.string.dismiss_team))) { + dismissTeam(); + } else if (name.equals(getString(R.string.transfer_team))) { + onTransferTeam(); + } + dialog.dismiss(); + } + }); + + dialog.show(); + } + + + private void showTeamNotifyMenu() { + if (teamNotifyDialog == null) { + List btnNames = TeamHelper.createNotifyMenuStrings(); + int type = team.getMessageNotifyType().getValue(); + teamNotifyDialog = new MenuDialog(AdvancedTeamInfoActivity.this, btnNames, type, 3, new MenuDialog + .MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + teamNotifyDialog.dismiss(); + + TeamMessageNotifyTypeEnum type = TeamHelper.getNotifyType(name); + if (type == null) { + return; + } + DialogMaker.showProgressDialog(AdvancedTeamInfoActivity.this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).muteTeam(teamId, type).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + updateTeamNotifyText(team.getMessageNotifyType()); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + teamNotifyDialog.undoLastSelect(); + Log.d(TAG, "muteTeam failed code:" + code); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + }); + } + teamNotifyDialog.show(); + } + + /** + * 显示验证菜单 + */ + private void showTeamAuthenMenu() { + if (authenDialog == null) { + List btnNames = TeamHelper.createAuthenMenuStrings(); + + int type = team.getVerifyType().getValue(); + authenDialog = new MenuDialog(AdvancedTeamInfoActivity.this, btnNames, type, 3, new MenuDialog + .MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + authenDialog.dismiss(); + + if (name.equals(getString(R.string.cancel))) { + return; // 取消不处理 + } + VerifyTypeEnum type = TeamHelper.getVerifyTypeEnum(name); + if (type != null) { + setAuthen(type); + } + + } + }); + } + authenDialog.show(); + } + + /** + * 显示邀请他人权限菜单 + */ + private void showTeamInviteMenu() { + if (inviteDialog == null) { + List btnNames = TeamHelper.createInviteMenuStrings(); + + int type = team.getTeamInviteMode().getValue(); + inviteDialog = new MenuDialog(AdvancedTeamInfoActivity.this, btnNames, type, 2, new MenuDialog + .MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + inviteDialog.dismiss(); + + if (name.equals(getString(R.string.cancel))) { + return; // 取消不处理 + } + TeamInviteModeEnum type = TeamHelper.getInviteModeEnum(name); + if (type != null) { + updateInviteMode(type); + } + } + }); + } + inviteDialog.show(); + } + + // 显示群资料修改权限菜单 + private void showTeamInfoUpdateMenu() { + if (teamInfoUpdateDialog == null) { + List btnNames = TeamHelper.createTeamInfoUpdateMenuStrings(); + + int type = team.getTeamUpdateMode().getValue(); + teamInfoUpdateDialog = new MenuDialog(AdvancedTeamInfoActivity.this, btnNames, type, 2, new MenuDialog + .MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + teamInfoUpdateDialog.dismiss(); + + if (name.equals(getString(R.string.cancel))) { + return; // 取消不处理 + } + TeamUpdateModeEnum type = TeamHelper.getUpdateModeEnum(name); + if (type != null) { + updateInfoUpdateMode(type); + } + } + }); + } + teamInfoUpdateDialog.show(); + } + + // 显示被邀请人身份验证菜单 + private void showTeamInviteeAuthenMenu() { + if (teamInviteeDialog == null) { + List btnNames = TeamHelper.createTeamInviteeAuthenMenuStrings(); + + int type = team.getTeamBeInviteMode().getValue(); + teamInviteeDialog = new MenuDialog(AdvancedTeamInfoActivity.this, btnNames, type, 2, new MenuDialog + .MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + teamInviteeDialog.dismiss(); + + if (name.equals(getString(R.string.cancel))) { + return; // 取消不处理 + } + TeamBeInviteModeEnum type = TeamHelper.getBeInvitedModeEnum(name); + if (type != null) { + updateBeInvitedMode(type); + } + } + }); + } + teamInviteeDialog.show(); + } + + + /** + * 设置我的名片 + * + * @param nickname 群昵称 + */ + private void setBusinessCard(final String nickname) { + DialogMaker.showProgressDialog(this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).updateMemberNick(teamId, NimUIKit.getAccount(), nickname).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + teamBusinessCard.setText(nickname); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + @Override + public void onHeadImageViewClick(String account) { + // 打开群成员信息详细页面 + AdvancedTeamMemberInfoActivity.startActivityForResult(AdvancedTeamInfoActivity.this, account, teamId); + } + + /** + * 设置群公告 + * + * @param announcement 群公告 + */ + private void setAnnouncement(String announcement) { + Announcement a = AnnouncementHelper.getLastAnnouncement(teamId, announcement); + if (a == null) { + announcementEdit.setText(""); + } else { + announcementEdit.setText(a.getTitle()); + } + } + + /** + * 设置验证模式 + * + * @param type 验证类型 + */ + private void setAuthen(final VerifyTypeEnum type) { + DialogMaker.showProgressDialog(this, getString(R.string.empty)); + NIMClient.getService(TeamService.class).updateTeam(teamId, TeamFieldEnum.VerifyType, type).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + setAuthenticationText(type); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + authenDialog.undoLastSelect(); // 撤销选择 + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 设置验证模式detail显示 + * + * @param type 验证类型 + */ + private void setAuthenticationText(VerifyTypeEnum type) { + authenticationText.setText(TeamHelper.getVerifyString(type)); + } + + private void updateTeamNotifyText(TeamMessageNotifyTypeEnum typeEnum) { + if (typeEnum == TeamMessageNotifyTypeEnum.All) { + notificationConfigText.setText(getString(R.string.team_notify_all)); + } else if (typeEnum == TeamMessageNotifyTypeEnum.Manager) { + notificationConfigText.setText(getString(R.string.team_notify_manager)); + } else if (typeEnum == TeamMessageNotifyTypeEnum.Mute) { + notificationConfigText.setText(getString(R.string.team_notify_mute)); + } + } + + /** + * 更新邀请他人权限 + * + * @param type 邀请他人类型 + */ + private void updateInviteMode(final TeamInviteModeEnum type) { + DialogMaker.showProgressDialog(this, getString(R.string.empty)); + NIMClient.getService(TeamService.class).updateTeam(teamId, TeamFieldEnum.InviteMode, type).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + updateInviteText(type); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + inviteDialog.undoLastSelect(); // 撤销选择 + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 更新邀请他人detail显示 + * + * @param type 邀请他人类型 + */ + private void updateInviteText(TeamInviteModeEnum type) { + inviteText.setText(TeamHelper.getInviteModeString(type)); + } + + /** + * 更新群资料修改权限 + * + * @param type 群资料修改类型 + */ + private void updateInfoUpdateMode(final TeamUpdateModeEnum type) { + DialogMaker.showProgressDialog(this, getString(R.string.empty)); + NIMClient.getService(TeamService.class).updateTeam(teamId, TeamFieldEnum.TeamUpdateMode, type).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + updateInfoUpateText(type); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + teamInfoUpdateDialog.undoLastSelect(); // 撤销选择 + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 更新群资料修改detail显示 + * + * @param type 群资料修改类型 + */ + private void updateInfoUpateText(TeamUpdateModeEnum type) { + infoUpdateText.setText(TeamHelper.getInfoUpdateModeString(type)); + } + + /** + * 更新被邀请人权限 + * + * @param type 被邀请人类型 + */ + private void updateBeInvitedMode(final TeamBeInviteModeEnum type) { + DialogMaker.showProgressDialog(this, getString(R.string.empty)); + NIMClient.getService(TeamService.class).updateTeam(teamId, TeamFieldEnum.BeInviteMode, type).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + updateBeInvitedText(type); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + teamInviteeDialog.undoLastSelect(); // 撤销选择 + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 更新被邀请人detail显示 + * + * @param type 被邀请人类型 + */ + private void updateBeInvitedText(TeamBeInviteModeEnum type) { + inviteeAutenText.setText(TeamHelper.getBeInvitedModeString(type)); + } + + /** + * 移除群成员成功后,删除列表中的群成员 + * + * @param account 被删除成员帐号 + */ + private void removeMember(String account) { + if (TextUtils.isEmpty(account)) { + return; + } + + memberAccounts.remove(account); + + for (TeamMember m : members) { + if (m.getAccount().equals(account)) { + members.remove(m); + break; + } + } + + memberCountText.setText(String.format("共%d人", members.size())); + + for (TeamMemberAdapter.TeamMemberItem item : dataSource) { + if (item.getAccount() != null && item.getAccount().equals(account)) { + dataSource.remove(item); + break; + } + } + adapter.notifyDataSetChanged(); + } + + /** + * 是否设置了管理员刷新界面 + * + * @param isSetAdmin + * @param account + */ + private void refreshAdmin(boolean isSetAdmin, String account) { + if (isSetAdmin) { + if (managerList.contains(account)) { + return; + } + managerList.add(account); + updateTeamMemberDataSource(); + } else { + if (managerList.contains(account)) { + managerList.remove(account); + updateTeamMemberDataSource(); + } + } + } + + private void registerUserInfoChangedObserver(boolean register) { + if (register) { + if (userInfoObserver == null) { + userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + adapter.notifyDataSetChanged(); + } + }; + } + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, true); + } else { + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, false); + } + } + + /** + * 更新头像 + */ + private void updateTeamIcon(final String path) { + if (TextUtils.isEmpty(path)) { + return; + } + + File file = new File(path); + if (file == null) { + return; + } + DialogMaker.showProgressDialog(this, null, null, true, new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + cancelUpload(R.string.team_update_cancel); + } + }).setCanceledOnTouchOutside(true); + + LogUtil.i(TAG, "start upload icon, local file path=" + file.getAbsolutePath()); + new Handler().postDelayed(outimeTask, ICON_TIME_OUT); + uploadFuture = NIMClient.getService(NosService.class).upload(file, PickImageAction.MIME_JPEG); + uploadFuture.setCallback(new RequestCallbackWrapper() { + @Override + public void onResult(int code, String url, Throwable exception) { + if (code == ResponseCode.RES_SUCCESS && !TextUtils.isEmpty(url)) { + LogUtil.i(TAG, "upload icon success, url =" + url); + + NIMClient.getService(TeamService.class).updateTeam(teamId, TeamFieldEnum.ICON, url).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.update_success); + onUpdateDone(); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); // 更新资料 + } else { + ToastHelper.showToast(AdvancedTeamInfoActivity.this, R.string.team_update_failed); + onUpdateDone(); + } + } + }); + } + + private void cancelUpload(int resId) { + if (uploadFuture != null) { + uploadFuture.abort(); + ToastHelper.showToast(AdvancedTeamInfoActivity.this, resId); + onUpdateDone(); + } + } + + private Runnable outimeTask = new Runnable() { + @Override + public void run() { + cancelUpload(R.string.team_update_failed); + } + }; + + private void onUpdateDone() { + uploadFuture = null; + DialogMaker.dismissProgressDialog(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamMemberActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamMemberActivity.java new file mode 100644 index 0000000..9c94465 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamMemberActivity.java @@ -0,0 +1,373 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.MotionEvent; +import android.view.View; +import android.widget.AbsListView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.team.adapter.TeamMemberAdapter; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.business.team.ui.TeamInfoGridView; +import com.fengliyan.tianlesue.im.uikit.business.team.viewholder.TeamMemberHolder; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapterDelegate; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * 群成员列表界面 + * Created by hzxuwen on 2015/3/17. + */ +public class AdvancedTeamMemberActivity extends UI implements TAdapterDelegate, + TeamMemberAdapter.RemoveMemberCallback, TeamMemberAdapter.AddMemberCallback, TeamMemberHolder.TeamMemberHolderEventListener { + + // constant + private static final String EXTRA_ID = "EXTRA_ID"; + public static final String EXTRA_DATA = "EXTRA_DATA"; + + // data source + private String teamId; + private List members; + private TeamMemberAdapter adapter; + private List memberAccounts; + private List dataSource; + private String creator; + private List managerList; + + // state + private boolean isSelfAdmin = false; + private boolean isSelfManager = false; + private boolean isMemberChange = false; + private UserInfoObserver userInfoObserver; + + public static void startActivityForResult(Activity context, String tid, int resCode) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_ID, tid); + intent.setClass(context, AdvancedTeamMemberActivity.class); + context.startActivityForResult(intent, resCode); + } + + /** + * *********************************lifeCycle******************************************* + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_team_member_grid_layout); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleId = R.string.team_member; + setToolBar(R.id.toolbar, options); + + parseIntentData(); + loadTeamInfo(); + initAdapter(); + findViews(); + registerUserInfoChangedObserver(true); + requestData(); + } + + @Override + public void onDestroy() { + registerUserInfoChangedObserver(false); + + super.onDestroy(); + } + + @Override + public void onBackPressed() { + Intent intent = new Intent(); + intent.putExtra(EXTRA_DATA, isMemberChange); + setResult(Activity.RESULT_OK, intent); + super.onBackPressed(); + } + + private void parseIntentData() { + teamId = getIntent().getStringExtra(EXTRA_ID); + } + + private void loadTeamInfo() { + Team team = NimUIKit.getTeamProvider().getTeamById(teamId); + if (team != null) { + creator = team.getCreator(); + } + } + + private void findViews() { + TeamInfoGridView teamInfoGridView = (TeamInfoGridView) findViewById(R.id.team_member_grid); + teamInfoGridView.setSelector(R.color.transparent); + teamInfoGridView.setOnScrollListener(new AbsListView.OnScrollListener() { + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + if (scrollState == 0) { + adapter.notifyDataSetChanged(); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }); + teamInfoGridView.setOnTouchListener(new View.OnTouchListener() { + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP && adapter.getMode() == TeamMemberAdapter.Mode.DELETE) { + adapter.setMode(TeamMemberAdapter.Mode.NORMAL); + adapter.notifyDataSetChanged(); + return true; + } + return false; + } + }); + teamInfoGridView.setAdapter(adapter); + } + + private void initAdapter() { + memberAccounts = new ArrayList<>(); + members = new ArrayList<>(); + dataSource = new ArrayList<>(); + managerList = new ArrayList<>(); + adapter = new TeamMemberAdapter(this, dataSource, this, this, this); + adapter.setEventListener(this); + } + + private void updateTeamMember(final List members) { + if (members != null && members.isEmpty()) { + return; + } + + addTeamMembers(members, true); + } + + private void addTeamMembers(final List m, boolean clear) { + if (m == null || m.isEmpty()) { + return; + } + + if (clear) { + this.members.clear(); + this.memberAccounts.clear(); + } + + // add + if (this.members.isEmpty()) { + this.members.addAll(m); + } else { + for (TeamMember tm : m) { + if (!this.memberAccounts.contains(tm.getAccount())) { + this.members.add(tm); + } + } + } + + // sort + Collections.sort(this.members, TeamHelper.teamMemberComparator); + + // accounts, manager, creator + this.memberAccounts.clear(); + this.managerList.clear(); + for (TeamMember tm : members) { + initManagerList(tm); + if (tm.getAccount().equals(NimUIKit.getAccount())) { + if (tm.getType() == TeamMemberType.Manager) { + isSelfManager = true; + } else if (tm.getType() == TeamMemberType.Owner) { + isSelfAdmin = true; + creator = NimUIKit.getAccount(); + } + } + this.memberAccounts.add(tm.getAccount()); + } + + updateTeamMemberDataSource(); + } + + /** + * 初始化管理员列表 + * + * @param tm 群成员 + */ + private void initManagerList(TeamMember tm) { + if (tm.getType() == TeamMemberType.Manager) { + managerList.add(tm.getAccount()); + } + } + + private void updateTeamMemberDataSource() { + if (members.size() <= 0) { + return; + } + + dataSource.clear(); + + // member item + for (String account : memberAccounts) { + dataSource.add(new TeamMemberAdapter.TeamMemberItem(TeamMemberAdapter.TeamMemberItemTag + .NORMAL, teamId, account, initMemberIdentity(account))); + } + + // refresh + adapter.notifyDataSetChanged(); + } + + /** + * 初始化成员身份 + * + * @param account 帐号 + * @return String + */ + private String initMemberIdentity(String account) { + String identity; + if (creator.equals(account)) { + identity = TeamMemberHolder.OWNER; + } else if (managerList.contains(account)) { + identity = TeamMemberHolder.ADMIN; + } else { + identity = null; + } + return identity; + } + + + @Override + public void onAddMember() { + + } + + @Override + public void onRemoveMember(String account) { + + } + + /** + * ******************************加载数据******************************* + */ + private void requestData() { + NimUIKit.getTeamProvider().fetchTeamMemberList(teamId, new SimpleCallback>() { + @Override + public void onResult(boolean success, List members, int code) { + if (success && members != null && !members.isEmpty()) { + updateTeamMember(members); + } + } + }); + } + + /** + * ************************ TAdapterDelegate ************************** + */ + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public Class viewHolderAtPosition(int position) { + return TeamMemberHolder.class; + } + + @Override + public boolean enabled(int position) { + return false; + } + + @Override + public void onHeadImageViewClick(String account) { + AdvancedTeamMemberInfoActivity.startActivityForResult(AdvancedTeamMemberActivity.this, account, teamId); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == Activity.RESULT_OK) { + switch (requestCode) { + case AdvancedTeamMemberInfoActivity.REQ_CODE_REMOVE_MEMBER: + boolean isSetAdmin = data.getBooleanExtra(AdvancedTeamMemberInfoActivity.EXTRA_ISADMIN, false); + boolean isRemoveMember = data.getBooleanExtra(AdvancedTeamMemberInfoActivity.EXTRA_ISREMOVE, false); + String account = data.getStringExtra(EXTRA_ID); + refreshAdmin(isSetAdmin, account); + if (isRemoveMember) { + removeMember(account); + } + break; + default: + break; + } + } + } + + /** + * 移除群成员成功后,删除列表中的群成员 + */ + private void removeMember(String account) { + if (TextUtils.isEmpty(account)) { + return; + } + for (TeamMemberAdapter.TeamMemberItem item : dataSource) { + if (item.getAccount() != null && item.getAccount().equals(account)) { + dataSource.remove(item); + isMemberChange = true; + break; + } + } + adapter.notifyDataSetChanged(); + } + + /** + * 是否设置了管理员刷新界面 + * + * @param isSetAdmin 是否设置为管理员 + * @param account 帐号 + */ + private void refreshAdmin(boolean isSetAdmin, String account) { + if (isSetAdmin) { + if (managerList.contains(account)) { + return; + } + managerList.add(account); + isMemberChange = true; + updateTeamMemberDataSource(); + } else { + if (managerList.contains(account)) { + managerList.remove(account); + isMemberChange = true; + updateTeamMemberDataSource(); + } + } + } + + private void registerUserInfoChangedObserver(boolean register) { + if (register) { + if (userInfoObserver == null) { + userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + adapter.notifyDataSetChanged(); + } + }; + } + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, true); + } else { + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, false); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamMemberInfoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamMemberInfoActivity.java new file mode 100644 index 0000000..3533f69 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamMemberInfoActivity.java @@ -0,0 +1,602 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.DialogMaker; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialogHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.MenuDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.fengliyan.tianlesue.im.uikit.common.ui.widget.SwitchButton; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.NetworkUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 群成员详细信息界面 + * Created by hzxuwen on 2015/3/19. + */ +public class AdvancedTeamMemberInfoActivity extends UI implements View.OnClickListener { + + private static final String TAG = AdvancedTeamMemberInfoActivity.class.getSimpleName(); + // constant + public static final int REQ_CODE_REMOVE_MEMBER = 11; + private static final String EXTRA_ID = "EXTRA_ID"; + private static final String EXTRA_TID = "EXTRA_TID"; + public static final String EXTRA_ISADMIN = "EXTRA_ISADMIN"; + public static final String EXTRA_ISREMOVE = "EXTRA_ISREMOVE"; + private final String KEY_MUTE_MSG = "mute_msg"; + + // data + private String account; + private String teamId; + private TeamMember viewMember; + private boolean isSetAdmin; + private Map toggleStateMap; + + // view + private HeadImageView headImageView; + private TextView memberName; + private TextView nickName; + private TextView identity; + private View nickContainer; + private Button removeBtn; + private View identityContainer; + private MenuDialog setAdminDialog; + private MenuDialog cancelAdminDialog; + private ViewGroup toggleLayout; + private SwitchButton muteSwitch; + + // state + private boolean isSelfCreator = false; + private boolean isSelfManager = false; + + public static void startActivityForResult(Activity activity, String account, String tid) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_ID, account); + intent.putExtra(EXTRA_TID, tid); + intent.setClass(activity, AdvancedTeamMemberInfoActivity.class); + activity.startActivityForResult(intent, REQ_CODE_REMOVE_MEMBER); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_advanced_team_member_info_layout); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleId = R.string.team_member_info; + setToolBar(R.id.toolbar, options); + + parseIntentData(); + + findViews(); + + loadMemberInfo(); + + initMemberInfo(); + } + + @Override + public void onResume() { + super.onResume(); + + updateToggleView(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (setAdminDialog != null) { + setAdminDialog.dismiss(); + } + if (cancelAdminDialog != null) { + cancelAdminDialog.dismiss(); + } + } + + private void parseIntentData() { + account = getIntent().getStringExtra(EXTRA_ID); + teamId = getIntent().getStringExtra(EXTRA_TID); + } + + private void findViews() { + nickContainer = findViewById(R.id.nickname_container); + identityContainer = findViewById(R.id.identity_container); + headImageView = (HeadImageView) findViewById(R.id.team_member_head_view); + memberName = (TextView) findViewById(R.id.team_member_name); + nickName = (TextView) findViewById(R.id.team_nickname_detail); + identity = (TextView) findViewById(R.id.team_member_identity_detail); + removeBtn = (Button) findViewById(R.id.team_remove_member); + toggleLayout = findView(R.id.toggle_layout); + setClickListener(); + } + + private void setClickListener() { + nickContainer.setOnClickListener(this); + identityContainer.setOnClickListener(this); + removeBtn.setOnClickListener(this); + } + + private void updateToggleView() { + if (getMyPermission()) { + boolean isMute = NimUIKit.getTeamProvider().getTeamMember(teamId, account).isMute(); + if (muteSwitch == null) { + addToggleBtn(isMute); + } else { + setToggleBtn(muteSwitch, isMute); + } + Log.i(TAG, "mute=" + isMute); + } + + } + + // 判断是否有权限 + private boolean getMyPermission() { + if (isSelfCreator && !isSelf(account)) { + return true; + } + if (isSelfManager && identity.getText().toString().equals(getString(R.string.team_member))) { + return true; + } + return false; + } + + private void addToggleBtn(boolean isMute) { + muteSwitch = addToggleItemView(KEY_MUTE_MSG, R.string.mute_msg, isMute); + } + + private void setToggleBtn(SwitchButton btn, boolean isChecked) { + btn.setCheck(isChecked); + } + + private SwitchButton addToggleItemView(String key, int titleResId, boolean initState) { + ViewGroup vp = (ViewGroup) getLayoutInflater().inflate(R.layout.nim_user_profile_toggle_item, null); + ViewGroup.LayoutParams vlp = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.isetting_item_height)); + vp.setLayoutParams(vlp); + + TextView titleText = ((TextView) vp.findViewById(R.id.user_profile_title)); + titleText.setText(titleResId); + + SwitchButton switchButton = (SwitchButton) vp.findViewById(R.id.user_profile_toggle); + switchButton.setCheck(initState); + switchButton.setOnChangedListener(onChangedListener); + switchButton.setTag(key); + + toggleLayout.addView(vp); + + if (toggleStateMap == null) { + toggleStateMap = new HashMap<>(); + } + toggleStateMap.put(key, initState); + return switchButton; + } + + private SwitchButton.OnChangedListener onChangedListener = new SwitchButton.OnChangedListener() { + @Override + public void OnChanged(View v, final boolean checkState) { + final String key = (String) v.getTag(); + if (!NetworkUtil.isNetAvailable(AdvancedTeamMemberInfoActivity.this)) { + ToastHelper.showToast(AdvancedTeamMemberInfoActivity.this, R.string.network_is_not_available); + if (key.equals(KEY_MUTE_MSG)) { + muteSwitch.setCheck(!checkState); + } + return; + } + + updateStateMap(checkState, key); + + if (key.equals(KEY_MUTE_MSG)) { + NIMClient.getService(TeamService.class).muteTeamMember(teamId, account, checkState).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + if (checkState) { + ToastHelper.showToast(AdvancedTeamMemberInfoActivity.this, "群禁言成功"); + } else { + ToastHelper.showToast(AdvancedTeamMemberInfoActivity.this, "取消群禁言成功"); + } + } + + @Override + public void onFailed(int code) { + if (code == 408) { + ToastHelper.showToast(AdvancedTeamMemberInfoActivity.this, R.string.network_is_not_available); + } else { + ToastHelper.showToast(AdvancedTeamMemberInfoActivity.this, "on failed:" + code); + } + updateStateMap(!checkState, key); + muteSwitch.setCheck(!checkState); + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + } + }; + + private void updateStateMap(boolean checkState, String key) { + if (toggleStateMap.containsKey(key)) { + toggleStateMap.put(key, checkState); // update state + Log.i(TAG, "toggle " + key + "to " + checkState); + } + } + + private void loadMemberInfo() { + viewMember = NimUIKit.getTeamProvider().getTeamMember(teamId, account); + if (viewMember != null) { + updateMemberInfo(); + } else { + requestMemberInfo(); + } + } + + /** + * 查询群成员的信息 + */ + private void requestMemberInfo() { + NimUIKit.getTeamProvider().fetchTeamMember(teamId, account, new SimpleCallback() { + @Override + public void onResult(boolean success, TeamMember member, int code) { + if (success && member != null) { + viewMember = member; + updateMemberInfo(); + } + } + }); + } + + private void initMemberInfo() { + memberName.setText(UserInfoHelper.getUserDisplayName(account)); + headImageView.loadBuddyAvatar(account); + } + + private void updateMemberInfo() { + updateMemberIdentity(); + updateMemberNickname(); + updateSelfIndentity(); + updateRemoveBtn(); + } + + /** + * 更新群成员的身份 + */ + private void updateMemberIdentity() { + if (viewMember.getType() == TeamMemberType.Manager) { + identity.setText(R.string.team_admin); + isSetAdmin = true; + } else { + isSetAdmin = false; + if (viewMember.getType() == TeamMemberType.Owner) { + identity.setText(R.string.team_creator); + } else { + identity.setText(R.string.team_member); + } + } + } + + /** + * 更新成员群昵称 + */ + private void updateMemberNickname() { + nickName.setText(viewMember.getTeamNick() != null ? viewMember.getTeamNick() : getString(R.string.team_nickname_none)); + } + + /** + * 获得用户自己的身份 + */ + private void updateSelfIndentity() { + TeamMember selfTeamMember = NimUIKit.getTeamProvider().getTeamMember(teamId, NimUIKit.getAccount()); + if (selfTeamMember == null) { + return; + } + if (selfTeamMember.getType() == TeamMemberType.Manager) { + isSelfManager = true; + } else if (selfTeamMember.getType() == TeamMemberType.Owner) { + isSelfCreator = true; + } + } + + /** + * 更新是否显移除本群按钮 + */ + private void updateRemoveBtn() { + if (viewMember.getAccount().equals(NimUIKit.getAccount())) { + removeBtn.setVisibility(View.GONE); + } else { + if (isSelfCreator) { + removeBtn.setVisibility(View.VISIBLE); + } else if (isSelfManager) { + if (viewMember.getType() == TeamMemberType.Owner) { + removeBtn.setVisibility(View.GONE); + } else if (viewMember.getType() == TeamMemberType.Normal) { + removeBtn.setVisibility(View.VISIBLE); + } else { + removeBtn.setVisibility(View.GONE); + } + } else { + removeBtn.setVisibility(View.GONE); + } + + } + } + + /** + * 更新群昵称 + * + * @param name + */ + private void setNickname(final String name) { + DialogMaker.showProgressDialog(this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).updateMemberNick(teamId, account, name).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + nickName.setText(name != null ? name : getString(R.string.team_nickname_none)); + ToastHelper.showToast(AdvancedTeamMemberInfoActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(AdvancedTeamMemberInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + @Override + public void onClick(View v) { + int i = v.getId(); + if (i == R.id.nickname_container) { + editNickname(); + + } else if (i == R.id.identity_container) { + showManagerButton(); + + } else if (i == R.id.team_remove_member) { + showConfirmButton(); + + } else { + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == AdvancedTeamNicknameActivity.REQ_CODE_TEAM_NAME && resultCode == Activity.RESULT_OK) { + final String teamName = data.getStringExtra(AdvancedTeamNicknameActivity.EXTRA_NAME); + setNickname(teamName); + } + } + + /** + * 设置群昵称 + */ + private void editNickname() { + if (isSelfCreator || isSelf(account)) { + AdvancedTeamNicknameActivity.start(AdvancedTeamMemberInfoActivity.this, nickName.getText().toString()); + } else if (isSelfManager && identity.getText().toString().equals(getString(R.string.team_member))) { + AdvancedTeamNicknameActivity.start(AdvancedTeamMemberInfoActivity.this, nickName.getText().toString()); + } else { + ToastHelper.showToast(this, R.string.no_permission); + } + } + + + /** + * 显示设置管理员按钮 + */ + private void showManagerButton() { + if (identity.getText().toString().equals(getString(R.string.team_creator))) { + return; + } + if (!isSelfCreator) + return; + + if (identity.getText().toString().equals(getString(R.string.team_member))) { + switchManagerButton(true); + } else { + switchManagerButton(false); + } + } + + /** + * 转换设置或取消管理员按钮 + * + * @param isSet 是否设置 + */ + private void switchManagerButton(boolean isSet) { + if (isSet) { + if (setAdminDialog == null) { + List btnNames = new ArrayList<>(); + btnNames.add(getString(R.string.set_team_admin)); + setAdminDialog = new MenuDialog(this, btnNames, new MenuDialog.MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + addManagers(); + setAdminDialog.dismiss(); + } + }); + } + setAdminDialog.show(); + } else { + if (cancelAdminDialog == null) { + List btnNames = new ArrayList<>(); + btnNames.add(getString(R.string.cancel_team_admin)); + cancelAdminDialog = new MenuDialog(this, btnNames, new MenuDialog.MenuDialogOnButtonClickListener() { + @Override + public void onButtonClick(String name) { + removeManagers(); + cancelAdminDialog.dismiss(); + } + }); + } + cancelAdminDialog.show(); + } + } + + /** + * 添加管理员权限 + */ + private void addManagers() { + DialogMaker.showProgressDialog(this, getString(R.string.empty)); + ArrayList accountList = new ArrayList<>(); + accountList.add(account); + NIMClient.getService(TeamService.class).addManagers(teamId, accountList).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List managers) { + DialogMaker.dismissProgressDialog(); + identity.setText(R.string.team_admin); + ToastHelper.showToastLong(AdvancedTeamMemberInfoActivity.this, R.string.update_success); + + viewMember = managers.get(0); + updateMemberInfo(); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToastLong(AdvancedTeamMemberInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 撤销管理员权限 + */ + private void removeManagers() { + DialogMaker.showProgressDialog(this, getString(R.string.empty)); + ArrayList accountList = new ArrayList<>(); + accountList.add(account); + NIMClient.getService(TeamService.class).removeManagers(teamId, accountList).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List members) { + DialogMaker.dismissProgressDialog(); + identity.setText(R.string.team_member); + ToastHelper.showToastLong(AdvancedTeamMemberInfoActivity.this, R.string.update_success); + + viewMember = members.get(0); + updateMemberInfo(); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToastLong(AdvancedTeamMemberInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 移除群成员确认 + */ + private void showConfirmButton() { + EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() { + + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + removeMember(); + } + }; + final EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(this, null, getString(R.string.team_member_remove_confirm), + getString(R.string.remove), getString(R.string.cancel), true, listener); + dialog.show(); + } + + /** + * 移除群成员 + */ + private void removeMember() { + DialogMaker.showProgressDialog(this, getString(R.string.empty)); + NIMClient.getService(TeamService.class).removeMember(teamId, account).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + makeIntent(account, isSetAdmin, true); + finish(); + ToastHelper.showToastLong(AdvancedTeamMemberInfoActivity.this, R.string.update_success); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToastLong(AdvancedTeamMemberInfoActivity.this, String.format(getString(R.string.update_failed), code)); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + @Override + public void onBackPressed() { + makeIntent(account, isSetAdmin, false); + super.onBackPressed(); + } + + /** + * 设置返回的Intent + * + * @param account 帐号 + * @param isSetAdmin 是否设置为管理员 + * @param value 是否移除群成员 + */ + private void makeIntent(String account, boolean isSetAdmin, boolean value) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_ID, account); + intent.putExtra(EXTRA_ISADMIN, isSetAdmin); + intent.putExtra(EXTRA_ISREMOVE, value); + setResult(RESULT_OK, intent); + } + + private boolean isSelf(String account) { + return NimUIKit.getAccount().equals(account); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamNicknameActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamNicknameActivity.java new file mode 100644 index 0000000..517ad3a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/AdvancedTeamNicknameActivity.java @@ -0,0 +1,153 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.R; + +/** + * Created by hzxuwen on 2015/3/19. + */ +public class AdvancedTeamNicknameActivity extends UI implements TextWatcher, View.OnClickListener { + + // constant + public static final String EXTRA_NAME = "EXTRA_NAME"; + public static final int REQ_CODE_TEAM_NAME = 20; + private static final int MAX_LENGTH = 32; + + // view + private EditText regularTeamNickname; + + // data + private String nickName; + + public static void start(Context context, String name) { + Intent intent = new Intent(); + intent.setClass(context, AdvancedTeamNicknameActivity.class); + intent.putExtra(EXTRA_NAME, name); + ((Activity) context).startActivityForResult(intent, REQ_CODE_TEAM_NAME); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_advanced_team_nickname_activity); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleId = R.string.team_nickname; + setToolBar(R.id.toolbar, options); + + nickName = getIntent().getStringExtra(EXTRA_NAME); + if (nickName == null) { + nickName = ""; + } + + TextView toolbarView = findView(R.id.action_bar_right_clickable_textview); + toolbarView.setText(R.string.save); + toolbarView.setOnClickListener(this); + + regularTeamNickname = (EditText) findViewById(R.id.regular_team_nickname); + regularTeamNickname.setText(nickName); + regularTeamNickname.addTextChangedListener(this); + regularTeamNickname.setOnKeyListener(new View.OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) { + // do nothing, just consume ACTION_UP event + return true; + } + return false; + } + + }); + regularTeamNickname.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE + || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + complete(); + return true; + } else { + return false; + } + } + }); + showKeyboardDelayed(regularTeamNickname); + + LinearLayout backgroundLayout = (LinearLayout) findViewById(R.id.background); + backgroundLayout.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + showKeyboard(false); + } + }); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + int editEnd = regularTeamNickname.getSelectionEnd(); + regularTeamNickname.removeTextChangedListener(this); + while (StringUtil.counterChars(s.toString()) > MAX_LENGTH && editEnd > 0) { + s.delete(editEnd - 1, editEnd); + editEnd--; + } + regularTeamNickname.setSelection(editEnd); + regularTeamNickname.addTextChangedListener(this); + } + + @Override + public void onClick(View v) { + int i = v.getId(); + if (i == R.id.action_bar_right_clickable_textview) { + showKeyboard(false); + complete(); + } else { + } + } + + private void complete() { + if (TextUtils.isEmpty(regularTeamNickname.getText().toString())) { + ToastHelper.showToast(this, R.string.team_name_toast); + } else { + Intent intent = getIntent(); + intent.putExtra(EXTRA_NAME, regularTeamNickname.getText().toString()); + setResult(RESULT_OK, intent); + finish(); + } + + } + + @Override + public void onBackPressed() { + showKeyboard(false); + super.onBackPressed(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/NormalTeamInfoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/NormalTeamInfoActivity.java new file mode 100644 index 0000000..294e014 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/NormalTeamInfoActivity.java @@ -0,0 +1,699 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.Button; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamMemberDataChangedObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObserver; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactIdFilter; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.activity.ContactSelectActivity; +import com.fengliyan.tianlesue.im.uikit.business.team.adapter.TeamMemberAdapter; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.business.team.model.TeamExtras; +import com.fengliyan.tianlesue.im.uikit.business.team.model.TeamRequestCode; +import com.fengliyan.tianlesue.im.uikit.business.team.ui.TeamInfoGridView; +import com.fengliyan.tianlesue.im.uikit.business.team.viewholder.TeamMemberHolder; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapterDelegate; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.DialogMaker; +import com.fengliyan.tianlesue.im.uikit.common.ui.widget.SwitchButton; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.NetworkUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.constant.TeamFieldEnum; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.constant.TeamMessageNotifyTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * 讨论组资料页 + *

+ * Created by huangjun on 2015/3/3. + */ +public class NormalTeamInfoActivity extends UI implements OnClickListener, TAdapterDelegate, + TeamMemberAdapter.RemoveMemberCallback, TeamMemberAdapter.AddMemberCallback, TeamMemberHolder.TeamMemberHolderEventListener { + + // constant + private static final String TAG = "TeamInfoActivity"; + + private static final int REQUEST_CODE_NAME = 101; + + private static final int REQUEST_CODE_CONTACT_SELECT = 102; + + private static final String EXTRA_ID = "EXTRA_ID"; + + private static final String KEY_MSG_NOTICE = "msg_notice"; + + // adapter & data source + + private TeamMemberAdapter adapter; + + private String teamId; + + private Team team; + + private String creator; + + private List memberAccounts; + + private List dataSource; + + private UserInfoObserver userInfoObserver; + + // view + private TextView teamNameTextView; + + private TeamInfoGridView gridView; + + private ViewGroup toggleLayout; + + private SwitchButton noticeBtn; + + // state + private boolean isSelfAdmin = false; + + private int teamCapacity = 200; // 群人数上限,暂定 + + /** + * 启动群资料页 + * + * @param context 调用方Activity + * @param id 讨论组ID + */ + public static void start(Context context, String id) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_ID, id); + intent.setClass(context, NormalTeamInfoActivity.class); + ((Activity) context).startActivityForResult(intent, TeamRequestCode.REQUEST_CODE); + } + + /** + * ************************ TAdapterDelegate ************************** + */ + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public Class viewHolderAtPosition(int position) { + return TeamMemberHolder.class; + } + + @Override + public boolean enabled(int position) { + return false; + } + + /** + * ***************************** Life cycle ***************************** + */ + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_team_info_activity); + + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + + parseIntentData(); + initToggleBtn(); + loadTeamInfo(); + initAdapter(); + findViews(); + requestMembers(); + + registerObservers(true); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + registerObservers(false); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODE_CONTACT_SELECT && resultCode == Activity.RESULT_OK) { + final ArrayList selected = data.getStringArrayListExtra(ContactSelectActivity.RESULT_DATA); + if (selected != null && !selected.isEmpty()) { + addMembersToTeam(selected); + } + } + } + + /** + * ************************** 群信息变更监听 ************************** + */ + /** + * 注册群信息更新监听 + * + * @param register + */ + private void registerObservers(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataObserver, register); + NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberObserver, register); + registerUserInfoChangedObserver(register); + } + + TeamDataChangedObserver teamDataObserver = new TeamDataChangedObserver() { + @Override + public void onUpdateTeams(List teams) { + for (Team team : teams) { + if (team.getId().equals(teamId)) { + updateTeamInfo(team); + break; + } + } + } + + @Override + public void onRemoveTeam(Team team) { + if (team.getId().equals(teamId)) { + NormalTeamInfoActivity.this.team = team; + } + } + }; + + TeamMemberDataChangedObserver teamMemberObserver = new TeamMemberDataChangedObserver() { + + @Override + public void onUpdateTeamMember(List members) { + List accounts = new ArrayList<>(); + for (TeamMember m : members) { + if (m.getTid().equals(teamId)) { + accounts.add(m.getAccount()); + } + } + + if (!accounts.isEmpty()) { + addMember(accounts, null, false); + } + } + + @Override + public void onRemoveTeamMember(List members) { + for (TeamMember member : members) { + if (member.getTid().equals(teamId)) { + removeMember(member.getAccount()); + } + } + } + }; + + private void refreshMembers(List members) { + gridView.setVisibility(View.VISIBLE); + List accounts = new ArrayList<>(); + for (TeamMember member : members) { + // 标记创建者(群主) + if (member.getType() == TeamMemberType.Owner) { + creator = member.getAccount(); + if (creator.equals(NimUIKit.getAccount())) { + isSelfAdmin = true; + } + } + accounts.add(member.getAccount()); + } + addMember(accounts, null, true); + } + + private void parseIntentData() { + teamId = getIntent().getStringExtra(EXTRA_ID); + } + + private void initToggleBtn() { + toggleLayout = findView(R.id.toggle_layout); + noticeBtn = addToggleItemView(KEY_MSG_NOTICE, R.string.team_notification_config, true); + } + + private void setToggleBtn(Team team) { + if (noticeBtn != null) { + noticeBtn.setCheck(team.getMessageNotifyType() == TeamMessageNotifyTypeEnum.All); + } + } + + private SwitchButton addToggleItemView(String key, int titleResId, boolean initState) { + ViewGroup vp = (ViewGroup) getLayoutInflater().inflate(R.layout.nim_user_profile_toggle_item, null); + ViewGroup.LayoutParams vlp = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.isetting_item_height)); + vp.setLayoutParams(vlp); + + TextView titleText = ((TextView) vp.findViewById(R.id.user_profile_title)); + titleText.setText(titleResId); + + SwitchButton switchButton = (SwitchButton) vp.findViewById(R.id.user_profile_toggle); + switchButton.setCheck(initState); + switchButton.setOnChangedListener(onChangedListener); + switchButton.setTag(key); + + toggleLayout.addView(vp); + + return switchButton; + } + + private SwitchButton.OnChangedListener onChangedListener = new SwitchButton.OnChangedListener() { + @Override + public void OnChanged(View v, final boolean checkState) { + if (!NetworkUtil.isNetAvailable(NormalTeamInfoActivity.this)) { + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.network_is_not_available); + noticeBtn.setCheck(!checkState); + return; + } + TeamMessageNotifyTypeEnum typeEnum = checkState ? TeamMessageNotifyTypeEnum.All : TeamMessageNotifyTypeEnum.Mute; + NIMClient.getService(TeamService.class).muteTeam(team.getId(), typeEnum).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + if (checkState) { + ToastHelper.showToast(NormalTeamInfoActivity.this, "开启消息提醒"); + } else { + ToastHelper.showToast(NormalTeamInfoActivity.this, "关闭消息提醒"); + } + } + + @Override + public void onFailed(int code) { + if (code == 408) { + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.network_is_not_available); + } else { + ToastHelper.showToast(NormalTeamInfoActivity.this, "on failed:" + code); + } + noticeBtn.setCheck(!checkState); + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + }; + + private void loadTeamInfo() { + creator = ""; + Team t = NimUIKit.getTeamProvider().getTeamById(teamId); + if (t != null) { + updateTeamInfo(t); + } else { + NimUIKit.getTeamProvider().fetchTeamById(teamId, new SimpleCallback() { + @Override + public void onResult(boolean success, Team result, int code) { + if (success && result != null) { + updateTeamInfo(result); + } else { + onGetTeamInfoFailed(); + } + } + }); + } + + } + + private void updateTeamInfo(Team t) { + if (t == null) { + return; + } + + team = t; + + // title + String teamName = team.getName(); + setTitle(teamName); + + // team name + View nameView = findViewById(R.id.settings_item_name); + teamNameTextView = (TextView) nameView.findViewById(R.id.item_detail); + teamNameTextView.setText(teamName); + teamNameTextView.setEnabled(isSelfAdmin); + + setToggleBtn(team); + } + + private void onGetTeamInfoFailed() { + ToastHelper.showToast(this, getString(R.string.normal_team_not_exist)); + finish(); + } + + private void initAdapter() { + memberAccounts = new ArrayList<>(); + dataSource = new ArrayList<>(); + adapter = new TeamMemberAdapter(this, dataSource, this, this, this); + adapter.setEventListener(this); + } + + private void findViews() { + // grid view + gridView = (TeamInfoGridView) findViewById(R.id.team_members_grid_view); + gridView.setSelector(R.color.transparent); + gridView.setOnScrollListener(new AbsListView.OnScrollListener() { + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + if (scrollState == 0) { + adapter.notifyDataSetChanged(); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }); + gridView.setOnTouchListener(new View.OnTouchListener() { + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP && adapter.getMode() == TeamMemberAdapter.Mode.DELETE) { + adapter.setMode(TeamMemberAdapter.Mode.NORMAL); + adapter.notifyDataSetChanged(); + return true; + } + return false; + } + }); + gridView.setAdapter(adapter); + + // discussion name view + View nameView = findViewById(R.id.settings_item_name); + nameView.setOnClickListener(this); + TextView nameLabel = (TextView) nameView.findViewById(R.id.item_title); + nameLabel.setText(R.string.normal_team_name); + + // talk button + Button quitBtn = (Button) findViewById(R.id.quit_team); + quitBtn.setOnClickListener(this); + } + + /** + * *************************** 加载&变更数据源 ******************************** + */ + private void requestMembers() { + gridView.setVisibility(View.GONE); + memberAccounts.clear(); + if (team != null) { + NimUIKit.getTeamProvider().fetchTeamMemberList(teamId, new SimpleCallback>() { + @Override + public void onResult(boolean success, List members, int code) { + if (success && members != null && !members.isEmpty()) { + refreshMembers(members); + } else { + ToastHelper.showToast(NormalTeamInfoActivity.this, "获取成员列表失败"); + } + } + }); + } + } + + private void addMember(List accounts, List failed, boolean clear) { + if (accounts == null || accounts.isEmpty()) { + return; + } + + if (clear) { + this.memberAccounts.clear(); + } + + // add + if (this.memberAccounts.isEmpty()) { + this.memberAccounts.addAll(accounts); + } else { + for (String account : accounts) { + if (!this.memberAccounts.contains(account) && (failed == null || !failed.contains(account))) { + this.memberAccounts.add(account); + } + } + } + + // sort + Collections.sort(this.memberAccounts, new Comparator() { + @Override + public int compare(String l, String r) { + if (creator == null) { + return 0; + } + + if (creator.equals(l)) { + return -1; + } + if (creator.equals(r)) { + return 1; + } + + return l.compareTo(r); + } + }); + + updateDataSource(); + } + + private void updateDataSource() { + dataSource.clear(); + + // member item + String identity; + for (String account : memberAccounts) { + if (creator.equals(account)) { + identity = TeamMemberHolder.OWNER; + } else { + identity = null; + } + dataSource.add(new TeamMemberAdapter.TeamMemberItem(TeamMemberAdapter.TeamMemberItemTag + .NORMAL, teamId, account, identity)); + } + + // add item + dataSource.add(new TeamMemberAdapter.TeamMemberItem(TeamMemberAdapter.TeamMemberItemTag.ADD, null, null, null)); + + // remove item + if (isSelfAdmin) { + dataSource.add(new TeamMemberAdapter.TeamMemberItem(TeamMemberAdapter.TeamMemberItemTag.DELETE, null, null, + null)); + } + + // refresh + if (adapter.getMode() != TeamMemberAdapter.Mode.DELETE) { + adapter.notifyDataSetChanged(); + } + } + + private void removeMember(String account) { + memberAccounts.remove(account); + for (TeamMemberAdapter.TeamMemberItem item : dataSource) { + if (account.equals(item.getAccount())) { + dataSource.remove(item); + break; + } + } + // 为了解决2.3系统,移除用户后刷新界面不显示的问题 + if (Build.VERSION.SDK_INT < 11) { + adapter.setMode(TeamMemberAdapter.Mode.NORMAL); + } + + adapter.notifyDataSetChanged(); + } + + /** + * ******************************* Action ********************************* + */ + + /** + * 邀请群成员 + */ + @Override + public void onAddMember() { + ContactSelectActivity.Option option = new ContactSelectActivity.Option(); + option.title = "邀请成员"; + ArrayList disableAccounts = new ArrayList<>(); + disableAccounts.addAll(memberAccounts); + option.itemDisableFilter = new ContactIdFilter(disableAccounts); + + // 限制群成员数量在群容量范围内 + int capacity = teamCapacity - memberAccounts.size(); + option.maxSelectNum = capacity; + option.maxSelectedTip = getString(R.string.reach_team_member_capacity, teamCapacity); + NimUIKit.startContactSelector(NormalTeamInfoActivity.this, option, REQUEST_CODE_CONTACT_SELECT); + } + + /** + * 移除群成员 + */ + @Override + public void onRemoveMember(final String account) { + DialogMaker.showProgressDialog(this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).removeMember(teamId, account).setCallback(new RequestCallback + () { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + removeMember(account); + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.remove_member_success); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.remove_member_failed); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + + /** + * 添加群成员 + */ + private void addMembersToTeam(final ArrayList selected) { + // add members + DialogMaker.showProgressDialog(this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).addMembers(teamId, selected).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List failedAccounts) { + DialogMaker.dismissProgressDialog(); + addMember(selected, failedAccounts, false); + if (failedAccounts != null && !failedAccounts.isEmpty()) { + TeamHelper.onMemberTeamNumOverrun(failedAccounts, NormalTeamInfoActivity.this); + } else { + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.invite_member_success); + } + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.invite_member_failed); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * 非群主退出群 + */ + private void quitTeam() { + DialogMaker.showProgressDialog(this, getString(R.string.empty), true); + NIMClient.getService(TeamService.class).quitTeam(teamId).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.quit_normal_team_success); + setResult(Activity.RESULT_OK, new Intent().putExtra(TeamExtras.RESULT_EXTRA_REASON, TeamExtras.RESULT_EXTRA_REASON_QUIT)); + + NIMClient.getService(MsgService.class).deleteRecentContact2(teamId, SessionTypeEnum.Team); + finish(); + } + + @Override + public void onFailed(int code) { + DialogMaker.dismissProgressDialog(); + ToastHelper.showToast(NormalTeamInfoActivity.this, R.string.quit_normal_team_failed); + } + + @Override + public void onException(Throwable exception) { + DialogMaker.dismissProgressDialog(); + } + }); + } + + /** + * ******************************* Event ********************************* + */ + + @Override + public void onClick(View v) { + int i = v.getId(); + if (i == R.id.quit_team) { + quitTeam(); + + } else if (i == R.id.settings_item_name) { + TeamPropertySettingActivity.start(NormalTeamInfoActivity.this, teamId, TeamFieldEnum.Name, teamNameTextView.getText().toString(), REQUEST_CODE_NAME); + + } else { + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && adapter.switchMode()) { + return true; + } + + return super.onKeyDown(keyCode, event); + } + + @Override + public void onBackPressed() { + if (adapter.switchMode()) { + return; + } + + super.onBackPressed(); + } + + @Override + public void onHeadImageViewClick(String account) { + if (NimUIKitImpl.getContactEventListener() != null) { + NimUIKitImpl.getContactEventListener().onAvatarClick(this, account); + } + } + + private void registerUserInfoChangedObserver(boolean register) { + if (register) { + if (userInfoObserver == null) { + userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + adapter.notifyDataSetChanged(); + } + }; + } + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, true); + } else { + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, false); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/TeamPropertySettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/TeamPropertySettingActivity.java new file mode 100644 index 0000000..ef1f2b1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/activity/TeamPropertySettingActivity.java @@ -0,0 +1,255 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringTextWatcher; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.constant.TeamFieldEnum; + +/** + * 群属性 + * Created by hzxuwen on 2015/4/10. + */ +public class TeamPropertySettingActivity extends UI implements View.OnClickListener { + + private static final String EXTRA_TID = "EXTRA_TID"; + public static final String EXTRA_DATA = "EXTRA_DATA"; + private static final String EXTRA_FIELD = "EXTRA_FIELD"; + + // view + private EditText editText; + + // data + private String teamId; + private TeamFieldEnum filed; + private String initialValue; + + + /** + * 修改群某一个属性公用界面 + * + * @param activity + * @param teamId + * @param field + * @param initialValue + * @param requestCode + */ + public static void start(Activity activity, String teamId, TeamFieldEnum field, String initialValue, int requestCode) { + Intent intent = new Intent(); + intent.setClass(activity, TeamPropertySettingActivity.class); + intent.putExtra(EXTRA_TID, teamId); + intent.putExtra(EXTRA_DATA, initialValue); + intent.putExtra(EXTRA_FIELD, field); + activity.startActivityForResult(intent, requestCode); + } + + /** + * 修改群某一个属性公用界面 + * + * @param context + * @param teamId + * @param field + * @param initialValue + */ + public static void start(Context context, String teamId, TeamFieldEnum field, String initialValue) { + Intent intent = new Intent(); + intent.setClass(context, TeamPropertySettingActivity.class); + intent.putExtra(EXTRA_TID, teamId); + intent.putExtra(EXTRA_DATA, initialValue); + intent.putExtra(EXTRA_FIELD, field); + context.startActivity(intent); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_team_name_activity); + + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + + findViews(); + parseIntent(); + + TextView toolbarView = findView(R.id.action_bar_right_clickable_textview); + toolbarView.setText(R.string.save); + toolbarView.setOnClickListener(this); + } + + private void parseIntent() { + teamId = getIntent().getStringExtra(EXTRA_TID); + filed = (TeamFieldEnum) getIntent().getSerializableExtra(EXTRA_FIELD); + initialValue = getIntent().getStringExtra(EXTRA_DATA); + + initData(); + } + + private void initData() { + int limit = 0; + switch (filed) { + case Name: + setTitle(R.string.team_settings_name); + editText.setHint(R.string.team_settings_set_name); + limit = 64; + break; + case Introduce: + setTitle(R.string.team_introduce); + editText.setHint(R.string.team_introduce_hint); + limit = 512; + break; + case Extension: + setTitle(R.string.team_extension); + editText.setHint(R.string.team_extension_hint); + limit = 65535; + break; + } + + if (!TextUtils.isEmpty(initialValue)) { + editText.setText(initialValue); + editText.setSelection(initialValue.length()); + } + editText.addTextChangedListener(new StringTextWatcher(limit, editText)); + } + + private void findViews() { + editText = (EditText) findViewById(R.id.discussion_name); + editText.setOnKeyListener(new View.OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + return keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP; + } + + }); + editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE + || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + complete(); + return true; + } else { + return false; + } + } + }); + showKeyboardDelayed(editText); + + LinearLayout backgroundLayout = (LinearLayout) findViewById(R.id.background); + backgroundLayout.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + showKeyboard(false); + } + }); + } + + @Override + public void onClick(View v) { + int i = v.getId(); + if (i == R.id.action_bar_right_clickable_textview) { + showKeyboard(false); + complete(); + } else { + } + } + + /** + * 点击保存 + */ + private void complete() { + if (filed == TeamFieldEnum.Name) { + if (TextUtils.isEmpty(editText.getText().toString())) { + ToastHelper.showToast(this, R.string.not_allow_empty); + } else { + char[] s = editText.getText().toString().toCharArray(); + int i; + for (i = 0; i < s.length; i++) { + if (String.valueOf(s[i]).equals(" ")) { + ToastHelper.showToast(this, R.string.now_allow_space); + break; + } + } + if (i == s.length) { + saveTeamProperty(); + } + } + } else { + if (TextUtils.equals(editText.getText().toString(), initialValue)) { + showKeyboard(false); + finish(); + } else if (TextUtils.isEmpty(teamId)) { + saved(); + } else { + saveTeamProperty(); + } + } + } + + private void saved() { + Intent intent = new Intent(); + intent.putExtra(EXTRA_DATA, editText.getText().toString()); + setResult(Activity.RESULT_OK, intent); + showKeyboard(false); + finish(); + } + + /** + * 保存设置 + */ + private void saveTeamProperty() { + if (teamId == null) { // 讨论组创建时,设置群名称 + Intent intent = new Intent(); + intent.putExtra(EXTRA_DATA, editText.getText().toString()); + setResult(Activity.RESULT_OK, intent); + finish(); + } else { + NIMClient.getService(TeamService.class).updateTeam(teamId, filed, editText.getText().toString()).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + ToastHelper.showToast(TeamPropertySettingActivity.this, R.string.update_success); + saved(); + } + + @Override + public void onFailed(int code) { + if (code == ResponseCode.RES_TEAM_ENACCESS) { + ToastHelper.showToast(TeamPropertySettingActivity.this, R.string.no_permission); + + } else { + ToastHelper.showToast(TeamPropertySettingActivity.this, String.format(getString(R.string.update_failed), code)); + } + } + + @Override + public void onException(Throwable exception) { + } + }); + } + } + + @Override + public void onBackPressed() { + showKeyboard(false); + super.onBackPressed(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/adapter/TeamMemberAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/adapter/TeamMemberAdapter.java new file mode 100644 index 0000000..93131d4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/adapter/TeamMemberAdapter.java @@ -0,0 +1,132 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import com.fengliyan.tianlesue.im.uikit.business.team.viewholder.TeamMemberHolder; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapter; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapterDelegate; + +import java.util.List; + +public class TeamMemberAdapter extends TAdapter { + + /** + * 当前GridView显示模式:显示讨论组成员,正在移除讨论组成员 + */ + public static enum Mode { + NORMAL, + DELETE + } + + /** + * 每个Item的类型:讨论组成员,添加成员,移除成员 + */ + public static enum TeamMemberItemTag { + NORMAL, + ADD, + DELETE + } + + /** + * GridView数据项 + */ + public static class TeamMemberItem { + private TeamMemberItemTag tag; + private String tid; + private String account; + private String desc; + + public TeamMemberItem(TeamMemberItemTag tag, String tid, String account, String desc) { + this.tag = tag; + this.tid = tid; + this.account = account; + this.desc = desc; + } + + public TeamMemberItemTag getTag() { + return tag; + } + + public String getTid() { + return tid; + } + + public String getDesc() { + return desc; + } + + public String getAccount() { + return account; + } + } + + /** + * 群成员移除回调函数 + */ + public static interface RemoveMemberCallback { + public void onRemoveMember(String account); + } + + public static interface AddMemberCallback { + public void onAddMember(); + } + + private Context context; + + private Mode mode = Mode.NORMAL; + + private RemoveMemberCallback removeMemberCallback; + + private AddMemberCallback addMemberCallback; + + public Mode getMode() { + return mode; + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + public boolean switchMode() { + if (getMode() == Mode.DELETE) { + setMode(Mode.NORMAL); + notifyDataSetChanged(); + return true; + } + return false; + } + + public RemoveMemberCallback getRemoveMemberCallback() { + return removeMemberCallback; + } + + public AddMemberCallback getAddMemberCallback() { + return addMemberCallback; + } + + public TeamMemberAdapter(Context context, List items, TAdapterDelegate delegate, + RemoveMemberCallback removeMemberCallback, AddMemberCallback addMemberCallback) { + super(context, items, delegate); + this.context = context; + this.removeMemberCallback = removeMemberCallback; + this.addMemberCallback = addMemberCallback; + } + + private TeamMemberHolder.TeamMemberHolderEventListener teamMemberHolderEventListener; + + public void setEventListener(TeamMemberHolder.TeamMemberHolderEventListener eventListener) { + this.teamMemberHolderEventListener = eventListener; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view = super.getView(position, convertView, parent); + if (teamMemberHolderEventListener != null) { + ((TeamMemberHolder) view.getTag()).setEventListener(teamMemberHolderEventListener); + } + + return view; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/adapter/TeamMemberListAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/adapter/TeamMemberListAdapter.java new file mode 100644 index 0000000..a28f522 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/adapter/TeamMemberListAdapter.java @@ -0,0 +1,80 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.team.viewholder.TeamMemberListHolder; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.List; + +/** + * Created by hzchenkang on 2016/12/2. + */ + +public class TeamMemberListAdapter extends RecyclerView.Adapter + implements View.OnClickListener { + + public interface ItemClickListener { + void onItemClick(TeamMember member); + } + + private Context context; + + private List members; + + private ItemClickListener listener; + + public TeamMemberListAdapter(Context context) { + this.context = context; + } + + public void updateData(List members) { + this.members = members; + notifyDataSetChanged(); + } + + public void setListener(ItemClickListener listener) { + this.listener = listener; + } + + @Override + public TeamMemberListHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (context == null) { + return null; + } + LayoutInflater inflater = LayoutInflater.from(context); + View v = inflater.inflate(R.layout.nim_ait_contact_team_member_item, parent, false); + v.setOnClickListener(this); + return new TeamMemberListHolder(v); + } + + @Override + public void onBindViewHolder(TeamMemberListHolder holder, int position) { + if (members == null || members.size() <= position) { + return; + } + + TeamMember member = members.get(position); + + holder.refresh(member); + } + + @Override + public int getItemCount() { + return members == null ? 0 : members.size(); + } + + @Override + public void onClick(View v) { + TeamMember member = (TeamMember) v.getTag(); + if (listener != null) { + listener.onItemClick(member); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/helper/AnnouncementHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/helper/AnnouncementHelper.java new file mode 100644 index 0000000..fe282be --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/helper/AnnouncementHelper.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.helper; + +import android.text.TextUtils; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.team.model.Announcement; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Created by huangjun on 2015/3/24. + */ +public class AnnouncementHelper { + public final static String JSON_KEY_CREATOR = "creator"; + public final static String JSON_KEY_TITLE = "title"; + public final static String JSON_KEY_TIME = "time"; + public final static String JSON_KEY_CONTENT = "content"; + public final static String JSON_KEY_ID = "id"; + + public static String makeAnnounceJson(String announce, String title, String content) { + JSONArray jsonArray = null; + try { + jsonArray = JSONArray.parseArray(announce); + } catch (Exception e) { + e.printStackTrace(); + } + + if (jsonArray == null) { + jsonArray = new JSONArray(); + } + + JSONObject json = new JSONObject(); + json.put(JSON_KEY_ID, UUID.randomUUID().toString()); + json.put(JSON_KEY_CREATOR, getCreatorName()); + json.put(JSON_KEY_TITLE, title); + json.put(JSON_KEY_CONTENT, content); + json.put(JSON_KEY_TIME, (System.currentTimeMillis() / 1000)); // 与ios和pc兼容 + jsonArray.add(json); + return jsonArray.toString(); + } + + public static List getAnnouncements(String teamId, String announce, int limit) { + if (TextUtils.isEmpty(announce)) { + return null; + } + + List announcements = new ArrayList<>(); + try { + int count = 0; + JSONArray jsonArray = JSONArray.parseArray(announce); + for (int i = jsonArray.size() - 1; i >= 0; i--) { + JSONObject json = jsonArray.getJSONObject(i); + String id = json.getString(JSON_KEY_ID); + String creator = json.getString(JSON_KEY_CREATOR); + String title = json.getString(JSON_KEY_TITLE); + long time = json.getLongValue(JSON_KEY_TIME); + String content = json.getString(JSON_KEY_CONTENT); + + announcements.add(new Announcement(id, teamId, creator, title, time, content)); + + if (++count >= limit) { + break; + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + + return announcements; + } + + public static Announcement getLastAnnouncement(String teamId, String announcement) { + List list = getAnnouncements(teamId, announcement, 1); + return (list == null || list.isEmpty()) ? null : list.get(0); + } + + private static String getCreatorName() { + return NimUIKit.getAccount(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/helper/TeamHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/helper/TeamHelper.java new file mode 100644 index 0000000..88a0174 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/helper/TeamHelper.java @@ -0,0 +1,337 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.helper; + +import android.content.Context; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.contact.core.item.ContactIdFilter; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.activity.ContactSelectActivity; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.team.constant.TeamBeInviteModeEnum; +import com.netease.nimlib.sdk.team.constant.TeamInviteModeEnum; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.constant.TeamMessageNotifyTypeEnum; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.constant.TeamUpdateModeEnum; +import com.netease.nimlib.sdk.team.constant.VerifyTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by hzxuwen on 2015/3/25. + */ +public class TeamHelper { + public static VerifyTypeEnum getVerifyTypeEnum(String name) { + VerifyTypeEnum type = null; + + if (name.equals(NimUIKit.getContext().getString(R.string.team_allow_anyone_join))) { + type = VerifyTypeEnum.Free; + } else if (name.equals(NimUIKit.getContext().getString(R.string.team_need_authentication))) { + type = VerifyTypeEnum.Apply; + } else if (name.equals(NimUIKit.getContext().getString(R.string.team_not_allow_anyone_join))) { + type = VerifyTypeEnum.Private; + } + + return type; + } + + public static List createAuthenMenuStrings() { + int[] res = new int[]{R.string.team_allow_anyone_join, R.string.team_need_authentication, + R.string.team_not_allow_anyone_join, R.string.cancel}; + List btnNames = new ArrayList<>(); + for (int r : res) { + btnNames.add(NimUIKit.getContext().getString(r)); + } + return btnNames; + } + + public static int getVerifyString(VerifyTypeEnum type) { + if (type == VerifyTypeEnum.Free) { + return R.string.team_allow_anyone_join; + } else if (type == VerifyTypeEnum.Apply) { + return R.string.team_need_authentication; + } else { + return R.string.team_not_allow_anyone_join; + } + } + + // 群消息提醒类型菜单项名称 + public static List createNotifyMenuStrings() { + int[] res = new int[]{ + R.string.team_notify_all, + R.string.team_notify_manager, + R.string.team_notify_mute, + R.string.cancel + }; + List btnNames = new ArrayList<>(); + for (int r : res) { + btnNames.add(NimUIKit.getContext().getString(r)); + } + return btnNames; + } + + // 获取提醒类型 + public static TeamMessageNotifyTypeEnum getNotifyType(String name) { + TeamMessageNotifyTypeEnum type = null; + if (name.equals(NimUIKit.getContext().getString(R.string.team_notify_all))) { + type = TeamMessageNotifyTypeEnum.All; + } else if (name.equals(NimUIKit.getContext().getString(R.string.team_notify_manager))) { + type = TeamMessageNotifyTypeEnum.Manager; + } else if (name.equals(NimUIKit.getContext().getString(R.string.team_notify_mute))) { + type = TeamMessageNotifyTypeEnum.Mute; + } + return type; + } + + // 邀请他人菜单项名称 + public static List createInviteMenuStrings() { + int[] res = new int[]{R.string.team_admin_invite, R.string.team_everyone_invite, + R.string.cancel}; + List btnNames = new ArrayList<>(); + for (int r : res) { + btnNames.add(NimUIKit.getContext().getString(r)); + } + return btnNames; + } + + // 获取邀请他人类型 + public static TeamInviteModeEnum getInviteModeEnum(String name) { + TeamInviteModeEnum type = null; + + if (name.equals(NimUIKit.getContext().getString(R.string.team_admin_invite))) { + type = TeamInviteModeEnum.Manager; + } else if (name.equals(NimUIKit.getContext().getString(R.string.team_everyone_invite))) { + type = TeamInviteModeEnum.All; + } + + return type; + } + + // 获取邀请他人文本描述 + public static int getInviteModeString(TeamInviteModeEnum type) { + if (type == TeamInviteModeEnum.Manager) { + return R.string.team_admin_invite; + } else { + return R.string.team_everyone_invite; + } + } + + // 群资料修改权限菜单名称 + public static List createTeamInfoUpdateMenuStrings() { + int[] res = new int[]{R.string.team_admin_update, R.string.team_everyone_update, + R.string.cancel}; + List btnNames = new ArrayList<>(); + for (int r : res) { + btnNames.add(NimUIKit.getContext().getString(r)); + } + return btnNames; + } + + // 获取群资料修改类型 + public static TeamUpdateModeEnum getUpdateModeEnum(String name) { + TeamUpdateModeEnum type = null; + + if (name.equals(NimUIKit.getContext().getString(R.string.team_admin_update))) { + type = TeamUpdateModeEnum.Manager; + } else if (name.equals(NimUIKit.getContext().getString(R.string.team_everyone_update))) { + type = TeamUpdateModeEnum.All; + } + + return type; + } + + // 获取群资料修改类型文本描述 + public static int getInfoUpdateModeString(TeamUpdateModeEnum type) { + if (type == TeamUpdateModeEnum.Manager) { + return R.string.team_admin_update; + } else { + return R.string.team_everyone_update; + } + } + + // 被邀请人身份验证名称 + public static List createTeamInviteeAuthenMenuStrings() { + int[] res = new int[]{R.string.team_invitee_need_authen, R.string.team_invitee_not_need_authen, + R.string.cancel}; + List btnNames = new ArrayList<>(); + for (int r : res) { + btnNames.add(NimUIKit.getContext().getString(r)); + } + return btnNames; + } + + // 获取被邀请人身份类型 + public static TeamBeInviteModeEnum getBeInvitedModeEnum(String name) { + TeamBeInviteModeEnum type = null; + + if (name.equals(NimUIKit.getContext().getString(R.string.team_invitee_need_authen))) { + type = TeamBeInviteModeEnum.NeedAuth; + } else if (name.equals(NimUIKit.getContext().getString(R.string.team_invitee_not_need_authen))) { + type = TeamBeInviteModeEnum.NoAuth; + } + + return type; + } + + // 获取被邀请人类型文本描述 + public static int getBeInvitedModeString(TeamBeInviteModeEnum type) { + if (type == TeamBeInviteModeEnum.NeedAuth) { + return R.string.team_invitee_need_authen; + } else { + return R.string.team_invitee_not_need_authen; + } + } + + /** + * 获取创建群通讯录选择器option + * + * @return + */ + public static ContactSelectActivity.Option getCreateContactSelectOption(ArrayList memberAccounts, int teamCapacity) { + // 限制群成员数量在群容量范围内 + int capacity = teamCapacity - (memberAccounts == null ? 0 : memberAccounts.size()); + ContactSelectActivity.Option option = TeamHelper.getContactSelectOption(memberAccounts); + option.maxSelectNum = capacity; + option.maxSelectedTip = NimUIKit.getContext().getString(R.string.reach_team_member_capacity, teamCapacity); + option.allowSelectEmpty = true; + option.alreadySelectedAccounts = memberAccounts; + return option; + } + + /** + * 获取通讯录选择器option + * + * @param memberAccounts + * @return + */ + public static ContactSelectActivity.Option getContactSelectOption(List memberAccounts) { + ContactSelectActivity.Option option = new ContactSelectActivity.Option(); + option.title = NimUIKit.getContext().getString(R.string.invite_member); + if (memberAccounts != null) { + ArrayList disableAccounts = new ArrayList<>(); + disableAccounts.addAll(memberAccounts); + option.itemDisableFilter = new ContactIdFilter(disableAccounts); + } + return option; + } + + private static Map teamMemberLevelMap = new HashMap<>(4); + + static { + teamMemberLevelMap.put(TeamMemberType.Owner, 0); + teamMemberLevelMap.put(TeamMemberType.Manager, 1); + teamMemberLevelMap.put(TeamMemberType.Normal, 2); + teamMemberLevelMap.put(TeamMemberType.Apply, 3); + } + + /** + * 邀请的成员,所在群数量已经超限 + * + * @param failedAccounts 超限的账号列表 + * @param context context + */ + public static void onMemberTeamNumOverrun(List failedAccounts, Context context) { + if (failedAccounts != null && !failedAccounts.isEmpty()) { + StringBuilder tipContent = new StringBuilder("好友:"); + for (int i = 0; i < failedAccounts.size(); i++) { + String name = UserInfoHelper.getUserDisplayName(failedAccounts.get(i)); + tipContent.append(name); + if (i != failedAccounts.size() - 1) { + tipContent.append("、"); + } + } + tipContent.append("所在群组数量达到上限,邀请失败"); + ToastHelper.showToast(context, tipContent.toString()); + } + } + + public static Comparator teamMemberComparator = new Comparator() { + @Override + public int compare(TeamMember l, TeamMember r) { + if (l == null) { + return 1; + } + + if (r == null) { + return -1; + } + + return teamMemberLevelMap.get(l.getType()) - teamMemberLevelMap.get(r.getType()); + } + }; + + + public static String getTeamName(String teamId) { + Team team = NimUIKit.getTeamProvider().getTeamById(teamId); + return team == null ? teamId : TextUtils.isEmpty(team.getName()) ? team.getId() : team + .getName(); + } + + /** + * 获取显示名称。用户本人显示“我” + * + * @param tid + * @param account + * @return + */ + public static String getTeamMemberDisplayName(String tid, String account) { + if (account.equals(NimUIKit.getAccount())) { + return "我"; + } + + return getDisplayNameWithoutMe(tid, account); + } + + /** + * 获取显示名称。用户本人显示“你” + * + * @param tid + * @param account + * @return + */ + public static String getTeamMemberDisplayNameYou(String tid, String account) { + if (account.equals(NimUIKit.getAccount())) { + return "你"; + } + + return getDisplayNameWithoutMe(tid, account); + } + + /** + * 获取显示名称。用户本人也显示昵称 + * 备注>群昵称>昵称 + */ + public static String getDisplayNameWithoutMe(String tid, String account) { + + String alias = NimUIKit.getContactProvider().getAlias(account); + if (!TextUtils.isEmpty(alias)) { + return alias; + } + + String memberNick = getTeamNick(tid, account); + if (!TextUtils.isEmpty(memberNick)) { + return memberNick; + } + + return UserInfoHelper.getUserName(account); + } + + public static String getTeamNick(String tid, String account) { + Team team = NimUIKit.getTeamProvider().getTeamById(tid); + if (team != null && team.getType() == TeamTypeEnum.Advanced) { + TeamMember member = NimUIKit.getTeamProvider().getTeamMember(tid, account); + if (member != null && !TextUtils.isEmpty(member.getTeamNick())) { + return member.getTeamNick(); + } + } + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/Announcement.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/Announcement.java new file mode 100644 index 0000000..99c6465 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/Announcement.java @@ -0,0 +1,48 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.model; + +/** + * 群公告结构(json) + *

+ * Created by huangjun on 2015/3/24. + */ +public class Announcement { + private String id; + private String creator; + private String title; + private long time; + private String content; + private String teamId; + + public Announcement(String id, String teamId, String creator, String title, long time, String content) { + this.id = id; + this.teamId = teamId; + this.creator = creator; + this.title = title; + this.time = time; + this.content = content; + } + + public String getId() { + return id; + } + + public String getTeamId() { + return teamId; + } + + public String getCreator() { + return creator; + } + + public String getTitle() { + return title; + } + + public long getTime() { + return time; + } + + public String getContent() { + return content; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/TeamExtras.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/TeamExtras.java new file mode 100644 index 0000000..5af18c2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/TeamExtras.java @@ -0,0 +1,12 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.model; + +/** + * Created by hzxuwen on 2015/9/22. + */ +public interface TeamExtras { + String RESULT_EXTRA_REASON = "RESULT_EXTRA_REASON"; + String RESULT_EXTRA_REASON_CREATE = "RESULT_EXTRA_REASON_CREATE"; + String RESULT_EXTRA_DATA = "RESULET_EXTRA_DATA"; + String RESULT_EXTRA_REASON_DISMISS = "RESULT_EXTRA_REASON_DISMISS"; + String RESULT_EXTRA_REASON_QUIT = "RESULT_EXTRA_REASON_QUIT"; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/TeamRequestCode.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/TeamRequestCode.java new file mode 100644 index 0000000..427568c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/model/TeamRequestCode.java @@ -0,0 +1,14 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.model; + +/** + * Created by hzxuwen on 2015/9/22. + */ +public interface TeamRequestCode { + int REQUEST_CODE = 0x04; + + int REQUEST_TEAM_MEMBER = 0x08; + + int REQUEST_TEAM_AIT_MEMBER = 0x10; //@功能时使用 + + int REQUEST_TEAM_VIDEO = 0x20; //群视频邀请成员 +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/ui/TeamInfoGridView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/ui/TeamInfoGridView.java new file mode 100644 index 0000000..55ebfe2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/ui/TeamInfoGridView.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.GridView; + +public class TeamInfoGridView extends GridView { + + public TeamInfoGridView(Context context) { + super(context); + } + + public TeamInfoGridView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public TeamInfoGridView(Context context, AttributeSet attrs) { + super(context, attrs); + + } + + // 取消gridview的滚动,使其能嵌套在scrollview中 + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamAnnounceHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamAnnounceHolder.java new file mode 100644 index 0000000..dbccbb1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamAnnounceHolder.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.viewholder; + +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.business.team.model.Announcement; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.netease.nim.uikit.R; + +/** + * Created by hzxuwen on 2015/3/20. + */ +public class TeamAnnounceHolder extends TViewHolder { + + private TextView announceTitle; + private TextView teamName; + private TextView announceCreateTime; + private TextView announceContent; + + @Override + protected int getResId() { + return R.layout.nim_advanced_team_announce_list_item; + } + + @Override + protected void inflate() { + announceTitle = (TextView) view.findViewById(R.id.announce_title); + teamName = (TextView) view.findViewById(R.id.team_name); + announceCreateTime = (TextView) view.findViewById(R.id.announce_create_time); + announceContent = (TextView) view.findViewById(R.id.announce_content); + } + + @Override + protected void refresh(Object item) { + Announcement a = (Announcement) item; + announceTitle.setText(a.getTitle()); + teamName.setText(TeamHelper.getTeamMemberDisplayName(a.getTeamId(), a.getCreator())); + announceCreateTime.setText(TimeUtil.getTimeShowString((a.getTime() * 1000), false)); // 兼容ios + announceContent.setText(a.getContent()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamMemberHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamMemberHolder.java new file mode 100644 index 0000000..b305c7b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamMemberHolder.java @@ -0,0 +1,141 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.viewholder; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.team.adapter.TeamMemberAdapter; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; + + +public class TeamMemberHolder extends TViewHolder { + + public interface TeamMemberHolderEventListener { + void onHeadImageViewClick(String account); + } + + protected TeamMemberHolderEventListener teamMemberHolderEventListener; + + public void setEventListener(TeamMemberHolderEventListener eventListener) { + this.teamMemberHolderEventListener = eventListener; + } + + private HeadImageView headImageView; + + private ImageView ownerImageView; + + private ImageView adminImageView; + + private ImageView deleteImageView; + + private TextView nameTextView; + + private TeamMemberAdapter.TeamMemberItem memberItem; + + public final static String OWNER = "owner"; + public final static String ADMIN = "admin"; + + protected TeamMemberAdapter getAdapter() { + return (TeamMemberAdapter) super.getAdapter(); + } + + @Override + protected int getResId() { + return R.layout.nim_team_member_item; + } + + @Override + protected void inflate() { + headImageView = (HeadImageView) view.findViewById(R.id.imageViewHeader); + nameTextView = (TextView) view.findViewById(R.id.textViewName); + ownerImageView = (ImageView) view.findViewById(R.id.imageViewOwner); + adminImageView = (ImageView) view.findViewById(R.id.imageViewAdmin); + deleteImageView = (ImageView) view.findViewById(R.id.imageViewDeleteTag); + } + + @Override + protected void refresh(Object item) { + memberItem = (TeamMemberAdapter.TeamMemberItem) item; + headImageView.resetImageView(); + ownerImageView.setVisibility(View.GONE); + adminImageView.setVisibility(View.GONE); + deleteImageView.setVisibility(View.GONE); + + if (getAdapter().getMode() == TeamMemberAdapter.Mode.NORMAL) { + view.setVisibility(View.VISIBLE); + if (memberItem.getTag() == TeamMemberAdapter.TeamMemberItemTag.ADD) { + // add team member + headImageView.setBackgroundResource(R.drawable.nim_team_member_add_selector); + nameTextView.setText(context.getString(R.string.add)); + headImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getAdapter().getAddMemberCallback().onAddMember(); + } + }); + } else if (memberItem.getTag() == TeamMemberAdapter.TeamMemberItemTag.DELETE) { + // delete team member + headImageView.setBackgroundResource(R.drawable.nim_team_member_delete_selector); + nameTextView.setText(context.getString(R.string.remove)); + headImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getAdapter().setMode(TeamMemberAdapter.Mode.DELETE); + getAdapter().notifyDataSetChanged(); + } + }); + } else { + // show team member + refreshTeamMember(memberItem, false); + } + } else if (getAdapter().getMode() == TeamMemberAdapter.Mode.DELETE) { + if (memberItem.getTag() == TeamMemberAdapter.TeamMemberItemTag.NORMAL) { + refreshTeamMember(memberItem, true); + } else { + view.setVisibility(View.GONE); + } + } + } + + private void refreshTeamMember(final TeamMemberAdapter.TeamMemberItem item, boolean deleteMode) { + nameTextView.setText(TeamHelper.getTeamMemberDisplayName(item.getTid(), item.getAccount())); + headImageView.loadBuddyAvatar(item.getAccount()); + headImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (teamMemberHolderEventListener != null) { + teamMemberHolderEventListener.onHeadImageViewClick(item.getAccount()); + } + } + }); + + if (item.getDesc() != null) { + if (item.getDesc().equals(OWNER)) { + ownerImageView.setVisibility(View.VISIBLE); + } else if (item.getDesc().equals(ADMIN)) { + adminImageView.setVisibility(View.VISIBLE); + } + } + + final String account = item.getAccount(); + if (deleteMode && !isSelf(account)) { + deleteImageView.setVisibility(View.VISIBLE); + deleteImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getAdapter().getRemoveMemberCallback().onRemoveMember(account); + } + }); + } else { + deleteImageView.setVisibility(View.GONE); + } + } + + private boolean isSelf(String account) { + return account.equals(NimUIKit.getAccount()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamMemberListHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamMemberListHolder.java new file mode 100644 index 0000000..4e6eca7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/team/viewholder/TeamMemberListHolder.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.im.uikit.business.team.viewholder; + +import android.view.View; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.netease.nimlib.sdk.team.model.TeamMember; + +/** + * Created by hzchenkang on 2016/12/2. + */ + +public class TeamMemberListHolder extends RecyclerView.ViewHolder { + + private HeadImageView headImageView; + + private TextView nameTextView; + + private View container; + + + public TeamMemberListHolder(View itemView) { + super(itemView); + headImageView = (HeadImageView) itemView.findViewById(R.id.imageViewHeader); + nameTextView = (TextView) itemView.findViewById(R.id.textViewName); + container = itemView; + } + + public void refresh(TeamMember member) { + headImageView.resetImageView(); + nameTextView.setText(TeamHelper.getTeamMemberDisplayName(member.getTid(), member.getAccount())); + headImageView.loadBuddyAvatar(member.getAccount()); + container.setTag(member); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/uinfo/UserInfoHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/uinfo/UserInfoHelper.java new file mode 100644 index 0000000..aa9e8e9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/business/uinfo/UserInfoHelper.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.im.uikit.business.uinfo; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.team.helper.TeamHelper; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +public class UserInfoHelper { + + // 获取用户显示在标题栏和最近联系人中的名字 + public static String getUserTitleName(String id, SessionTypeEnum sessionType) { + if (sessionType == SessionTypeEnum.P2P) { + if (NimUIKit.getAccount().equals(id)) { + return UserManager.getUserInfo().getNickname(); + } else { + return getUserDisplayName(id); + } + } else if (sessionType == SessionTypeEnum.Team) { + return TeamHelper.getTeamName(id); + } + return id; + } + + /** + * @param account 用户帐号 + * @return + */ + public static String getUserDisplayName(String account) { + String alias = NimUIKit.getContactProvider().getAlias(account); + if (!TextUtils.isEmpty(alias)) { + return alias; + } else { + UserInfo userInfo = NimUIKit.getUserInfoProvider().getUserInfo(account); + if (userInfo != null && !TextUtils.isEmpty(userInfo.getName())) { + return userInfo.getName(); + } else { + return account; + } + } + } + + // 获取用户原本的昵称 + public static String getUserName(String account) { + UserInfo userInfo = NimUIKit.getUserInfoProvider().getUserInfo(account); + if (userInfo != null && !TextUtils.isEmpty(userInfo.getName())) { + return userInfo.getName(); + } else { + return account; + } + } + + /** + * @param account 账号 + * @param selfNameDisplay 如果是自己,则显示内容 + * @return + */ + public static String getUserDisplayNameEx(String account, String selfNameDisplay) { + if (account.equals(NimUIKit.getAccount())) { + return selfNameDisplay; + } + + return getUserDisplayName(account); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/CommonUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/CommonUtil.java new file mode 100644 index 0000000..683fcc0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/CommonUtil.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.im.uikit.common; + +import com.netease.nimlib.sdk.msg.model.RecentContact; + +import java.util.Collection; + +public class CommonUtil { + + + public static void addTag(RecentContact recent, long tag) { + tag = recent.getTag() | tag; + recent.setTag(tag); + } + + public static void removeTag(RecentContact recent, long tag) { + tag = recent.getTag() & ~tag; + recent.setTag(tag); + } + + public static boolean isTagSet(RecentContact recent, long tag) { + return (recent.getTag() & tag) == tag; + } + + public static boolean isEmpty(Collection collection) { + return collection == null || collection.isEmpty(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/Constans.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/Constans.java new file mode 100644 index 0000000..f834319 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/Constans.java @@ -0,0 +1,20 @@ +package com.fengliyan.tianlesue.im.uikit.common; + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class Constans { + // public final static String IMAGE_URL = "http://xqasset.whnuanbeinikj.cn/"; + public final static String IMAGE_URL = "http://xqasset.whnuanbeinikj.cn/"; + public final static String FIRST_CHARGE_TYPE = "FIRST_CHARGE_TYPE"; + public final static String DEFAULT_PAY_TYPE = "DEFAULT_PAY_TYPE";//默认支付方式 "1":"支付宝","2":"微信" + public final static String SHOW_CER_DIALOG = "SHOW_CER_DIALOG";//真人认证弹窗 + public final static String ENVIRONMENT_TYPE = "ENVIRONMENT_TYPE";//true 开发,false 正式 + public final static String NEWCOMER_WELFARE = "NEWCOMER_WELFARE";//新人福利 + public final static String IS_SHOW_DIALOG = "IS_SHOW_DIALOG";//首充、快捷充值是否弹出 + public final static String MARKET_STATUS = "MARKET_STATUS";// 应用市场版本提审状态:0=提审中 1=已上架 + public final static String CUSTOMER_TAG_STICKY = "CUSTOMER_TAG_STICKY";//取消默认客服置顶 + public final static String USER_MOBILE = "USER_MOBILE"; + public final static String IS_FIRST_RECHARGE = "IS_FIRST_RECHARGE"; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ToastHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ToastHelper.java new file mode 100644 index 0000000..f2a0543 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ToastHelper.java @@ -0,0 +1,55 @@ +package com.fengliyan.tianlesue.im.uikit.common; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.widget.Toast; + + +public class ToastHelper { + + private static Toast sToast ; + + + private ToastHelper(){ + + } + + public static void showToast(Context context , String text){ + showToastInner(context,text,Toast.LENGTH_SHORT); + } + + public static void showToast(Context context , int stringId){ + showToastInner(context,context.getString(stringId),Toast.LENGTH_SHORT); + } + + + public static void showToastLong(Context context , String text ){ + showToastInner(context,text,Toast.LENGTH_LONG); + } + + public static void showToastLong(Context context , int stringId){ + showToastInner(context,context.getString(stringId),Toast.LENGTH_LONG); + } + + + private static void showToastInner(Context context , String text , int duration){ + ensureToast( context); + sToast.setText(text); + sToast.setDuration(duration); + sToast.show(); + } + + + @SuppressLint("ShowToast") + private static void ensureToast(Context context) { + if(sToast!=null){ + return; + } + synchronized (ToastHelper.class){ + if(sToast!=null) { + return; + } + sToast =Toast.makeText(context.getApplicationContext()," ",Toast.LENGTH_SHORT); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/ListActivityBase.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/ListActivityBase.java new file mode 100644 index 0000000..e8dd707 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/ListActivityBase.java @@ -0,0 +1,81 @@ +package com.fengliyan.tianlesue.im.uikit.common.activity; + +import android.os.Bundle; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.decoration.DividerItemDecoration; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener.OnItemClickListener; +import com.netease.nim.uikit.R; + +import java.util.List; + +import me.everything.android.ui.overscroll.OverScrollDecoratorHelper; + +/** + * 列表Activity抽象类 + *

+ * Created by huangjun on 2017/6/21. + */ + +public abstract class ListActivityBase extends UI { + + // interface + + protected abstract String getTitleString(); + + protected abstract List onLoadData(); + + protected abstract int onItemResId(); + + protected abstract void convertItem(BaseViewHolder helper, T item); + + protected abstract void onItemClick(T item); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_list_activity_layout); + + // toolbar + ToolBarOptions options = new NimToolBarOptions(); + options.titleString = getTitleString(); + setToolBar(R.id.toolbar, options); + + // RecyclerView + RecyclerView recyclerView = (RecyclerView) findViewById(R.id.data_list); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); + recyclerView.addOnItemTouchListener(new OnItemClickListener() { + @Override + public void onItemClick(Adapter adapter, View view, int position) { + ListActivityBase.this.onItemClick(adapter.getItem(position)); + } + }); + + // ios style + OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL); + + // adapter + final List data = onLoadData(); + final BaseQuickAdapter adapter = new Adapter(recyclerView, onItemResId(), data) { + @Override + protected void convert(BaseViewHolder helper, T item, int position, boolean isScrolling) { + convertItem(helper, item); + } + }; + recyclerView.setAdapter(adapter); + } + + abstract class Adapter extends BaseQuickAdapter { + + Adapter(RecyclerView recyclerView, final int layoutId, List data) { + super(recyclerView, layoutId, data); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/ToolBarOptions.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/ToolBarOptions.java new file mode 100644 index 0000000..08d2231 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/ToolBarOptions.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.im.uikit.common.activity; + +/** + * Created by hzxuwen on 2016/6/16. + */ +public class ToolBarOptions { + /** + * toolbar的title资源id + */ + public int titleId; + /** + * toolbar的title + */ + public String titleString; + /** + * toolbar的logo资源id + */ + public int logoId; + /** + * toolbar的返回按钮资源id + */ + public int navigateId; + /** + * toolbar的返回按钮 + */ + public boolean isNeedNavigate; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/UI.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/UI.java new file mode 100644 index 0000000..9f91b68 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/activity/UI.java @@ -0,0 +1,315 @@ +package com.fengliyan.tianlesue.im.uikit.common.activity; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.MenuItem; +import android.view.View; +import android.view.inputmethod.InputMethodManager; + +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import com.fengliyan.tianlesue.im.uikit.common.fragment.TFragment; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ReflectionUtil; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import java.util.ArrayList; +import java.util.List; + +public abstract class UI extends BaseActivity { + + private boolean destroyed = false; + + private static Handler handler; + + private Toolbar toolbar; + + @Override + protected void onStart() { + super.onStart(); + } + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + hideTitleBar(); + + LogUtil.ui("activity: " + getClass().getSimpleName() + " onCreate()"); + } + + @Override + public void initState(Activity mActivity, int color) { +// super.initState(mActivity, color); + } + + @Override + public void onBackPressed() { + invokeFragmentManagerNoteStateNotSaved(); + super.onBackPressed(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + LogUtil.ui("activity: " + getClass().getSimpleName() + " onDestroy()"); + destroyed = true; + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + onNavigateUpClicked(); + return true; + } + return super.onOptionsItemSelected(item); + } + + public void setToolBar(int toolBarId, ToolBarOptions options) { + toolbar = findViewById(toolBarId); + if (options.titleId != 0) { + toolbar.setTitle(options.titleId); + } + if (!TextUtils.isEmpty(options.titleString)) { + toolbar.setTitle(options.titleString); + } +// if (options.logoId != 0) { +// toolbar.setLogo(options.logoId); +// } + + setSupportActionBar(toolbar); + + if (options.isNeedNavigate) { + toolbar.setNavigationIcon(options.navigateId); + toolbar.setContentInsetStartWithNavigation(0); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onNavigateUpClicked(); + } + }); + } + } + + public void setToolBar(int toolbarId, int titleId, int logoId) { + toolbar = findViewById(toolbarId); + toolbar.setTitle(titleId); +// toolbar.setLogo(logoId); + setSupportActionBar(toolbar); + } + + public Toolbar getToolBar() { + return toolbar; + } + + public int getToolBarHeight() { + if (toolbar != null) { + return toolbar.getHeight(); + } + + return 0; + } + + public void onNavigateUpClicked() { + onBackPressed(); + } + + @Override + public void setTitle(CharSequence title) { + super.setTitle(title); + if (toolbar != null) { + toolbar.setTitle(title); + } + } + + public void setSubTitle(String subTitle) { + if (toolbar != null) { + toolbar.setSubtitle(subTitle); + } + } + + protected final Handler getHandler() { + if (handler == null) { + handler = new Handler(getMainLooper()); + } + return handler; + } + + protected void showKeyboard(boolean isShow) { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (isShow) { + if (getCurrentFocus() == null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } else { + imm.showSoftInput(getCurrentFocus(), 0); + } + } else { + if (getCurrentFocus() != null) { + imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + } + + /** + * 延时弹出键盘 + * + * @param focus 键盘的焦点项 + */ + protected void showKeyboardDelayed(View focus) { + final View viewToFocus = focus; + if (focus != null) { + focus.requestFocus(); + } + + getHandler().postDelayed(new Runnable() { + @Override + public void run() { + if (viewToFocus == null || viewToFocus.isFocused()) { + showKeyboard(true); + } + } + }, 200); + } + + + public boolean isDestroyedCompatible() { + if (Build.VERSION.SDK_INT >= 17) { + return isDestroyedCompatible17(); + } else { + return destroyed || super.isFinishing(); + } + } + + @TargetApi(17) + private boolean isDestroyedCompatible17() { + return super.isDestroyed(); + } + + /** + * fragment management + */ + public TFragment addFragment(TFragment fragment) { + List fragments = new ArrayList<>(1); + fragments.add(fragment); + + List fragments2 = addFragments(fragments); + return fragments2.get(0); + } + + public List addFragments(List fragments) { + List fragments2 = new ArrayList<>(fragments.size()); + + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction transaction = fm.beginTransaction(); + + boolean commit = false; + for (int i = 0; i < fragments.size(); i++) { + // install + TFragment fragment = fragments.get(i); + int id = fragment.getContainerId(); + + // exists + TFragment fragment2 = (TFragment) fm.findFragmentById(id); + + if (fragment2 == null) { + fragment2 = fragment; + transaction.add(id, fragment); + commit = true; + } + + fragments2.add(i, fragment2); + } + + if (commit) { + try { + transaction.commitAllowingStateLoss(); + } catch (Exception e) { + + } + } + + return fragments2; + } + + public TFragment switchContent(TFragment fragment) { + return switchContent(fragment, false); + } + + protected TFragment switchContent(TFragment fragment, boolean needAddToBackStack) { + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.replace(fragment.getContainerId(), fragment); + if (needAddToBackStack) { + fragmentTransaction.addToBackStack(null); + } + try { + fragmentTransaction.commitAllowingStateLoss(); + } catch (Exception e) { + + } + + return fragment; + } + + protected boolean displayHomeAsUpEnabled() { + return true; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_MENU: + return onMenuKeyDown(); + + default: + return super.onKeyDown(keyCode, event); + } + } + + protected boolean onMenuKeyDown() { + return false; + } + + private void invokeFragmentManagerNoteStateNotSaved() { + FragmentManager fm = getSupportFragmentManager(); + ReflectionUtil.invokeMethod(fm, "noteStateNotSaved", null); + } + + protected void switchFragmentContent(TFragment fragment) { + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction transaction = fm.beginTransaction(); + transaction.replace(fragment.getContainerId(), fragment); + try { + transaction.commitAllowingStateLoss(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + protected boolean isCompatible(int apiLevel) { + return Build.VERSION.SDK_INT >= apiLevel; + } + + protected T findView(int resId) { + return (T) (findViewById(resId)); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/IScrollStateListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/IScrollStateListener.java new file mode 100644 index 0000000..6f75e2f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/IScrollStateListener.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.common.adapter; + +public interface IScrollStateListener { + + /** + * move to scrap heap + */ + public void reclaim(); + + + /** + * on idle + */ + public void onImmutable(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/IViewReclaimer.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/IViewReclaimer.java new file mode 100644 index 0000000..e0c0ec2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/IViewReclaimer.java @@ -0,0 +1,12 @@ +package com.fengliyan.tianlesue.im.uikit.common.adapter; + +import android.view.View; + +public interface IViewReclaimer { + /** + * reclaim view + * + * @param view + */ + public void reclaimView(View view); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TAdapter.java new file mode 100644 index 0000000..b7046b5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TAdapter.java @@ -0,0 +1,168 @@ +package com.fengliyan.tianlesue.im.uikit.common.adapter; + + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class TAdapter extends BaseAdapter implements IViewReclaimer { + + protected final Context context; + + private final List items; + + private final TAdapterDelegate delegate; + + private final LayoutInflater inflater; + + private final Map, Integer> viewTypes; + + private Object tag; + + private boolean mutable; + + private Set listeners; + + public TAdapter(Context context, List items, TAdapterDelegate delegate) { + this.context = context; + this.items = items; + this.delegate = delegate; + this.inflater = LayoutInflater.from(context); + this.viewTypes = new HashMap, Integer>(getViewTypeCount()); + this.listeners = new HashSet(); + } + + @Override + public int getCount() { + return items == null ? 0 : items.size(); + } + + public T getItem(int position) { + return position < getCount() ? items.get(position) : null; + } + + public long getItemId(int position) { + return position; + } + + public boolean isEnabled(int position) { + return delegate.enabled(position); + } + + public List getItems() { + return items; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + return getView(position, convertView, parent, true); + } + + public View getView(final int position, View convertView, ViewGroup parent, boolean needRefresh) { + if (convertView == null) { + convertView = viewAtPosition(position); + } + + TViewHolder holder = (TViewHolder) convertView.getTag(); + holder.setPosition(position); + if (needRefresh) { + try { + holder.refresh(getItem(position)); + } catch (RuntimeException e) { + LogUtil.e("TAdapter", "refresh viewholder error. " + e.getMessage()); + } + } + + if (holder instanceof IScrollStateListener) { + listeners.add(holder); + } + + return convertView; + } + + @Override + public int getViewTypeCount() { + return delegate.getViewTypeCount(); + } + + @Override + public int getItemViewType(int position) { + if (getViewTypeCount() == 1) { + return 0; + } + + Class clazz = delegate.viewHolderAtPosition(position); + if (viewTypes.containsKey(clazz)) { + return viewTypes.get(clazz); + } else { + int type = viewTypes.size(); + if (type < getViewTypeCount()) { + viewTypes.put(clazz, type); + return type; + } + return 0; + } + } + + @Override + public void reclaimView(View view) { + if (view == null) { + return; + } + + TViewHolder holder = (TViewHolder) view.getTag(); + if (holder != null) { + holder.reclaim(); + listeners.remove(holder); + } + } + + public void onMutable(boolean mutable) { + boolean becomeImmutable = this.mutable && !mutable; + this.mutable = mutable; + if (becomeImmutable) { + for (IScrollStateListener listener : listeners) { + listener.onImmutable(); + } + listeners.clear(); + } + } + + public boolean isMutable() { + return mutable; + } + + public View viewAtPosition(int position) { + TViewHolder holder = null; + View view = null; + try { + Class viewHolder = delegate.viewHolderAtPosition(position); + holder = (TViewHolder) viewHolder.newInstance(); + holder.setAdapter(this); + } catch (Exception e) { + e.printStackTrace(); + } + view = holder.getView(inflater); + view.setTag(holder); + holder.setContext(view.getContext()); + return view; + } + + public Object getTag() { + return tag; + } + + public void setTag(Object tag) { + this.tag = tag; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TAdapterDelegate.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TAdapterDelegate.java new file mode 100644 index 0000000..d3e58c2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TAdapterDelegate.java @@ -0,0 +1,10 @@ +package com.fengliyan.tianlesue.im.uikit.common.adapter; + +public interface TAdapterDelegate { + + public int getViewTypeCount(); + + public Class viewHolderAtPosition(int position); + + public boolean enabled(int position); +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TViewHolder.java new file mode 100644 index 0000000..1bcbe07 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/adapter/TViewHolder.java @@ -0,0 +1,100 @@ +package com.fengliyan.tianlesue.im.uikit.common.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.fragment.app.Fragment; + +public abstract class TViewHolder implements IScrollStateListener { + /** + * context + */ + protected Context context; + + /** + * fragment + */ + protected Fragment fragment; + + /** + * list item view + */ + protected View view; + + /** + * adapter providing data + */ + protected TAdapter adapter; + + /** + * index of item + */ + protected int position; + + public TViewHolder() { + + } + + protected void setFragment(Fragment fragment) { + this.fragment = fragment; + } + + protected void setContext(Context context) { + + this.context = context; + } + + protected void setAdapter(TAdapter adapter) { + this.adapter = adapter; + } + + protected TAdapter getAdapter() { + return this.adapter; + } + + protected void setPosition(int position) { + this.position = position; + } + + public View getView(LayoutInflater inflater) { + int resId = getResId(); + view = inflater.inflate(resId, null); + inflate(); + return view; + } + + public boolean isFirstItem() { + return position == 0; + } + + public boolean isLastItem() { + return position == adapter.getCount() - 1; + } + + protected abstract int getResId(); + + protected abstract void inflate(); + + protected abstract void refresh(Object item); + + @Override + public void reclaim() { + } + + @Override + public void onImmutable() { + } + + protected boolean mutable() { + return adapter.isMutable(); + } + + public void destory() { + + } + + protected T findView(int resId) { + return (T) (view.findViewById(resId)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/badger/Badger.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/badger/Badger.java new file mode 100644 index 0000000..294c35b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/badger/Badger.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.im.uikit.common.badger; + +import android.os.Build; +import android.os.Handler; +import android.util.Log; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.framework.infra.Handlers; + +import me.leolin.shortcutbadger.ShortcutBadger; + +/** + * APP图标未读数红点更新接口 + * https://github.com/leolin310148/ShortcutBadger + *

+ * Created by huangjun on 2017/7/25. + */ + +public class Badger { + private static final String TAG = "Badger"; + + private static Handler handler; + + private static boolean support = false; + + static { + support = Build.VERSION.SDK_INT < Build.VERSION_CODES.O; + } + + public static void updateBadgerCount(final int unreadCount) { + if (!support) { + return; // O版本及以上不再支持 + } + + if (handler == null) { + handler = Handlers.sharedInstance().newHandler("Badger"); + } + + handler.removeCallbacksAndMessages(null); + handler.postDelayed(new Runnable() { + @Override + public void run() { + int badgerCount = unreadCount; + if (badgerCount < 0) { + badgerCount = 0; + } else if (badgerCount > 99) { + badgerCount = 99; + } + + boolean res = ShortcutBadger.applyCount(NimUIKit.getContext(), badgerCount); + if (!res) { + support = false; // 如果失败就不要再使用了! + } + Log.i(TAG, "update badger count " + (res ? "success" : "failed")); + } + }, 200); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/fragment/TFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/fragment/TFragment.java new file mode 100644 index 0000000..717c9ac --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/fragment/TFragment.java @@ -0,0 +1,141 @@ +package com.fengliyan.tianlesue.im.uikit.common.fragment; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.view.inputmethod.InputMethodManager; + +import androidx.fragment.app.Fragment; + +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; + +public abstract class TFragment extends Fragment { + private static final Handler handler = new Handler(); + + private int containerId; + + private boolean destroyed; + + protected final boolean isDestroyed() { + return destroyed; + } + + public int getContainerId() { + return containerId; + } + + public void setContainerId(int containerId) { + this.containerId = containerId; + } + + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + LogUtil.ui("fragment: " + getClass().getSimpleName() + " onActivityCreated()"); + + destroyed = false; + } + + public void onDestroy() { + super.onDestroy(); + + LogUtil.ui("fragment: " + getClass().getSimpleName() + " onDestroy()"); + + destroyed = true; + } + + protected final Handler getHandler() { + return handler; + } + + protected final void postRunnable(final Runnable runnable) { + handler.post(new Runnable() { + @Override + public void run() { + // validate + if (!isAdded()) { + return; + } + + // run + runnable.run(); + } + }); + } + + protected final void postDelayed(final Runnable runnable, long delay) { + handler.postDelayed(new Runnable() { + @Override + public void run() { + // validate + if (!isAdded()) { + return; + } + + // run + runnable.run(); + } + }, delay); + } + + protected void showKeyboard(boolean isShow) { + Activity activity = getActivity(); + if (activity == null) { + return; + } + + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + + if (isShow) { + if (activity.getCurrentFocus() == null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } else { + imm.showSoftInput(activity.getCurrentFocus(), 0); + } + } else { + if (activity.getCurrentFocus() != null) { + imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), + InputMethodManager.HIDE_NOT_ALWAYS); + } + + } + } + + protected void hideKeyboard(View view) { + Activity activity = getActivity(); + if (activity == null) { + return; + } + + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + + imm.hideSoftInputFromWindow( + view.getWindowToken(), + InputMethodManager.HIDE_NOT_ALWAYS); + } + + protected T findView(int resId) { + return (T) (getView().findViewById(resId)); + } + + protected void setToolBar(int toolbarId, int titleId, int logoId) { + if (getActivity() != null && getActivity() instanceof UI) { + ((UI) getActivity()).setToolBar(toolbarId, titleId, logoId); + } + } + + protected void setTitle(int titleId) { + if (getActivity() != null && getActivity() instanceof UI) { + getActivity().setTitle(titleId); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/fragment/TabFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/fragment/TabFragment.java new file mode 100644 index 0000000..56466ae --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/fragment/TabFragment.java @@ -0,0 +1,52 @@ +package com.fengliyan.tianlesue.im.uikit.common.fragment; + +public abstract class TabFragment extends TFragment { + + public interface State { + public boolean isCurrent(TabFragment fragment); + } + + private State state; + + public void setState(State state) { + this.state = state; + } + + /** + * is current + * + * @return + */ + protected final boolean isCurrent() { + return state.isCurrent(this); + } + + /** + * notify current + */ + public void onCurrent() { + // NO OP + } + + /** + * leave current page + */ + public void onLeave() { + + } + + /** + * notify current scrolled + */ + public void onCurrentScrolled() { + // NO OP + } + + public void onCurrentTabClicked() { + // NO OP + } + + public void onCurrentTabDoubleTap() { + // NO OP + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/NimSingleThreadExecutor.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/NimSingleThreadExecutor.java new file mode 100644 index 0000000..bca8214 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/NimSingleThreadExecutor.java @@ -0,0 +1,76 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework; + +import android.os.Handler; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +/** + * Created by huangjun on 2015/3/12. + */ +public class NimSingleThreadExecutor { + + private static NimSingleThreadExecutor instance; + + private Handler uiHandler; + private Executor executor; + + private NimSingleThreadExecutor() { + uiHandler = new Handler(NimUIKit.getContext().getMainLooper()); + executor = Executors.newSingleThreadExecutor(); + } + + public synchronized static NimSingleThreadExecutor getInstance() { + if (instance == null) { + instance = new NimSingleThreadExecutor(); + } + + return instance; + } + + public void execute(NimTask task) { + if (executor != null) { + executor.execute(new NimRunnable<>(task)); + } + } + + public void execute(Runnable runnable) { + if (executor != null) { + executor.execute(runnable); + } + } + + /** + * ****************** model ************************* + */ + + public interface NimTask { + T runInBackground(); + + void onCompleted(T result); + } + + private class NimRunnable implements Runnable { + + public NimRunnable(NimTask task) { + this.task = task; + } + + private NimTask task; + + @Override + public void run() { + final T res = task.runInBackground(); + if (uiHandler != null) { + uiHandler.post(new Runnable() { + @Override + public void run() { + task.onCompleted(res); + } + }); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/NimTaskExecutor.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/NimTaskExecutor.java new file mode 100644 index 0000000..b75674d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/NimTaskExecutor.java @@ -0,0 +1,165 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework; + +import android.annotation.TargetApi; +import android.os.Build; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class NimTaskExecutor implements Executor { + + private final static int QUEUE_INIT_CAPACITY = 20; + + public static final Executor IMMEDIATE_EXECUTOR = new Executor() { + @Override + public void execute(Runnable command) { + command.run(); + } + }; + + public static class Config { + public int core; + public int max; + public int timeout; + public boolean allowCoreTimeOut; + + public Config(int core, int max, int timeout, boolean allowCoreTimeOut) { + this.core = core; + this.max = max; + this.timeout = timeout; + this.allowCoreTimeOut = allowCoreTimeOut; + } + } + + private final String name; + + private final Config config; + + private ExecutorService service; + + public NimTaskExecutor(String name, Config config) { + this(name, config, true); + } + + public NimTaskExecutor(String name, Config config, boolean startup) { + this.name = name; + this.config = config; + + if (startup) { + startup(); + } + } + + public void startup() { + synchronized (this) { + // has startup + if (service != null && !service.isShutdown()) { + return; + } + + // create + service = createExecutor(config); + } + } + + public void shutdown() { + ExecutorService executor = null; + + synchronized (this) { + // swap + if (service != null) { + executor = service; + service = null; + } + } + + if (executor != null) { + // shutdown + if (!executor.isShutdown()) { + executor.shutdown(); + } + + // recycle + executor = null; + } + } + + @Override + public void execute(Runnable runnable) { + synchronized (this) { + // has shutdown, reject + if (service == null || service.isShutdown()) { + return; + } + + // execute + service.execute(runnable); + } + } + + public Future submit(Runnable runnable) { + synchronized (this) { + if (service == null || service.isShutdown()) { + return null; + } + return service.submit(runnable); + } + } + + private ExecutorService createExecutor(Config config) { + ThreadPoolExecutor service = new ThreadPoolExecutor(config.core, config.max, config.timeout, + TimeUnit.MILLISECONDS, new LinkedBlockingQueue(QUEUE_INIT_CAPACITY), + new TaskThreadFactory(name), new ThreadPoolExecutor.DiscardPolicy()); + + allowCoreThreadTimeOut(service, config.allowCoreTimeOut); + + return service; + } + + static class TaskThreadFactory implements ThreadFactory { + private final ThreadGroup mThreadGroup; + + private final AtomicInteger mThreadNumber = new AtomicInteger(1); + + private final String mNamePrefix; + + TaskThreadFactory(String name) { + SecurityManager s = System.getSecurityManager(); + + mThreadGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); + + mNamePrefix = name + "#"; + } + + public Thread newThread(Runnable r) { + Thread t = new Thread(mThreadGroup, r, mNamePrefix + mThreadNumber.getAndIncrement(), 0); + + // no daemon + if (t.isDaemon()) + t.setDaemon(false); + + // normal priority + if (t.getPriority() != Thread.NORM_PRIORITY) + t.setPriority(Thread.NORM_PRIORITY); + + return t; + } + } + + private static final void allowCoreThreadTimeOut(ThreadPoolExecutor service, boolean value) { + if (Build.VERSION.SDK_INT >= 9) { + allowCoreThreadTimeOut9(service, value); + } + } + + @TargetApi(9) + private static final void allowCoreThreadTimeOut9(ThreadPoolExecutor service, boolean value) { + service.allowCoreThreadTimeOut(value); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/AbstractTaskWorker.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/AbstractTaskWorker.java new file mode 100644 index 0000000..32ddd73 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/AbstractTaskWorker.java @@ -0,0 +1,60 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.concurrent.Executor; + +public abstract class AbstractTaskWorker { + public interface ExecuteCallback { + public void onExecuted(Task task, boolean unschedule); + } + + /** + * execute callback + */ + private ExecuteCallback executeCallback; + + /** + * dispatch + * + * @param task + * @return Executor + */ + protected abstract Executor getTaskHost(Task task); + + public AbstractTaskWorker() { + + } + + public void setExecuteCallback(ExecuteCallback executeCallback) { + this.executeCallback = executeCallback; + } + + public void execute(Task task) { + getExecutor(task).execute(getRunnable(task)); + } + + private final Executor getExecutor(Task task) { + if (task.info.background) { + Executor executor = getTaskHost(task); + if (executor != null) { + return executor; + } + } + + return TaskExecutor.IMMEDIATE_EXECUTOR; + } + + private final Runnable getRunnable(final Task task) { + return new Runnable() { + @Override + public void run() { + // schedule + boolean unschedule = task.schedule(); + + // callback + if (executeCallback != null) { + executeCallback.onExecuted(task, unschedule); + } + } + }; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/CallbackWrapper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/CallbackWrapper.java new file mode 100644 index 0000000..d342f50 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/CallbackWrapper.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class CallbackWrapper implements TaskObserver { + protected T callback; + + public CallbackWrapper(T callback) { + this.callback = callback; + } + + @Override + public void onTaskResult(Task task, Object[] results) { + } + + @Override + public void onTaskProgress(Task task, Object[] params) { + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/CompoundTaskWorker.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/CompoundTaskWorker.java new file mode 100644 index 0000000..bbac860 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/CompoundTaskWorker.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.concurrent.Executor; + +public class CompoundTaskWorker extends AbstractTaskWorker { + private AbstractTaskWorker[] workers; + + public CompoundTaskWorker(AbstractTaskWorker... workers) { + this.workers = workers; + } + + protected int dispatch(Task task) { + return 0; + } + + @Override + protected Executor getTaskHost(Task task) { + int index = dispatch(task); + + if (index >= 0 && index < workers.length) { + return workers[index].getTaskHost(task); + } + + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTask.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTask.java new file mode 100644 index 0000000..be8e79b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTask.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public abstract class DefaultTask extends ManagedTask { + private DefaultTaskCallback callback; + + public DefaultTask(DefaultTaskCallback callback) { + this.callback = callback; + } + + @Override + protected void onTaskResult(Object[] results) { + if (results != null) { + notifyResult((Integer) results[0], results[1]); + } + } + + private void notifyResult(int result, Object attachment) { + if (callback != null) { + callback.onFinish(key(), result, attachment); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskCallback.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskCallback.java new file mode 100644 index 0000000..1690363 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskCallback.java @@ -0,0 +1,5 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public interface DefaultTaskCallback { + public void onFinish(String key, int result, Object attachment); +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskManager.java new file mode 100644 index 0000000..28c3751 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskManager.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class DefaultTaskManager extends TaskManager { + public DefaultTaskManager() { + this(new DefaultTaskWorker()); + } + + public DefaultTaskManager(String name) { + this(new DefaultTaskWorker(name)); + } + + public DefaultTaskManager(AbstractTaskWorker worker) { + super(new DefaultTaskScheduler(worker)); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskRegistry.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskRegistry.java new file mode 100644 index 0000000..dce2085 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskRegistry.java @@ -0,0 +1,71 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + +public class DefaultTaskRegistry implements TaskRegistry { + /** + * tasks + */ + public HashMap tasks = new HashMap(); + + @Override + public Task register(Task task) { + // key + String key = task.key(); + + synchronized (tasks) { + Task tsk = tasks.get(key); + + if (tsk == null) { + tsk = task; + + tasks.put(key, task); + } + + return tsk; + } + } + + @Override + public Task unregister(Task task) { + // key + String key = task.key(); + + synchronized (tasks) { + return tasks.remove(key); + } + } + + @Override + public boolean registered(Task task) { + // key + String key = task.key(); + + synchronized (tasks) { + return tasks.containsKey(key); + } + } + + @Override + public Task query(String key) { + synchronized (tasks) { + return tasks.get(key); + } + } + + @Override + public Collection queryAll() { + synchronized (tasks) { + return new ArrayList(tasks.values()); + } + } + + @Override + public int count() { + synchronized (tasks) { + return tasks.size(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskScheduler.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskScheduler.java new file mode 100644 index 0000000..a7d88b3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskScheduler.java @@ -0,0 +1,94 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import android.os.Handler; +import android.os.Looper; + +public class DefaultTaskScheduler implements TaskScheduler { + /** + * registry + */ + private final TaskRegistry registry = new DefaultTaskRegistry(); + + /** + * execute callback + */ + private final AbstractTaskWorker.ExecuteCallback executeCallback = new AbstractTaskWorker.ExecuteCallback() { + @Override + public void onExecuted(Task task, boolean unschedule) { + if (unschedule) { + unschedule(task); + } + } + }; + + /** + * worker + */ + private final AbstractTaskWorker worker; + + private final Handler handler; + + private static final Handler sharedHandler = new Handler(Looper.getMainLooper()); + + public DefaultTaskScheduler(AbstractTaskWorker worker) { + this(worker, sharedHandler); + } + + public DefaultTaskScheduler(AbstractTaskWorker worker, Handler handler) { + worker.setExecuteCallback(executeCallback); + + this.worker = worker; + this.handler = handler; + } + + @Override + public Task schedule(boolean background, String key, Task task, Object... params) { + // attach + task.info = new Task.Info(background, key, params); + task.state = new Task.State(); + task.handler = handler; + + // register + Task tsk = registry.register(task); + + if (task == tsk) { + // execute + worker.execute(task); + } + + return tsk; + } + + @Override + public void reschedule(Task task) { + if (registry.registered(task)) { + // execute + worker.execute(task); + } + } + + @Override + public void unschedule(Task task) { + registry.unregister(task); + } + + @Override + public Task scheduled(String key) { + return registry.query(key); + } + + @Override + public int count() { + return registry.count(); + } + + @Override + public void cancelAll() { + for (Task task : registry.queryAll()) { + if (task.scheduled() > 0) { + registry.unregister(task); + } + task.cancel(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskWorker.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskWorker.java new file mode 100644 index 0000000..c92281b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/DefaultTaskWorker.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class DefaultTaskWorker extends TaskWorker { + public DefaultTaskWorker() { + this("Default"); + } + + public DefaultTaskWorker(String name) { + this(name, TaskExecutor.defaultConfig); + } + + public DefaultTaskWorker(String name, TaskExecutor.Config config) { + super(new TaskExecutor("TW#" + name, config)); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Handlers.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Handlers.java new file mode 100644 index 0000000..3e49905 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Handlers.java @@ -0,0 +1,99 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import android.content.Context; +import android.os.Handler; +import android.os.HandlerThread; +import android.text.TextUtils; + +import java.util.HashMap; + +public final class Handlers { + public static final String DEFAULT_TAG = "Default"; + + private static Handlers instance; + + public static synchronized Handlers sharedInstance() { + if (instance == null) { + instance = new Handlers(); + } + + return instance; + } + + private static Handler sharedHandler; + + /** + * get shared handler for main looper + * + * @param context + * @return + */ + public static final Handler sharedHandler(Context context) { + /** + * duplicate handlers !!! i don't care + */ + + if (sharedHandler == null) { + sharedHandler = new Handler(context.getMainLooper()); + } + + return sharedHandler; + } + + /** + * get new handler for main looper + * + * @param context + * @return + */ + public static final Handler newHandler(Context context) { + return new Handler(context.getMainLooper()); + } + + private Handlers() { + + } + + /** + * get new handler for a background default looper + * + * @return + */ + public final Handler newHandler() { + return newHandler(DEFAULT_TAG); + } + + /** + * get new handler for a background stand alone looper identified by tag + * + * @param tag + * @return + */ + public final Handler newHandler(String tag) { + return new Handler(getHandlerThread(tag).getLooper()); + } + + private final HashMap threads = new HashMap(); + + private final HandlerThread getHandlerThread(String tag) { + HandlerThread handlerThread = null; + + synchronized (threads) { + handlerThread = threads.get(tag); + + if (handlerThread == null) { + handlerThread = new HandlerThread(nameOfTag(tag)); + + handlerThread.start(); + + threads.put(tag, handlerThread); + } + } + + return handlerThread; + } + + private final static String nameOfTag(String tag) { + return "HT-" + (TextUtils.isEmpty(tag) ? DEFAULT_TAG : tag); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/ManagedTask.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/ManagedTask.java new file mode 100644 index 0000000..76f2bb2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/ManagedTask.java @@ -0,0 +1,259 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; + +import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class ManagedTask extends ObservableTask { + private static final String TAG = "ManagedTask"; + private static final String ENCLOSURE = "()"; + + private static AtomicInteger serial = new AtomicInteger(); + + private TaskManager taskManager; + + private TaskObserver taskObserver; + + private final TaskObserver getTaskObserver() { + if (taskObserver == null) { + taskObserver = new TaskObserver() { + @Override + public void onTaskResult(Task task, Object[] results) { + if (!cancelled()) { + onDepTaskResult(task, results); + } + } + + @Override + public void onTaskProgress(Task task, Object[] params) { + if (!cancelled()) { + onDepTaskProgress(task, params); + } + } + }; + } + + return taskObserver; + } + + private ArrayList links = new ArrayList(); + + /** + * on task result + * + * @param results + */ + protected void onTaskResult(Object[] results) { + } + + /** + * on task progress + * + * @param params + */ + protected void onTaskProgress(Object[] params) { + } + + /** + * on dependent task result + * + * @param task + * @param results + */ + protected void onDepTaskResult(Task task, Object[] results) { + } + + /** + * on dependent task progress + * + * @param task + * @param params + */ + protected void onDepTaskProgress(Task task, Object[] params) { + } + + /** + * on task result + * + * @param results + */ + @Override + protected final void onPublishResult(Object[] results) { + // self + if (!cancelled()) { + onTaskResult(results); + } + notifyTaskResult(results); + + // links + synchronized (links) { + for (ManagedTask link : links) { + link.onPublishResult(results); + } + } + } + + /** + * on task progress + * + * @param params + */ + @Override + protected final void onPublishProgress(Object[] params) { + // self + if (!cancelled()) { + onTaskProgress(params); + } + notifyTaskProgress(params); + + // links + synchronized (links) { + for (ManagedTask link : links) { + link.onPublishProgress(params); + } + } + } + + /** + * attach task manager + * + * @param taskManager + */ + /*package*/ + final void attachTaskManager(TaskManager taskManager) { + this.taskManager = taskManager; + } + + /** + * an same task has been scheduled + * + * @param task + */ + /*package*/ + final void onSameTask(ManagedTask task) { + // link + task.link(this); + } + + /** + * make task key + * + * @param task + * @param params + * @return + */ + /*package*/ + static final String makeTaskKey(ManagedTask task, Object... params) { + String tag = task.getTaskTag(); + String id = task.getTaskId(); + String extraId = task.getTaskExtraId(params); + + StringBuilder sb = new StringBuilder(); + + // tag + sb.append("T"); + sb.append(ENCLOSURE.charAt(0)); + sb.append(tag); + sb.append(ENCLOSURE.charAt(1)); + + // id + sb.append("I"); + sb.append(ENCLOSURE.charAt(0)); + sb.append(id); + sb.append(ENCLOSURE.charAt(1)); + + // extra id + if (!TextUtils.isEmpty(extraId)) { + sb.append("E"); + sb.append(ENCLOSURE.charAt(0)); + sb.append(extraId); + sb.append(ENCLOSURE.charAt(1)); + } + + return sb.toString(); + } + + /** + * get task tag + * + * @return task tag + */ + protected String getTaskTag() { + return getClass().getSimpleName(); + } + + /** + * get task id + * + * @return task id + */ + protected String getTaskId() { + return Integer.toString(serial.getAndIncrement()); + } + + /** + * get task extra id + * + * @param params + * @return + */ + protected String getTaskExtraId(Object... params) { + return null; + } + + /** + * schedule task + * + * @param background + * @param task + * @param params + * @return task key + */ + protected String schedule(boolean background, ManagedTask task, Object... params) { + // register + task.registerObserver(getTaskObserver()); + + // execute + return taskManager.schedule(background, task, params); + } + + /** + * reschedule self + */ + protected void reschedule() { + taskManager.reschedule(this); + } + + /** + * cancel linked tasks recursively + */ + @Override + public void cancel() { + super.cancel(); + synchronized (links) { + for (ManagedTask link : links) { + link.cancel(); + } + } + } + + /** + * link task + * + * @param task + */ + private final void link(ManagedTask task) { + trace("link " + dump(true)); + + synchronized (links) { + links.add(task); + } + } + + private static final void trace(String msg) { + LogUtil.d(TAG, msg); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Observable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Observable.java new file mode 100644 index 0000000..a9cdcb0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Observable.java @@ -0,0 +1,53 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.ArrayList; +import java.util.List; + +public abstract class Observable { + protected final ArrayList mObservers = new ArrayList(); + + public void registerObserver(T observer) { + if (observer == null) { + return; + } + synchronized (mObservers) { + if (mObservers.contains(observer)) { + return; + } + mObservers.add(observer); + } + } + + public void unregisterObserver(T observer) { + if (observer == null) { + return; + } + synchronized (mObservers) { + int index = mObservers.indexOf(observer); + if (index == -1) { + return; + } + mObservers.remove(index); + } + } + + public void unregisterAll() { + synchronized (mObservers) { + mObservers.clear(); + } + } + + protected List getObservers() { + return getObservers(true); + } + + protected List getObservers(boolean sync) { + if (sync) { + synchronized (mObservers) { + return new ArrayList(mObservers); + } + } else { + return mObservers; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/ObservableTask.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/ObservableTask.java new file mode 100644 index 0000000..baeef2c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/ObservableTask.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public abstract class ObservableTask extends Task { + private TaskObservable observable = new TaskObservable(); + + /** + * register observer + * + * @param observer + */ + public void registerObserver(TaskObserver observer) { + observable.registerObserver(observer); + } + + /** + * unregister observer + * + * @param observer + */ + public void unregisterObserver(TaskObserver observer) { + observable.unregisterObserver(observer); + } + + /** + * notify task result + * + * @param results + */ + protected final void notifyTaskResult(Object[] results) { + // observable + observable.onTaskResult(this, results); + } + + /** + * notify task progress + * + * @param params + */ + protected final void notifyTaskProgress(Object[] params) { + // observable + observable.onTaskProgress(this, params); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Params.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Params.java new file mode 100644 index 0000000..cb7515f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Params.java @@ -0,0 +1,46 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public final class Params { + public static final int[] getDimension(Object[] params, int index, int[] def) { + if (params != null && params.length > index && params[index] != null) { + if (params[index] instanceof int[]) { + int[] param = (int[]) params[index]; + if (param.length > 1) { + return param; + } + } + } + + return def; + } + + public static final String getString(Object[] params, int index, String def) { + if (params != null && params.length > index && params[index] != null) { + if (params[index] instanceof String) { + String param = (String) params[index]; + return param; + } + } + + return def; + } + + public static final boolean getBoolean(Object[] params, int index, boolean def) { + if (params != null && params.length > index && params[index] != null) { + if (params[index] instanceof Boolean) { + Boolean param = (Boolean) params[index]; + return param; + } + } + + return def; + } + + public static final Object getObject(Object[] params, int index, Object def) { + if (params != null && params.length > index && params[index] != null) { + return params[index]; + } + + return def; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Task.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Task.java new file mode 100644 index 0000000..02358ef --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/Task.java @@ -0,0 +1,291 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import android.os.Handler; + +public abstract class Task { + private static final String ENCLOSURE = "<>"; + private static final int RETRY_COUNT = 1; + + /*package*/ static class Info { + /** + * background + */ + boolean background; + + /** + * key + */ + String key; + + /** + * parameters + */ + Object[] params; + + Info(boolean background, String key, Object[] params) { + this.background = background; + this.key = key; + this.params = params; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("B"); + sb.append(ENCLOSURE.charAt(0)); + sb.append(background ? "T" : "F"); + sb.append(ENCLOSURE.charAt(1)); + + sb.append(" "); + + sb.append("K"); + sb.append(ENCLOSURE.charAt(0)); + sb.append(key); + sb.append(ENCLOSURE.charAt(1)); + + return sb.toString(); + } + } + + /*package*/ static class State { + /** + * cancelled + */ + boolean cancelled; + + /** + * chances + */ + int chances; + + /** + * pending + */ + boolean pending; + + /** + * fault + */ + boolean fault; + + State() { + + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("C"); + sb.append(ENCLOSURE.charAt(0)); + sb.append(chances); + sb.append(ENCLOSURE.charAt(1)); + + sb.append(" "); + + sb.append("P"); + sb.append(ENCLOSURE.charAt(0)); + sb.append(pending ? "T" : "F"); + sb.append(ENCLOSURE.charAt(1)); + + return sb.toString(); + } + } + + /** + * handler for publish states + */ + /*package*/ Handler handler; + + /** + * task info + */ + /*package*/ Info info; + + /** + * task state + */ + /*package*/ State state; + + public void cancel() { + state.cancelled = true; + } + + public void setProperty(int prop, Object data) { + // NOP + } + + protected boolean background() { + return info.background; + } + + protected String key() { + return info.key; + } + + protected Object[] params() { + return info.params; + } + + protected boolean cancelled() { + return state.cancelled; + } + + protected int scheduled() { + return state.chances; + } + + protected void pending() { + state.pending = true; + } + + protected boolean giveup() { + // give up + boolean giveup = scheduled() > RETRY_COUNT; + + // mark pending if proceed + if (!giveup) { + pending(); + } + + return giveup; + } + + /*package*/ boolean schedule() { + // update chances + state.chances++; + // reset pending + state.pending = false; + + // execute + Object[] results = null; + try { + results = execute(info.params); + } catch (Throwable tr) { + onException(tr); + + // fault + state.fault = true; + } + + // no fault and pending + if (!state.fault && state.pending) { + // not proceed + return false; + } + + // publish result + publishResult(results); + + return true; + } + + /** + * execute + * + * @param params + * @return results + */ + protected abstract Object[] execute(Object[] params); + + /** + * on exception + * + * @param tr throwable + */ + protected void onException(Throwable tr) { + // save +// AppCrashHandler.getInstance(null).saveException(tr, false); + } + + ; + + /** + * on handle result + * + * @param results + */ + protected void onHandleResult(Object[] results) { + } + + ; + + /** + * on publish result + * + * @param results + */ + protected void onPublishResult(Object[] results) { + } + + /** + * on publish progress + * + * @param params + */ + protected void onPublishProgress(Object[] params) { + } + + /** + * publish result + * + * @param results + */ + protected final void publishResult(Object[] results) { + publish(true, results); + } + + /** + * publish progress + * + * @param params + */ + protected final void publishProgress(Object[] params) { + publish(false, params); + } + + private final void publish(final boolean result, final Object[] params) { + if (info.background && handler != null) { + // shift to looper thread of handler to publish + handler.post(new Runnable() { + @Override + public void run() { + // publish on current thread + onPublish(result, params); + } + }); + } else { + // publish on current thread + onPublish(result, params); + } + } + + private final void onPublish(boolean result, Object[] params) { + if (result) { + onHandleResult(params); + onPublishResult(params); + } else { + onPublishProgress(params); + } + } + + public final String dump(boolean statefull) { + StringBuilder sb = new StringBuilder(); + + // info + sb.append(info); + // state + if (statefull) { + sb.append(" "); + sb.append(state); + } + + return sb.toString(); + } + + @Override + public String toString() { + return dump(true); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskExecutor.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskExecutor.java new file mode 100644 index 0000000..48602d5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskExecutor.java @@ -0,0 +1,237 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import android.annotation.TargetApi; +import android.os.Build; + +import java.util.Comparator; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + + +public class TaskExecutor implements Executor { + private final static int QUEUE_INIT_CAPACITY = 11; + + private static final int CORE = 3; + + private static final int MAX = 5; + + private static final int TIMEOUT = 30 * 1000; + + public static final Executor IMMEDIATE_EXECUTOR = new Executor() { + @Override + public void execute(Runnable command) { + command.run(); + } + }; + + public static class Config { + public int core; + + public int max; + + public int timeout; + + public boolean allowCoreTimeOut; + + public Config(int core, int max, int timeout, boolean allowCoreTimeOut) { + this.core = core; + this.max = max; + this.timeout = timeout; + this.allowCoreTimeOut = allowCoreTimeOut; + } + } + + public static Config defaultConfig = new Config(CORE, MAX, TIMEOUT, true); + + private final String name; + + private final Config config; + + private ExecutorService service; + + public TaskExecutor(String name) { + this(name, defaultConfig); + } + + public TaskExecutor(String name, Config config) { + this(name, config, true); + } + + public TaskExecutor(String name, Config config, boolean startup) { + this.name = name; + this.config = config; + + if (startup) { + startup(); + } + } + + public void startup() { + synchronized (this) { + // has startup + if (service != null && !service.isShutdown()) { + return; + } + + // create + service = createExecutor(config); + } + } + + public void shutdown() { + ExecutorService executor = null; + + synchronized (this) { + // swap + if (service != null) { + executor = service; + service = null; + } + } + + if (executor != null) { + // shutdown + if (!executor.isShutdown()) { + executor.shutdown(); + } + + // recycle + executor = null; + } + } + + @Override + public void execute(Runnable runnable) { + // executeRunnable runnable with default priority + executeRunnable(new PRunnable(runnable, 0)); + } + + public Future submit(Runnable runnable) { + synchronized (this) { + if (service == null || service.isShutdown()) { + return null; + } + return service.submit(new PRunnable(runnable, 0)); + } + } + + public void execute(Runnable runnable, int priority) { + // executeRunnable runnable with priority + executeRunnable(new PRunnable(runnable, priority)); + } + + private void executeRunnable(Runnable runnable) { + synchronized (this) { + // has shutdown, reject + if (service == null || service.isShutdown()) { + return; + } + + // execute + service.execute(runnable); + } + } + + private ExecutorService createExecutor(Config config) { +// ThreadPoolExecutor service = new ThreadPoolExecutor(config.core, config.max, config.timeout, +// TimeUnit.MILLISECONDS, new PriorityBlockingQueue(QUEUE_INIT_CAPACITY, mQueueComparator), +// new TaskThreadFactory(name), new ThreadPoolExecutor.DiscardPolicy()); + + ThreadPoolExecutor service = new ThreadPoolExecutor(config.core, Integer.MAX_VALUE, config.timeout, + TimeUnit.MILLISECONDS, new PriorityBlockingQueue(QUEUE_INIT_CAPACITY, mQueueComparator), + new TaskThreadFactory(name), new ThreadPoolExecutor.DiscardPolicy()); + + allowCoreThreadTimeOut(service, config.allowCoreTimeOut); + + return service; + } + + private static class PRunnable implements Runnable { + private static int sSerial = 0; + + private Runnable runnable; + + private int priority; + + private int serial; + + public PRunnable(Runnable r, int p) { + serial = sSerial++; + runnable = r; + priority = p; + } + + @Override + public void run() { + if (runnable != null) { + runnable.run(); + } + } + + public static final int compare(PRunnable r1, PRunnable r2) { + if (r1.priority != r2.priority) { + return r2.priority - r1.priority; + } else { + return r1.serial - r2.serial; + } + } + } + + Comparator mQueueComparator = new Comparator() { + + @Override + public int compare(Runnable lhs, Runnable rhs) { + PRunnable r1 = (PRunnable) lhs; + PRunnable r2 = (PRunnable) rhs; + + return PRunnable.compare(r1, r2); + } + }; + + static class TaskThreadFactory implements ThreadFactory { + private final ThreadGroup mThreadGroup; + + private final AtomicInteger mThreadNumber = new AtomicInteger(1); + + private final String mNamePrefix; + + TaskThreadFactory(String name) { + SecurityManager s = System.getSecurityManager(); + + mThreadGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); + + mNamePrefix = name + "#"; + } + + public Thread newThread(Runnable r) { + Thread t = new Thread(mThreadGroup, r, mNamePrefix + mThreadNumber.getAndIncrement(), 0); + + // no daemon + if (t.isDaemon()) + t.setDaemon(false); + + // normal priority + if (t.getPriority() != Thread.NORM_PRIORITY) + t.setPriority(Thread.NORM_PRIORITY); + + return t; + } + } + + private static final void allowCoreThreadTimeOut(ThreadPoolExecutor service, boolean value) { + if (Build.VERSION.SDK_INT >= 9) { + allowCoreThreadTimeOut9(service, value); + } + } + + @TargetApi(9) + private static final void allowCoreThreadTimeOut9(ThreadPoolExecutor service, boolean value) { + service.allowCoreThreadTimeOut(value); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskFrequencyController.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskFrequencyController.java new file mode 100644 index 0000000..130b245 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskFrequencyController.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 控制任务执行频率,允许调用根据任务类型,设定最小的执行间隔。 + * 任务类型默认就是任务的类名,如果同一种任务需要再细分,由用户提供自定义的tag + */ +public class TaskFrequencyController { + + private static Map taskTime = new HashMap(); + + public static T runTask(ControllableTask task, int frequencyInS, T def) { + String key = makeKey(task); + Long lastTime = taskTime.get(key); + long current = new Date().getTime() / 1000; + if (lastTime != null && current - lastTime < frequencyInS) { + return def; + } + + taskTime.put(key, current); + return task.run(); + } + + public static boolean runTask(VoidControllableTask task, int frequencyInS) { + String key = makeKey(task); + Long lastTime = taskTime.get(key); + long current = new Date().getTime() / 1000; + if (lastTime != null && current - lastTime < frequencyInS) { + return false; + } + + taskTime.put(key, current); + task.run(); + return true; + } + + public static void reset() { + taskTime.clear(); + } + + private static interface IControllableTask { + public String tag(); + } + + public static abstract class ControllableTask implements IControllableTask { + public String tag() { + return getClass().getSimpleName(); + } + + public abstract T run(); + } + + public static abstract class VoidControllableTask implements IControllableTask { + public String tag() { + return getClass().getSimpleName(); + } + + public abstract void run(); + } + + private static String makeKey(IControllableTask task) { + return task.getClass().getName() + "#" + task.tag(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskManager.java new file mode 100644 index 0000000..3689583 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskManager.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class TaskManager { + /** + * task scheduler + */ + private TaskScheduler ts; + + private boolean shutdown = false; + + public TaskManager(TaskScheduler ts) { + this.ts = ts; + TaskManagerRegistry.register(this); + } + + public String schedule(ManagedTask task, Object... params) { + return schedule(true, task, params); + } + + public String schedule(boolean background, ManagedTask task, Object... params) { + // check state + if (shutdown) { + return null; + } + + // attach + task.attachTaskManager(this); + + // as task key + String key = ManagedTask.makeTaskKey(task, params); + + // execute + ManagedTask tsk = (ManagedTask) ts.schedule(background, key, task, params); + + // same + if (tsk != task) { + task.onSameTask(tsk); + } + + // result + return key; + } + + public void reschedule(ManagedTask task) { + // check state + if (shutdown) { + return; + } + + ts.reschedule(task); + } + + public boolean scheduled(String key) { + return ts.scheduled(key) != null; + } + + public int count() { + return ts.count(); + } + + public void cancel(String key) { + Task task = ts.scheduled(key); + + if (task != null) { + task.cancel(); + } + } + + public void shutdown() { + shutdown = true; + cancelAll(); + } + + public void cancelAll() { + ts.cancelAll(); + } + + public void setProperty(String key, int prop, Object data) { + Task task = ts.scheduled(key); + + if (task != null) { + task.setProperty(prop, data); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskManagerRegistry.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskManagerRegistry.java new file mode 100644 index 0000000..3c67b70 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskManagerRegistry.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import android.content.Context; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +public class TaskManagerRegistry { + private static List> managers = new ArrayList>(); + + public static void register(TaskManager manager) { + synchronized (managers) { + managers.add(new WeakReference(manager)); + } + } + + public static void waitAll(final Context context, final Runnable done, final int max, final int interval) { + cancelAll(true); + + Handlers.sharedHandler(context).postDelayed(new Runnable() { + int count; + + @Override + public void run() { + if (!idle() && count++ < max) { + Handlers.sharedHandler(context).postDelayed(this, interval); + } else { + done.run(); + } + } + }, interval); + } + + private static void cancelAll(boolean clear) { + synchronized (managers) { + for (int i = 0; i < managers.size(); ++i) { + TaskManager manager = managers.get(i).get(); + if (manager != null) { + manager.shutdown(); + } else { + managers.remove(i--); + } + } + + if (clear) { + managers.clear(); + } + } + } + + private static boolean idle() { + synchronized (managers) { + for (int i = 0; i < managers.size(); ++i) { + TaskManager manager = managers.get(i).get(); + if (manager != null) { + if (manager.count() > 0) { + return false; + } + } else { + managers.remove(i--); + } + } + } + return true; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskObservable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskObservable.java new file mode 100644 index 0000000..e745dd0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskObservable.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class TaskObservable extends Observable implements TaskObserver { + @Override + public void onTaskResult(Task task, Object[] results) { + for (TaskObserver observer : getObservers()) { + observer.onTaskResult(task, results); + } + } + + @Override + public void onTaskProgress(Task task, Object[] params) { + for (TaskObserver observer : getObservers()) { + observer.onTaskProgress(task, params); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskObserver.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskObserver.java new file mode 100644 index 0000000..92186aa --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskObserver.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public interface TaskObserver { + /** + * on task result + * + * @param task + * @param results + */ + public void onTaskResult(Task task, Object[] results); + + /** + * on task progress + * + * @param task + * @param params + */ + public void onTaskProgress(Task task, Object[] params); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskRegistry.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskRegistry.java new file mode 100644 index 0000000..8ae93fd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskRegistry.java @@ -0,0 +1,51 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.Collection; + +public interface TaskRegistry { + /** + * register task + * + * @param task + * @return task registered + */ + public Task register(Task task); + + /** + * unregister task + * + * @param task + * @return task unregistered + */ + public Task unregister(Task task); + + /** + * task registered + * + * @param task + * @return registered + */ + public boolean registered(Task task); + + /** + * query task + * + * @param key + * @return task + */ + public Task query(String key); + + /** + * query all tasks registered + * + * @return + */ + public Collection queryAll(); + + /** + * count + * + * @return count + */ + public int count(); +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskScheduler.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskScheduler.java new file mode 100644 index 0000000..8e1d960 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskScheduler.java @@ -0,0 +1,48 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public interface TaskScheduler { + /** + * schedule + * + * @param background + * @param task + * @param key + * @param params + * @return scheduled task + */ + public Task schedule(boolean background, String key, Task task, Object... params); + + /** + * reschedule + * + * @param task + */ + public void reschedule(Task task); + + /** + * unschedule + * + * @param task + */ + public void unschedule(Task task); + + /** + * scheduled + * + * @param key + * @return Task + */ + public Task scheduled(String key); + + /** + * count + * + * @return count + */ + public int count(); + + /** + * cancelAll + */ + public void cancelAll(); +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskWorker.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskWorker.java new file mode 100644 index 0000000..e04a5b6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TaskWorker.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.concurrent.Executor; + +public class TaskWorker extends AbstractTaskWorker { + /** + * executor + */ + private Executor executor; + + public TaskWorker(Executor executor) { + this.executor = executor; + } + + @Override + protected Executor getTaskHost(Task task) { + return executor; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TraceTaskRegistry.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TraceTaskRegistry.java new file mode 100644 index 0000000..8ef254e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TraceTaskRegistry.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class TraceTaskRegistry extends WrapTaskRegistry { + public TraceTaskRegistry(TaskRegistry wrap) { + super(wrap); + } + + @Override + public Task register(Task task) { + Task tsk = super.register(task); + + if (tsk == task) { + trace("register " + tsk.dump(false)); + } + + return tsk; + } + + @Override + public Task unregister(Task task) { + Task tsk = super.unregister(task); + + if (tsk != null) { + trace("unregister " + tsk.dump(false)); + } + + return tsk; + } + + private final void trace(String msg) { + + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TraceTaskScheduler.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TraceTaskScheduler.java new file mode 100644 index 0000000..91f1437 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/TraceTaskScheduler.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class TraceTaskScheduler extends WrapTaskScheduler { + public TraceTaskScheduler(TaskScheduler wrap) { + super(wrap); + } + + @Override + public void reschedule(Task task) { + trace("reschedule " + task.dump(true)); + + super.reschedule(task); + } + + private final void trace(String msg) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/WrapTaskRegistry.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/WrapTaskRegistry.java new file mode 100644 index 0000000..588601e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/WrapTaskRegistry.java @@ -0,0 +1,41 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +import java.util.Collection; + +public class WrapTaskRegistry implements TaskRegistry { + private TaskRegistry wrap; + + public WrapTaskRegistry(TaskRegistry wrap) { + this.wrap = wrap; + } + + @Override + public Task register(Task task) { + return wrap.register(task); + } + + @Override + public Task unregister(Task task) { + return wrap.unregister(task); + } + + @Override + public boolean registered(Task task) { + return wrap.registered(task); + } + + @Override + public Task query(String key) { + return wrap.query(key); + } + + @Override + public Collection queryAll() { + return wrap.queryAll(); + } + + @Override + public int count() { + return wrap.count(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/WrapTaskScheduler.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/WrapTaskScheduler.java new file mode 100644 index 0000000..f3480c2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/framework/infra/WrapTaskScheduler.java @@ -0,0 +1,39 @@ +package com.fengliyan.tianlesue.im.uikit.common.framework.infra; + +public class WrapTaskScheduler implements TaskScheduler { + private TaskScheduler wrap; + + public WrapTaskScheduler(TaskScheduler wrap) { + this.wrap = wrap; + } + + @Override + public Task schedule(boolean background, String key, Task task, Object... params) { + return wrap.schedule(background, key, task, params); + } + + @Override + public void reschedule(Task task) { + wrap.reschedule(task); + } + + @Override + public void unschedule(Task task) { + wrap.unschedule(task); + } + + @Override + public Task scheduled(String key) { + return wrap.scheduled(key); + } + + @Override + public int count() { + return wrap.count(); + } + + @Override + public void cancelAll() { + wrap.cancelAll(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/http/HttpClientWrapper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/http/HttpClientWrapper.java new file mode 100644 index 0000000..4549906 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/http/HttpClientWrapper.java @@ -0,0 +1,223 @@ +package com.fengliyan.tianlesue.im.uikit.common.http; + +import com.alibaba.fastjson.JSONObject; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Map; + +/** + * Created by huangjun on 2016/11/21. + */ + +public class HttpClientWrapper { + + private static final String TAG = "http"; + + private static final Integer TIMEOUT = 30 * 1000; // 允许反射修此常量,如果是基本类型,那么编译时会被优化直接替换,运行时无法在修改。 + private static final int BUFFER_SIZE = 1024; + private static final int RES_CODE_SUCCESS = 200; + private static final String CHARSET = "UTF-8"; + private static final String HTTP_GET = "GET"; + private static final String HTTP_POST = "POST"; + + public static class HttpResult { + public int code; + public Throwable e; + public T obj; + + public HttpResult() { + this.code = 0; + e = null; + obj = null; + } + } + + public static String buildRequestParams(Map params) { + if (params == null) { + return null; + } + + StringBuilder result = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + result.append("&").append(entry.getKey()).append("=").append(entry.getValue()); + } + + return result.toString(); + } + + public static HttpResult get(final String urlStr, final Map headers) { + LogUtil.d(TAG, "http get url=" + urlStr); + HttpResult result = new HttpResult<>(); + + HttpURLConnection urlConnection = null; + try { + // conn + urlConnection = buildGet(urlStr, headers); + + // request + int resCode = result.code = urlConnection.getResponseCode(); // 开始连接并发送数据 + + // response + if (resCode == RES_CODE_SUCCESS) { + result.obj = buildString(urlConnection.getInputStream()); + LogUtil.d(TAG, "http get success, result=" + result.obj + ", url=" + urlStr); + } else { + LogUtil.e(TAG, "http get failed, code=" + resCode + ", url=" + urlStr); + } + } catch (IOException e) { + e.printStackTrace(); + result.e = e; + LogUtil.e(TAG, "http get error, e=" + e.getMessage() + ", url=" + urlStr); + } finally { + if (urlConnection != null) { + urlConnection.disconnect(); + } + } + + return result; + } + + public static HttpResult post(final String urlStr, final Map headers, T body) { + LogUtil.d(TAG, "http post url=" + urlStr); + HttpResult result = new HttpResult<>(); + + HttpURLConnection urlConnection = null; + try { + // conn + urlConnection = buildPost(urlStr, headers, body); // os.flush 开始建立连接 + + // request + int resCode = result.code = urlConnection.getResponseCode(); // 开始发送数据 + + // response + if (resCode == RES_CODE_SUCCESS) { + result.obj = buildString(urlConnection.getInputStream()); + LogUtil.d(TAG, "http post success, result=" + result + ", url=" + urlStr); + } else { + LogUtil.e(TAG, "http post failed, code=" + resCode + ", url=" + urlStr); + } + } catch (IOException e) { + e.printStackTrace(); + result.e = e; + LogUtil.e(TAG, "http post error, e=" + e.getMessage() + ", url=" + urlStr); + } finally { + if (urlConnection != null) { + urlConnection.disconnect(); + } + } + + return result; + } + + private static HttpURLConnection buildGet(String urlStr, final Map headers) throws IOException { + URL url = new URL(urlStr); // URLEncoder.encode(param, "UTF-8") + + // conn + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); + configUrlConnection(urlConnection); + urlConnection.setRequestMethod(HTTP_GET); + + // headers + buildHeaders(urlConnection, headers); + + return urlConnection; + } + + private static HttpURLConnection buildPost(String urlStr, final Map headers, T body) throws IOException { + URL url = new URL(urlStr); + + // conn + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); + configUrlConnection(urlConnection); + urlConnection.setRequestMethod(HTTP_POST); + urlConnection.setDoOutput(true); + urlConnection.setDoInput(true); + + // headers + buildHeaders(urlConnection, headers); + + // json body + buildJsonHeaders(urlConnection, body); + + // body + OutputStream os = urlConnection.getOutputStream(); + DataOutputStream out = new DataOutputStream(os); + IOException exception = null; + try { + if (body instanceof String) { + out.write(((String) body).getBytes(CHARSET)); + } else if (body instanceof byte[]) { + out.write((byte[]) body); + } else if (body instanceof JSONObject) { + out.write(((JSONObject) body).toJSONString().getBytes(CHARSET)); + } else if (body instanceof org.json.JSONObject) { + out.write(body.toString().getBytes(CHARSET)); + } + os.flush(); // 开始与对方建立三次握手。 + } catch (IOException e) { + exception = e; + } finally { + out.close(); + os.close(); + } + + if (exception != null) { + throw exception; + } + + return urlConnection; + } + + private static void configUrlConnection(HttpURLConnection urlConnection) { + urlConnection.setReadTimeout(TIMEOUT); + urlConnection.setConnectTimeout(TIMEOUT); + urlConnection.setUseCaches(false); + } + + private static void buildHeaders(HttpURLConnection urlConnection, final Map headers) { + // common + urlConnection.setRequestProperty("charset", CHARSET); + + // custom + if (headers != null) { + for (String key : headers.keySet()) { + urlConnection.setRequestProperty(key, headers.get(key)); + } + } + } + + private static void buildJsonHeaders(HttpURLConnection urlConnection, T body) { + if (body instanceof JSONObject || body instanceof org.json.JSONObject) { + urlConnection.setRequestProperty("Content-Type", "application/json"); + } + } + + private static String buildString(final InputStream is) throws IOException { + if (is == null) { + return null; + } + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + int len; + byte buffer[] = new byte[BUFFER_SIZE]; + while ((len = is.read(buffer)) != -1) { + os.write(buffer, 0, len); + } + } catch (IOException e) { + throw e; + } finally { + is.close(); + os.close(); + } + + return new String(os.toByteArray(), CHARSET); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/http/NimHttpClient.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/http/NimHttpClient.java new file mode 100644 index 0000000..f9e0f52 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/http/NimHttpClient.java @@ -0,0 +1,114 @@ +package com.fengliyan.tianlesue.im.uikit.common.http; + +import android.content.Context; +import android.os.Handler; + +import com.fengliyan.tianlesue.im.uikit.common.framework.NimTaskExecutor; + +import java.util.Map; + +/** + * Created by huangjun on 2015/3/6. + */ +public class NimHttpClient { + + /** + * *********************** Http Task & Callback ************************* + */ + public interface NimHttpCallback { + void onResponse(String response, int code, Throwable e); + } + + public class NimHttpTask implements Runnable { + + private String url; + private Map headers; + private String jsonBody; + private NimHttpCallback callback; + private boolean post; + + public NimHttpTask(String url, Map headers, String jsonBody, NimHttpCallback callback) { + this(url, headers, jsonBody, callback, true); + } + + public NimHttpTask(String url, Map headers, String jsonBody, NimHttpCallback callback, boolean post) { + this.url = url; + this.headers = headers; + this.jsonBody = jsonBody; + this.callback = callback; + this.post = post; + } + + @Override + public void run() { + final HttpClientWrapper.HttpResult result = post ? + HttpClientWrapper.post(url, headers, jsonBody) : HttpClientWrapper.get(url, headers); + + // do callback on ui thread + uiHandler.post(new Runnable() { + @Override + public void run() { + if (callback != null) { + callback.onResponse(result.obj, result.code, result.e); + } + } + }); + } + } + + /** + * ************************ Single instance ************************** + */ + private static NimHttpClient instance; + + public synchronized static NimHttpClient getInstance() { + if (instance == null) { + instance = new NimHttpClient(); + } + + return instance; + } + + private NimHttpClient() { + + } + + /** + * **************** Http Config & Thread pool & Http Client ****************** + */ + + private boolean inited = false; + + private NimTaskExecutor executor; + + private Handler uiHandler; + + public void init(Context context) { + if (inited) { + return; + } + + // init thread pool + executor = new NimTaskExecutor("NIM_HTTP_TASK_EXECUTOR", new NimTaskExecutor.Config(1, 3, 10 * 1000, true)); + uiHandler = new Handler(context.getMainLooper()); + inited = true; + } + + public void release() { + if (executor != null) { + executor.shutdown(); + } + } + + public void execute(String url, Map headers, String body, NimHttpCallback callback) { + execute(url, headers, body, true, callback); + } + + public void execute(String url, Map headers, String body, boolean post, NimHttpCallback callback) { + if (!inited) { + return; + } + + executor.execute(new NimHttpTask(url, headers, body, callback, post)); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/audioplayer/BaseAudioControl.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/audioplayer/BaseAudioControl.java new file mode 100644 index 0000000..fdd0ba8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/audioplayer/BaseAudioControl.java @@ -0,0 +1,361 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.audioplayer; + +import android.content.Context; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.os.Handler; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.media.player.AudioPlayer; +import com.netease.nimlib.sdk.media.player.OnPlayListener; + +abstract public class BaseAudioControl { + + interface AudioControllerState { + int stop = 0; + int ready = 1; + int playing = 2; + } + + private int state; + protected boolean isEarPhoneModeEnable = true; // 是否是听筒模式 + + public interface AudioControlListener { + //AudioControl准备就绪,已经postDelayed playRunnable,不等同于AudioPlayer已经开始播放 + public void onAudioControllerReady(Playable playable); + + /** + * 结束播放 + */ + public void onEndPlay(Playable playable); + + /** + * 显示播放过程中的进度条 + * + * @param curPosition 当前进度,如果传-1则自动获取进度 + */ + public void updatePlayingProgress(Playable playable, long curPosition); + } + + protected AudioControlListener audioControlListener; + + protected Context mContext; + protected AudioPlayer currentAudioPlayer; + protected Playable currentPlayable; + + protected boolean needSeek = false; + protected long seekPosition; + + private MediaPlayer mSuffixPlayer = null; + private boolean mSuffix = false; + protected Handler mHandler = new Handler(); + + private BasePlayerListener basePlayerListener = null; + + protected void setOnPlayListener(Playable playingPlayable, AudioControlListener audioControlListener) { + this.audioControlListener = audioControlListener; + + basePlayerListener = new BasePlayerListener(currentAudioPlayer, playingPlayable); + currentAudioPlayer.setOnPlayListener(basePlayerListener); + basePlayerListener.setAudioControlListener(audioControlListener); + } + + public void setEarPhoneModeEnable(boolean isEarPhoneModeEnable) { + this.isEarPhoneModeEnable = isEarPhoneModeEnable; +// if (isEarPhoneModeEnable) { +// updateAudioStreamType(AudioManager.STREAM_VOICE_CALL); +// } else { + updateAudioStreamType(AudioManager.STREAM_MUSIC); +// } + } + + @SuppressWarnings("unchecked") + public void changeAudioControlListener(AudioControlListener audioControlListener) { + this.audioControlListener = audioControlListener; + + if (isPlayingAudio()) { + OnPlayListener onPlayListener = currentAudioPlayer.getOnPlayListener(); + if (onPlayListener != null) { + ((BasePlayerListener) onPlayListener).setAudioControlListener(audioControlListener); + } + } + } + + public AudioControlListener getAudioControlListener() { + return audioControlListener; + } + + public BaseAudioControl(Context context, boolean suffix) { + this.mContext = context; + this.mSuffix = suffix; + } + + protected void playSuffix() { + if (mSuffix) { + mSuffixPlayer = MediaPlayer.create(mContext, R.raw.audio_end_tip); + mSuffixPlayer.setLooping(false); + mSuffixPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mSuffixPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + mSuffixPlayer.release(); + mSuffixPlayer = null; + } + }); + mSuffixPlayer.start(); + } + } + + protected boolean startAudio( + Playable playable, + AudioControlListener audioControlListener, + int audioStreamType, + boolean resetOrigAudioStreamType, + long delayMillis) { + String filePath = playable.getPath(); + if (TextUtils.isEmpty(filePath)) { + return false; + } + + //正在播放,停止播放 + if (isPlayingAudio()) { + stopAudio(); + //如果相等,就是同一个对象了 + if (currentPlayable.isAudioEqual(playable)) { + return false; + } + } + + state = AudioControllerState.stop; + + currentPlayable = playable; + currentAudioPlayer = new AudioPlayer(mContext); + currentAudioPlayer.setDataSource(filePath); + + setOnPlayListener(currentPlayable, audioControlListener); + + if (resetOrigAudioStreamType) { + this.origAudioStreamType = audioStreamType; + } + this.currentAudioStreamType = audioStreamType; + + mHandler.postDelayed(playRunnable, delayMillis); + + state = AudioControllerState.ready; + if (audioControlListener != null) { + audioControlListener.onAudioControllerReady(currentPlayable); + } + + return true; + } + + Runnable playRunnable = new Runnable() { + + @Override + public void run() { + if (currentAudioPlayer == null) { + LogUtil.audio("playRunnable run when currentAudioPlayer == null"); + return; + } + + currentAudioPlayer.start(currentAudioStreamType); + } + }; + + private int origAudioStreamType; + private int currentAudioStreamType; + + public int getCurrentAudioStreamType() { + return currentAudioStreamType; + } + + protected int getUserSettingAudioStreamType() { + // 听筒模式/扬声器模式 +// if (isEarPhoneModeEnable) { +// return AudioManager.STREAM_VOICE_CALL; +// } else { + return AudioManager.STREAM_MUSIC; +// } + } + + protected void resetAudioController(Playable playable) { + currentAudioPlayer.setOnPlayListener(null); + currentAudioPlayer = null; + + state = AudioControllerState.stop; + } + + //playing or ready + public boolean isPlayingAudio() { + if (currentAudioPlayer != null) { + return state == AudioControllerState.playing + || state == AudioControllerState.ready; + } else { + return false; + } + } + + //stop or cancel + public void stopAudio() { + if (state == AudioControllerState.playing) { + //playing->stop + currentAudioPlayer.stop(); + } else if (state == AudioControllerState.ready) { + //ready->cancel + mHandler.removeCallbacks(playRunnable); + resetAudioController(currentPlayable); + + if (audioControlListener != null) { + audioControlListener.onEndPlay(currentPlayable); + } + } + } + + public boolean updateAudioStreamType(int audioStreamType) { + if (!isPlayingAudio()) { + return false; + } + + if (audioStreamType == getCurrentAudioStreamType()) { + return false; + } + + changeAudioStreamType(audioStreamType); + return true; + } + + public boolean restoreAudioStreamType() { + if (!isPlayingAudio()) { + return false; + } + + if (origAudioStreamType == getCurrentAudioStreamType()) { + return false; + } + + changeAudioStreamType(origAudioStreamType); + return true; + } + + private void changeAudioStreamType(int audioStreamType) { + if (currentAudioPlayer.isPlaying()) { + seekPosition = currentAudioPlayer.getCurrentPosition(); + needSeek = true; + currentAudioStreamType = audioStreamType; + currentAudioPlayer.start(audioStreamType); + } else { + currentAudioStreamType = origAudioStreamType; + } + } + + public class BasePlayerListener implements OnPlayListener { + protected AudioPlayer listenerPlayingAudioPlayer; + protected Playable listenerPlayingPlayable; + protected AudioControlListener audioControlListener; + + public BasePlayerListener(AudioPlayer playingAudioPlayer, Playable playingPlayable) { + listenerPlayingAudioPlayer = playingAudioPlayer; + listenerPlayingPlayable = playingPlayable; + } + + public void setAudioControlListener(AudioControlListener audioControlListener) { + this.audioControlListener = audioControlListener; + } + + protected boolean checkAudioPlayerValid() { + if (currentAudioPlayer != listenerPlayingAudioPlayer) { + return false; + } + + return true; + } + + @Override + public void onPrepared() { + if (!checkAudioPlayerValid()) { + return; + } + + state = AudioControllerState.playing; + if (needSeek) { + needSeek = false; + listenerPlayingAudioPlayer.seekTo((int) seekPosition); + } + } + + @Override + public void onPlaying(long curPosition) { + if (!checkAudioPlayerValid()) { + return; + } + + if (audioControlListener != null) { + audioControlListener.updatePlayingProgress(listenerPlayingPlayable, curPosition); + } + } + + @Override + public void onInterrupt() { + if (!checkAudioPlayerValid()) { + return; + } + + resetAudioController(listenerPlayingPlayable); + if (audioControlListener != null) { + audioControlListener.onEndPlay(currentPlayable); + } + + } + + @Override + public void onError(String error) { + if (!checkAudioPlayerValid()) { + return; + } + + resetAudioController(listenerPlayingPlayable); + if (audioControlListener != null) { + audioControlListener.onEndPlay(currentPlayable); + } + } + + @Override + public void onCompletion() { + if (!checkAudioPlayerValid()) { + return; + } + + resetAudioController(listenerPlayingPlayable); + if (audioControlListener != null) { + audioControlListener.onEndPlay(currentPlayable); + } + + playSuffix(); + } + } + + ; + + public void startPlayAudio( + T t, + AudioControlListener audioControlListener) { + startPlayAudio(t, audioControlListener, getUserSettingAudioStreamType()); + } + + public void startPlayAudio( + T t, + AudioControlListener audioControlListener, + int audioStreamType) { + startPlayAudioDelay(0, t, audioControlListener, audioStreamType); + } + + public void startPlayAudioDelay(long delayMillis, T t, AudioControlListener audioControlListener) { + startPlayAudioDelay(delayMillis, t, audioControlListener, getUserSettingAudioStreamType()); + } + + public abstract void startPlayAudioDelay(long delayMillis, T t, AudioControlListener audioControlListener, int audioStreamType); + + public abstract T getPlayingAudio(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/audioplayer/Playable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/audioplayer/Playable.java new file mode 100644 index 0000000..81b0320 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/audioplayer/Playable.java @@ -0,0 +1,9 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.audioplayer; + +public interface Playable { + long getDuration(); + + String getPath(); + + boolean isAudioEqual(Playable audio); +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/dao/MediaDAO.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/dao/MediaDAO.java new file mode 100644 index 0000000..f371925 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/dao/MediaDAO.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.dao; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.provider.MediaStore; +import android.util.Log; + +public class MediaDAO { + private static final String TAG = "MediaDAO"; + + public static Cursor getAllMediaThumbnails(final Context context) { + final String[] projection = new String[]{ + MediaStore.Images.Thumbnails._ID, + MediaStore.Images.Thumbnails.IMAGE_ID, + MediaStore.Images.Thumbnails.DATA}; + final Uri images = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI; + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(images, projection, null, + null, MediaStore.Images.Thumbnails._ID + " DESC"); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "getAllMediaThumbnails exception"); + } + return cursor; + } + + public static Cursor getAllMediaPhotos(final Context context) { + final Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(images, null, null, + null, MediaStore.Images.Media.DATE_MODIFIED + " DESC"); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "getAllMediaPhotos exception"); + } + + return cursor; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/PickImageHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/PickImageHelper.java new file mode 100644 index 0000000..d3a5b77 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/PickImageHelper.java @@ -0,0 +1,151 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker; + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.activity.PickImageActivity; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.utils.PermissionUtil; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.netease.nim.uikit.R; + +import java.util.List; + +/** + * Created by huangjun on 2015/9/22. + */ +public class PickImageHelper { + + public static class PickImageOption { + /** + * 图片选择器标题 + */ + public int titleResId = R.string.choose; + + /** + * 是否多选 + */ + public boolean multiSelect = true; + + /** + * 最多选多少张图(多选时有效) + */ + public int multiSelectMaxCount = 9; + + /** + * 是否进行图片裁剪(图片选择模式:false / 图片裁剪模式:true) + */ + public boolean crop = false; + + /** + * 图片裁剪的宽度(裁剪模式时有效) + */ + public int cropOutputImageWidth = 720; + + /** + * 图片裁剪的高度(裁剪模式时有效) + */ + public int cropOutputImageHeight = 720; + + /** + * 图片选择保存路径 + */ + public String outputPath = StorageUtil.getWritePath(StringUtil.get32UUID() + ".jpg", StorageType.TYPE_TEMP); + } + + /** + * 打开图片选择器 + */ + public static void pickImage(final Context context, final int requestCode, final PickImageOption option) { + if (context == null) { + return; + } + + CustomAlertDialog dialog = new CustomAlertDialog(context); + dialog.setTitle(option.titleResId); + + dialog.addItem(context.getString(R.string.input_panel_take), new CustomAlertDialog.onSeparateItemClickListener() { + @Override + public void onClick() { + showPermissionDialog(context, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 0, requestCode, option); + } + }); + + dialog.addItem(context.getString(R.string.choose_from_photo_album), new CustomAlertDialog + .onSeparateItemClickListener() { + @Override + public void onClick() { + showPermissionDialog(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1, requestCode, option); + } + }); + + dialog.show(); + } + + private static void showPermissionDialog(Context context, String[] permission, int type, int requestCode, PickImageOption option) { + //权限允许 + PermissionDialog permissionDialog = new PermissionDialog(context, permission); + permissionDialog.show(); + XXPermissions.with(context) + .permission(permission) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + if (type == 0) { + int from = PickImageActivity.FROM_CAMERA; + if (!option.crop) { + PickImageActivity.start((Activity) context, requestCode, from, option.outputPath, option.multiSelect, 1, + true, false, 0, 0); + } else { + PickImageActivity.start((Activity) context, requestCode, from, option.outputPath, false, 1, + false, true, option.cropOutputImageWidth, option.cropOutputImageHeight); + } + } else { + int from = PickImageActivity.FROM_LOCAL; + if (!option.crop) { + PickImageActivity.start((Activity) context, requestCode, from, option.outputPath, option.multiSelect, + option.multiSelectMaxCount, true, false, 0, 0); + } else { + PickImageActivity.start((Activity) context, requestCode, from, option.outputPath, false, 1, + false, true, option.cropOutputImageWidth, option.cropOutputImageHeight); + } + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog customAlertDialog = new com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog(context); + customAlertDialog.setTitle("私语需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(context); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/CropImageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/CropImageActivity.java new file mode 100644 index 0000000..e2401b2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/CropImageActivity.java @@ -0,0 +1,115 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.activity; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.Handler; +import android.view.View; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.CropImageView; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; + + +public class CropImageActivity extends UI { + + public static final int PICKER_IMAGE_EDIT = 0x1040; + + private boolean returnData; + + private String filePath; + + private CropImageView cropImageView; + + public static void startForData(Activity activity, String srcFile, int outputX, int outputY, int requestCode) { + Intent intent = new Intent(activity, CropImageActivity.class); + intent.putExtra(Extras.EXTRA_SRC_FILE, srcFile); + intent.putExtra(Extras.EXTRA_OUTPUTX, outputX); + intent.putExtra(Extras.EXTRA_OUTPUTY, outputY); + intent.putExtra(Extras.EXTRA_RETURN_DATA, true); + activity.startActivityForResult(intent, requestCode); + } + + public static void startForFile(Activity activity, String srcFile, int outputX, int outputY, String path, + int requestCode) { + Intent intent = new Intent(activity, CropImageActivity.class); + intent.putExtra(Extras.EXTRA_SRC_FILE, srcFile); + intent.putExtra(Extras.EXTRA_OUTPUTX, outputX); + intent.putExtra(Extras.EXTRA_OUTPUTY, outputY); + intent.putExtra(Extras.EXTRA_FILE_PATH, path); + activity.startActivityForResult(intent, requestCode); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_crop_image_activity); + + ToolBarOptions options = new NimToolBarOptions(); + options.titleId = R.string.crop; + setToolBar(R.id.toolbar, options); + + processIntent(); + + initCropImageView(); + } + + @Override + public void onDestroy() { + cropImageView.clear(); + super.onDestroy(); + } + + private void processIntent() { + Intent intent = getIntent(); + returnData = intent.getBooleanExtra(Extras.EXTRA_RETURN_DATA, false); + filePath = intent.getStringExtra(Extras.EXTRA_FILE_PATH); + } + + private void initCropImageView() { + cropImageView = (CropImageView) findViewById(R.id.cropable_image_view); + Intent intent = getIntent(); + final String srcFile = intent.getStringExtra(Extras.EXTRA_SRC_FILE); + int outputX = intent.getIntExtra(Extras.EXTRA_OUTPUTX, 0); + int outputY = intent.getIntExtra(Extras.EXTRA_OUTPUTY, 0); + cropImageView.setOutput(outputX, outputY); + + // 抛到下一个UI循环,等到我们的activity真正到了前台 + // 否则可能会获取不到openGL的最大texture size,导致解出的bitmap过大,显示不了 + new Handler().post(new Runnable() { + @Override + public void run() { + Bitmap src = BitmapDecoder.decodeSampledForDisplay(srcFile); + src = ImageUtil.rotateBitmapInNeeded(srcFile, src); + cropImageView.setImageBitmap(src); + } + }); + } + + public void onClick(View v) { + if (v.getId() == R.id.ok_btn) { + if (returnData) { + byte[] data = cropImageView.getCroppedImage(); + if (data != null) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_DATA, data); + setResult(RESULT_OK, intent); + } + finish(); + } else { + if (cropImageView.saveCroppedImage(filePath)) { + setResult(RESULT_OK); + } + finish(); + } + } else if (v.getId() == R.id.cancel_btn) { + finish(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickImageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickImageActivity.java new file mode 100644 index 0000000..92948f5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickImageActivity.java @@ -0,0 +1,297 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.activity; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.provider.MediaStore; +import android.provider.MediaStore.Images; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.GenericFileProvider; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PickerContract; +import com.netease.nim.uikit.R; + +import java.io.File; +import java.util.List; + +public class PickImageActivity extends UI { + + private static final String KEY_STATE = "state"; + + public static final int FROM_LOCAL = 1; + + public static final int FROM_CAMERA = 2; + + private static final int REQUEST_CODE_CROP = 3; + + private static final int REQUEST_CODE_LOCAL = FROM_LOCAL; + + private static final int REQUEST_CODE_CAMERA = FROM_CAMERA; + + private boolean inited = false; + + public static void start(Activity activity, int requestCode, int from, String outPath) { + Intent intent = new Intent(activity, PickImageActivity.class); + intent.putExtra(Extras.EXTRA_FROM, from); + intent.putExtra(Extras.EXTRA_FILE_PATH, outPath); + activity.startActivityForResult(intent, requestCode); + } + + public static void start(Activity activity, int requestCode, int from, + String outPath, boolean mutiSelectMode, int multiSelectLimitSize, + boolean isSupportOrig, boolean crop, int outputX, int outputY) { + Intent intent = new Intent(activity, PickImageActivity.class); + intent.putExtra(Extras.EXTRA_FROM, from); + intent.putExtra(Extras.EXTRA_FILE_PATH, outPath); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_MODE, mutiSelectMode); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, multiSelectLimitSize); + intent.putExtra(Extras.EXTRA_SUPPORT_ORIGINAL, isSupportOrig); + intent.putExtra(Extras.EXTRA_NEED_CROP, crop); + intent.putExtra(Extras.EXTRA_OUTPUTX, outputX); + intent.putExtra(Extras.EXTRA_OUTPUTY, outputY); + activity.startActivityForResult(intent, requestCode); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_pick_image_activity); + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + } + + @Override + public void onResume() { + super.onResume(); + if (!inited) { + processIntent(); + inited = true; + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(KEY_STATE, inited); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + if (savedInstanceState != null) { + inited = savedInstanceState.getBoolean(KEY_STATE); + } + } + + private void processIntent() { + int from = getIntent().getIntExtra(Extras.EXTRA_FROM, FROM_LOCAL); + if (from == FROM_LOCAL) { + pickFromLocal(); + } else { + pickFromCamera(); + } + } + + private void pickFromLocal() { + Intent intent = pickIntent(); + if (intent == null) { + finish(); + return; + } + + try { + startActivityForResult(intent, REQUEST_CODE_LOCAL); + } catch (ActivityNotFoundException e) { + ToastHelper.showToastLong(this, R.string.gallery_invalid); + finish(); + } catch (Exception e) { + ToastHelper.showToastLong(this, R.string.sdcard_not_enough_head_error); + finish(); + } + } + + private void pickFromCamera() { + try { + String outPath = getIntent().getStringExtra(Extras.EXTRA_FILE_PATH); + if (TextUtils.isEmpty(outPath)) { + ToastHelper.showToastLong(this, R.string.sdcard_not_enough_error); + finish(); + return; + } + File outputFile = new File(outPath); + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (Build.VERSION.SDK_INT > 23) { + intent.putExtra(MediaStore.EXTRA_OUTPUT, GenericFileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".generic.file.provider", outputFile)); + } else { + intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputFile)); + } + startActivityForResult(intent, REQUEST_CODE_CAMERA); + } catch (ActivityNotFoundException e) { + finish(); + } catch (Exception e) { + ToastHelper.showToastLong(this, R.string.sdcard_not_enough_head_error); + finish(); + } + } + + private Intent pickIntent() { + Intent intent = getIntent(); + boolean mutiSelect = intent.getBooleanExtra(Extras.EXTRA_MUTI_SELECT_MODE, false); + int mutiSelectLimitSize = intent.getIntExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, 9); + boolean isSupportOrg = intent.getBooleanExtra(Extras.EXTRA_SUPPORT_ORIGINAL, false); + return makeLaunchIntent(this, mutiSelect, mutiSelectLimitSize, isSupportOrg); + } + + private Intent makeLaunchIntent(Context context, boolean mutiSelectMode, + int mutiSelectLimitSize, boolean isSupportOrig) { + Intent intent = new Intent(); + intent.setClass(context, PickerAlbumActivity.class); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_MODE, mutiSelectMode); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, + mutiSelectLimitSize); + intent.putExtra(Extras.EXTRA_SUPPORT_ORIGINAL, isSupportOrig); + + return intent; + } + + private String pathFromResult(Intent data) { + String outPath = getIntent().getStringExtra(Extras.EXTRA_FILE_PATH); + if (data == null || data.getData() == null) { + return outPath; + } + + Uri uri = data.getData(); + Cursor cursor = getContentResolver() + .query(uri, new String[]{Images.Media.DATA}, null, null, null); + if (cursor == null) { + // miui 2.3 有可能为null + return uri.getPath(); + } else { + if (uri.toString().contains("content://com.android.providers.media.documents/document/image")) { // htc 某些手机 + // 获取图片地址 + String _id = null; + String uridecode = uri.decode(uri.toString()); + int id_index = uridecode.lastIndexOf(":"); + _id = uridecode.substring(id_index + 1); + Cursor mcursor = getContentResolver().query(Images.Media.EXTERNAL_CONTENT_URI, null, " _id = " + _id, + null, null); + mcursor.moveToFirst(); + int column_index = mcursor.getColumnIndexOrThrow(Images.Media.DATA); + outPath = mcursor.getString(column_index); + if (!mcursor.isClosed()) { + mcursor.close(); + } + if (!cursor.isClosed()) { + cursor.close(); + } + return outPath; + + } else { + cursor.moveToFirst(); + int column_index = cursor.getColumnIndexOrThrow(Images.Media.DATA); + outPath = cursor.getString(column_index); + if (!cursor.isClosed()) { + cursor.close(); + } + return outPath; + } + } + } + + private void onPickedLocal(Intent data, int code) { + boolean mutiSelect = getIntent().getBooleanExtra(Extras.EXTRA_MUTI_SELECT_MODE, false); + try { + List photos = PickerContract.getPhotos(data); + if (photos != null && photos.size() >= 1) { + PhotoInfo select = photos.get(0); + String photoPath = select.getAbsolutePath(); + boolean crop = getIntent().getBooleanExtra(Extras.EXTRA_NEED_CROP, false); + if (crop) { + crop(photoPath); + } else { + if (data != null) { + Intent result = new Intent(data); + result.putExtra(Extras.EXTRA_FROM_LOCAL, true); + setResult(RESULT_OK, result); + finish(); + } + } + } + } catch (Exception e) { + ToastHelper.showToastLong(this, R.string.picker_image_error); + finish(); + } + } + + private void onPickedCamera(Intent data, int code) { + try { + String photoPath = pathFromResult(data); + boolean crop = getIntent().getBooleanExtra(Extras.EXTRA_NEED_CROP, false); + if (crop) { + crop(photoPath); + } else { + if (!TextUtils.isEmpty(photoPath)) { + Intent result = new Intent(); + result.putExtra(Extras.EXTRA_FROM_LOCAL, code == REQUEST_CODE_LOCAL); + result.putExtra(Extras.EXTRA_FILE_PATH, photoPath); + setResult(RESULT_OK, result); + } + finish(); + } + } catch (Exception e) { + ToastHelper.showToastLong(this, R.string.picker_image_error); + finish(); + } + } + + private void crop(String src) { + Intent intent = getIntent(); + int outputX = intent.getIntExtra(Extras.EXTRA_OUTPUTX, 0); + int outputY = intent.getIntExtra(Extras.EXTRA_OUTPUTY, 0); + String outPath = intent.getStringExtra(Extras.EXTRA_FILE_PATH); + CropImageActivity.startForFile(this, src, outputX, outputY, outPath, REQUEST_CODE_CROP); + } + + private void onCropped() { + String outPath = getIntent().getStringExtra(Extras.EXTRA_FILE_PATH); + Intent result = new Intent(); + result.putExtra(Extras.EXTRA_FILE_PATH, outPath); + setResult(RESULT_OK, result); + finish(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode != RESULT_OK) { + setResult(resultCode); + finish(); + return; + } + + switch (requestCode) { + case REQUEST_CODE_LOCAL: + onPickedLocal(data, requestCode); + break; + case REQUEST_CODE_CAMERA: + onPickedCamera(data, requestCode); + break; + case REQUEST_CODE_CROP: + onCropped(); + break; + default: + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickerAlbumActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickerAlbumActivity.java new file mode 100644 index 0000000..b4c59d7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickerAlbumActivity.java @@ -0,0 +1,299 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.activity; + + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.RequestCode; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.fragment.PickerAlbumFragment; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.fragment.PickerImageFragment; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.loader.PickerImageLoader; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.AlbumInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PickerContract; +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Inner image picker, no longer use third-part application + */ +public class PickerAlbumActivity extends UI implements PickerAlbumFragment.OnAlbumItemClickListener, + PickerImageFragment.OnPhotoSelectClickListener, OnClickListener { + + private FrameLayout pickerAlbumLayout; + + private FrameLayout pickerPhotosLayout; + + private PickerAlbumFragment photoFolderFragment; + + private PickerImageFragment photoFragment; + + private RelativeLayout pickerBottomBar; + + private TextView pickerPreview; + + private TextView pickerSend; + + private List hasSelectList = new ArrayList(); + + private boolean isMutiMode; + + private boolean isSupportOriginal; + + private boolean isSendOriginalImage; + + private int mutiSelectLimitSize; + + private boolean isAlbumPage; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_picker_album_activity); + + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + + proceedExtra(); + initActionBar(); + initUI(); + } + + private void proceedExtra() { + Intent intent = getIntent(); + if (intent != null) { + isMutiMode = intent.getBooleanExtra(Extras.EXTRA_MUTI_SELECT_MODE, false); + mutiSelectLimitSize = intent.getIntExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, 9); + isSupportOriginal = intent.getBooleanExtra(Extras.EXTRA_SUPPORT_ORIGINAL, false); + } + } + + private void initActionBar() { + setTitle(R.string.picker_image_folder); + } + + private void initUI() { + // bottom bar + pickerBottomBar = (RelativeLayout) findViewById(R.id.picker_bottombar); + if (isMutiMode) { + pickerBottomBar.setVisibility(View.VISIBLE); + } else { + pickerBottomBar.setVisibility(View.GONE); + } + pickerPreview = (TextView) findViewById(R.id.picker_bottombar_preview); + pickerPreview.setOnClickListener(this); + pickerSend = (TextView) findViewById(R.id.picker_bottombar_select); + pickerSend.setOnClickListener(this); + + // fragment + pickerAlbumLayout = (FrameLayout) findViewById(R.id.picker_album_fragment); + pickerPhotosLayout = (FrameLayout) findViewById(R.id.picker_photos_fragment); + photoFolderFragment = new PickerAlbumFragment(); + switchContent(photoFolderFragment); + + isAlbumPage = true; + } + + @Override + public void OnAlbumItemClick(AlbumInfo info) { + // check photo list if has already be choose + List photoList = info.getList(); + if (photoList == null) { + return; + } + for (PhotoInfo photo : photoList) { + if (checkSelectPhoto(photo)) { + photo.setChoose(true); + } else { + photo.setChoose(false); + } + } + // switch to photo fragment + pickerAlbumLayout.setVisibility(View.GONE); + pickerPhotosLayout.setVisibility(View.VISIBLE); + if (photoFragment == null) { + photoFragment = new PickerImageFragment(); + photoFragment.setArguments(makeDataBundle(photoList, isMutiMode, mutiSelectLimitSize)); + switchContent(photoFragment); + } else { + int hasSelectSize = hasSelectList.size(); + photoFragment.resetFragment(photoList, hasSelectSize); + } + // update title + setTitle(info.getAlbumName()); + isAlbumPage = false; + } + + public Bundle makeDataBundle(List photos, boolean mutiMode, int mutiSelectLimitSize) { + Bundle bundle = new Bundle(); + bundle.putSerializable(Extras.EXTRA_PHOTO_LISTS, new ArrayList(photos)); + bundle.putBoolean(Extras.EXTRA_MUTI_SELECT_MODE, mutiMode); + bundle.putInt(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, mutiSelectLimitSize); + + return bundle; + } + + @Override + public void onPhotoSingleClick(List photos, int position) { + if (isMutiMode) { + PickerAlbumPreviewActivity.start(this, photos, position, isSupportOriginal, + isSendOriginalImage, hasSelectList, mutiSelectLimitSize); + } else { + if (photos != null) { + PhotoInfo photo = photos.get(position); + List selectList = new ArrayList(); + selectList.add(photo); + + setResult(RESULT_OK, PickerContract.makeDataIntent(selectList, false)); + finish(); + } + } + } + + @Override + public void onPhotoSelectClick(PhotoInfo selectPhoto) { + if (selectPhoto == null) + return; + // check + boolean isChoose = selectPhoto.isChoose(); + if (isChoose) { + boolean isSelect = checkSelectPhoto(selectPhoto); + if (!isSelect) { + addSelectPhoto(selectPhoto); + } + } else { + removeSelectPhoto(selectPhoto); + } + // update bottom bar + updateSelectBtnStatus(); + } + + private boolean checkSelectPhoto(PhotoInfo photo) { + boolean isSelect = false; + for (int i = 0; i < hasSelectList.size(); i++) { + PhotoInfo select = hasSelectList.get(i); + if (select.getImageId() == photo.getImageId()) { + isSelect = true; + break; + } + } + + return isSelect; + } + + private void removeSelectPhoto(PhotoInfo photo) { + Iterator lIterator = hasSelectList.iterator(); + while (lIterator.hasNext()) { + PhotoInfo select = lIterator.next(); + if (select.getImageId() == photo.getImageId()) { + lIterator.remove(); + } + } + } + + private void addSelectPhoto(PhotoInfo photo) { + hasSelectList.add(photo); + } + + private void resetSelectPhotos(List photos) { + if (hasSelectList != null) { + hasSelectList.clear(); + } else { + hasSelectList = new ArrayList(); + } + hasSelectList.addAll(photos); + } + + private void updateSelectBtnStatus() { + int selectSize = hasSelectList.size(); + if (selectSize > 0) { + pickerPreview.setEnabled(true); + pickerSend.setEnabled(true); + pickerSend.setText(String.format(this.getResources().getString( + R.string.picker_image_send_select), selectSize)); + } else { + pickerPreview.setEnabled(false); + pickerSend.setEnabled(false); + pickerSend.setText(R.string.picker_image_send); + } + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.picker_bottombar_preview) { + PickerAlbumPreviewActivity.start(this, hasSelectList, 0, isSupportOriginal, + isSendOriginalImage, hasSelectList, mutiSelectLimitSize); + } else if (v.getId() == R.id.picker_bottombar_select) { + setResult(RESULT_OK, PickerContract.makeDataIntent(hasSelectList, isSendOriginalImage)); + finish(); + } + } + + @Override + public void onBackPressed() { + if (isAlbumPage) { + finish(); + } else { + backToAlbumPage(); + } + } + + private void backToAlbumPage() { + setTitle(R.string.picker_image_folder); + isAlbumPage = true; + pickerAlbumLayout.setVisibility(View.VISIBLE); + pickerPhotosLayout.setVisibility(View.GONE); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == RequestCode.PICKER_IMAGE_PREVIEW) { + if (resultCode == RESULT_OK) { + if (data != null) { + setResult(RESULT_OK, new Intent(data)); + finish(); + } + } else if (resultCode == PickerAlbumPreviewActivity.RESULT_FROM_USER) { + if (data != null) { + // update photo fragment + isSendOriginalImage = data.getBooleanExtra(Extras.EXTRA_IS_ORIGINAL, false); + List list = PickerContract.getPhotos(data); + if (photoFragment != null && list != null) { + photoFragment.updateGridview(list); + } + // update select photo list + List selectList = PickerContract.getSelectPhotos(data); + resetSelectPhotos(selectList); + updateSelectBtnStatus(); + if (photoFragment != null && hasSelectList != null) { + photoFragment.updateSelectedForAdapter(hasSelectList.size()); + } + } + } + } + } + + @Override + protected void onStart() { + super.onStart(); + PickerImageLoader.initCache(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + PickerImageLoader.clearCache(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickerAlbumPreviewActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickerAlbumPreviewActivity.java new file mode 100644 index 0000000..7cef76e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PickerAlbumPreviewActivity.java @@ -0,0 +1,396 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.activity; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.RequestCode; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter.PickerPreviewPagerAdapter; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PickerContract; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.util.PickerUtil; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.BaseZoomableImageView; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class PickerAlbumPreviewActivity extends UI implements OnClickListener, ViewPager.OnPageChangeListener { + + public static final int RESULT_FROM_USER = RESULT_FIRST_USER + 1; + + public static void start(Activity activity, List photos, int position, boolean supportOrig, + boolean isOrig, List selectPhotoList, int mutiSelectLimitSize) { + Intent intent = PickerContract.makePreviewDataIntent(photos, selectPhotoList); + intent.setClass(activity, PickerAlbumPreviewActivity.class); + intent.putExtra(Extras.EXTRA_PREVIEW_CURRENT_POS, position); + intent.putExtra(Extras.EXTRA_SUPPORT_ORIGINAL, supportOrig); + intent.putExtra(Extras.EXTRA_IS_ORIGINAL, isOrig); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, mutiSelectLimitSize); + activity.startActivityForResult(intent, RequestCode.PICKER_IMAGE_PREVIEW); + } + + public static void start(Fragment fragment, List photos, int position, boolean supportOrig, + boolean isOrig, List selectPhotoList, int mutiSelectLimitSize) { + Intent intent = PickerContract.makePreviewDataIntent(photos, selectPhotoList); + intent.setClass(fragment.getActivity(), PickerAlbumPreviewActivity.class); + intent.putExtra(Extras.EXTRA_PREVIEW_CURRENT_POS, position); + intent.putExtra(Extras.EXTRA_SUPPORT_ORIGINAL, supportOrig); + intent.putExtra(Extras.EXTRA_IS_ORIGINAL, isOrig); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, mutiSelectLimitSize); + fragment.startActivityForResult(intent, RequestCode.PICKER_IMAGE_PREVIEW); + } + + private ViewPager imageViewPager; + + private PickerPreviewPagerAdapter imageViewPagerAdapter; + + private List selectPhotoList = new ArrayList(); + + private List photoLists = new ArrayList(); + + private int firstDisplayImageIndex = 0; + + private int currentPosition = -1; + + private int totalSize; + + private BaseZoomableImageView currentImageView; + + private int tempIndex = -1; + + @SuppressWarnings("unused") + private LinearLayout previewOperationBar; + + private ImageButton originalImage; + + private boolean isSupportOriginal; + + private boolean isSendOriginalImage; + + private TextView originalImageSizeTip; + + private TextView previewSendBtn; + + private ImageButton previewSelectBtn; + + private int mutiSelectLimitSize; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_picker_image_preview_activity); + + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + + proceedExtras(); + initActionBar(); + initUI(); + } + + private void proceedExtras() { + Intent intent = getIntent(); + isSupportOriginal = intent.getBooleanExtra(Extras.EXTRA_SUPPORT_ORIGINAL, false); + isSendOriginalImage = intent.getBooleanExtra(Extras.EXTRA_IS_ORIGINAL, false); + firstDisplayImageIndex = intent.getIntExtra(Extras.EXTRA_PREVIEW_CURRENT_POS, 0); + mutiSelectLimitSize = intent.getIntExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, 9); + + photoLists.addAll(PickerContract.getPhotos(intent)); + totalSize = photoLists.size(); + + selectPhotoList.clear(); + selectPhotoList.addAll(PickerContract.getSelectPhotos(intent)); + } + + private void initActionBar() { + previewSelectBtn = (ImageButton) findViewById(R.id.picker_image_preview_photos_select); + previewSelectBtn.setOnClickListener(this); + } + + private void initUI() { + previewOperationBar = (LinearLayout) findViewById(R.id.picker_image_preview_operator_bar); + originalImage = (ImageButton) findViewById(R.id.picker_image_preview_orignal_image); + originalImage.setOnClickListener(this); + originalImageSizeTip = (TextView) findViewById(R.id.picker_image_preview_orignal_image_tip); + if (!isSupportOriginal) { + originalImage.setVisibility(View.INVISIBLE); + originalImageSizeTip.setVisibility(View.INVISIBLE); + } + previewSendBtn = (TextView) findViewById(R.id.picker_image_preview_send); + previewSendBtn.setOnClickListener(this); + updateSelectBtnStatus(); + updateOriImageSizeTip(isSendOriginalImage); + + imageViewPager = (ViewPager) findViewById(R.id.picker_image_preview_viewpager); + imageViewPager.setOnPageChangeListener(this); + imageViewPager.setOffscreenPageLimit(2); + imageViewPagerAdapter = new PickerPreviewPagerAdapter(this, photoLists, getLayoutInflater(), + imageViewPager.getLayoutParams().width, imageViewPager.getLayoutParams().height, this); + imageViewPager.setAdapter(imageViewPagerAdapter); + + setTitleIndex(firstDisplayImageIndex); + updateTitleSelect(firstDisplayImageIndex); + imageViewPager.setCurrentItem(firstDisplayImageIndex); + } + + private void updateTitleSelect(int index) { + if (photoLists == null || index >= photoLists.size()) + return; + + PhotoInfo photo = photoLists.get(index); + if (photo.isChoose()) { + previewSelectBtn.setImageResource(R.drawable.nim_picker_image_selected); + } else { + previewSelectBtn.setImageResource(R.drawable.nim_picker_preview_unselected); + } + } + + private void setTitleIndex(int index) { + if (totalSize <= 0) { + setTitle(""); + } else { + index++; + setTitle(index + "/" + totalSize); + } + } + + public void updateCurrentImageView(final int position) { + if (photoLists == null + || (position > 0 + && position >= photoLists.size())) + return; + + if (currentPosition == position) { + return; + } else { + currentPosition = position; + } + + LinearLayout currentLayout = (LinearLayout) imageViewPager.findViewWithTag(position); + if (currentLayout == null) { + Handler mHandler = new Handler(); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + updateCurrentImageView(position); + } + }, 300); + return; + } + currentImageView = (BaseZoomableImageView) currentLayout.findViewById(R.id.imageView); + currentImageView.setViewPager(imageViewPager); + + setImageView(photoLists.get(position)); + } + + public void setImageView(PhotoInfo info) { + if (info == null) { + return; + } + + if (info.getAbsolutePath() == null) { + return; + } + + Bitmap bitmap = BitmapDecoder.decodeSampledForDisplay(info.getAbsolutePath()); + if (bitmap == null) { + currentImageView.setImageBitmap(ImageUtil.getDefaultBitmapWhenGetFail()); + ToastHelper.showToastLong(this, R.string.picker_image_error); + } else { + try { + bitmap = ImageUtil.rotateBitmapInNeeded(info.getAbsolutePath(), bitmap); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + currentImageView.setImageBitmap(bitmap); + } + } + + private void restoreList() { + if (tempIndex != -1) { + imageViewPager.setAdapter(imageViewPagerAdapter); + setTitleIndex(tempIndex); + imageViewPager.setCurrentItem(tempIndex); + tempIndex = -1; + } + } + + private void updateSelectBtnStatus() { + int selectSize = selectPhotoList.size(); + if (selectSize > 0) { + previewSendBtn.setEnabled(true); + previewSendBtn.setText(String.format(this.getResources().getString( + R.string.picker_image_send_select), selectSize)); + } else { + previewSendBtn.setEnabled(true); + previewSendBtn.setText(R.string.picker_image_send); + } + } + + private void updatePreviewSelectBtnStatus(boolean isChoose) { + if (isChoose) { + previewSelectBtn.setImageResource(R.drawable.nim_picker_image_selected); + } else { + previewSelectBtn.setImageResource(R.drawable.nim_picker_preview_unselected); + } + } + + private void updateOriImageSizeTip(boolean isOri) { + if (selectPhotoList == null) + return; + if (isOri) { + long totalSize = 0; + for (int i = 0; i < selectPhotoList.size(); i++) { + PhotoInfo pi = selectPhotoList.get(i); + totalSize += pi.getSize(); + } + originalImageSizeTip.setText(String.format(this.getResources().getString( + R.string.picker_image_preview_original_select), PickerUtil.getFileSizeString(totalSize))); + originalImage.setImageResource(R.drawable.nim_picker_orignal_checked); + } else { + originalImageSizeTip.setText(R.string.picker_image_preview_original); + originalImage.setImageResource(R.drawable.nim_picker_orignal_normal); + } + } + + private boolean checkSelectPhoto(PhotoInfo photo) { + boolean isSelect = false; + for (int i = 0; i < selectPhotoList.size(); i++) { + PhotoInfo select = selectPhotoList.get(i); + if (select.getImageId() == photo.getImageId()) { + isSelect = true; + break; + } + } + + return isSelect; + } + + private void removeSelectPhoto(PhotoInfo photo) { + Iterator lIterator = selectPhotoList.iterator(); + while (lIterator.hasNext()) { + PhotoInfo select = lIterator.next(); + if (select.getImageId() == photo.getImageId()) { + lIterator.remove(); + } + } + } + + @Override + public void onResume() { + // restore the data source + restoreList(); + + super.onResume(); + } + + @Override + public void onPause() { + // save the data source and recycle all bitmaps + imageViewPager.setAdapter(null); + tempIndex = currentPosition; + currentPosition = -1; + + super.onPause(); + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.picker_image_preview_photos_select) { + if (photoLists == null || currentPosition >= photoLists.size()) + return; + + PhotoInfo selectPhoto = photoLists.get(currentPosition); + boolean isChoose = selectPhoto.isChoose(); + if (selectPhotoList != null && selectPhotoList.size() >= mutiSelectLimitSize && !isChoose) { + ToastHelper.showToast(this, String.format(getResources().getString(R.string.picker_image_exceed_max_image_select) + , mutiSelectLimitSize)); + return; + } + selectPhoto.setChoose(!isChoose); + updatePreviewSelectBtnStatus(!isChoose); + + // check + if (!isChoose) { + boolean isSelect = checkSelectPhoto(selectPhoto); + if (!isSelect) { + selectPhotoList.add(selectPhoto); + } + } else { + removeSelectPhoto(selectPhoto); + } + // update bottom bar + updateSelectBtnStatus(); + // 如果没有选择,则自动取消原图发送 + if (selectPhotoList.size() == 0 && isSendOriginalImage) { + isSendOriginalImage = false; + } + updateOriImageSizeTip(isSendOriginalImage); + } else if (v.getId() == R.id.picker_image_preview_send) { + if (selectPhotoList != null && selectPhotoList.size() == 0) { // 没有选择,点击发送则发送当前图片 + PhotoInfo current = photoLists.get(currentPosition); + current.setChoose(true); + selectPhotoList.add(current); + } + setResult(RESULT_OK, PickerContract.makeDataIntent(selectPhotoList, isSendOriginalImage)); + finish(); + } else if (v.getId() == R.id.picker_image_preview_orignal_image) { + if (!isSendOriginalImage) { + isSendOriginalImage = true; + // 如果已选图片小于mutiSelectLimitSize,点击发送原图,自动选择当前页面 + int selectSize = selectPhotoList != null ? selectPhotoList.size() : 0; + if (selectSize < mutiSelectLimitSize) { + PhotoInfo cur = photoLists.get(currentPosition); + if (!cur.isChoose()) { + cur.setChoose(true); + selectPhotoList.add(cur); + updateSelectBtnStatus(); + updatePreviewSelectBtnStatus(true); + } + } + } else { + isSendOriginalImage = false; + } + updateOriImageSizeTip(isSendOriginalImage); + } + } + + @Override + public void onBackPressed() { + setResult(RESULT_FROM_USER, PickerContract.makePreviewDataIntent(photoLists, selectPhotoList, + isSendOriginalImage)); + finish(); + } + + @Override + public void onPageScrollStateChanged(int arg0) { + } + + @Override + public void onPageScrolled(int arg0, float arg1, int arg2) { + } + + @Override + public void onPageSelected(int arg0) { + setTitleIndex(arg0); + updateTitleSelect(arg0); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PreviewImageFromCameraActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PreviewImageFromCameraActivity.java new file mode 100644 index 0000000..d0c2ec0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PreviewImageFromCameraActivity.java @@ -0,0 +1,212 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.activity; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.api.wrapper.NimToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.RequestCode; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.ToolBarOptions; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.netease.nim.uikit.R; + +import java.io.File; +import java.util.ArrayList; + +public class PreviewImageFromCameraActivity extends UI { + + public static final String RESULT_RETAKE = "RESULT_RETAKE"; + public static final String RESULT_SEND = "RESULT_SEND"; + + private ImageView previewImageView; + + private File imageFile; + + private Button sendButton; + + private String origImageFilePath; + + private String btnText; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_preview_image_from_camera_activity); + + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + + initActionBar(); + getIntentData(); + findViews(); + initSendBtn(); + showPicture(); + } + + private void findViews() { + sendButton = (Button) findViewById(R.id.buttonSend); + previewImageView = (ImageView) findViewById(R.id.imageViewPreview); + } + + private void getIntentData() { + String imageFilePathString = getIntent().getExtras().getString("ImageFilePath"); + origImageFilePath = getIntent().getExtras().getString("OrigImageFilePath"); + btnText = getIntent().getExtras().getString(Extras.EXTRA_PREVIEW_IMAGE_BTN_TEXT); + imageFile = new File(imageFilePathString); + } + + private void initSendBtn() { + if (!TextUtils.isEmpty(btnText)) { + sendButton.setText(btnText); + } + sendButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + ArrayList imageList = new ArrayList(); + ArrayList origImageList = new ArrayList(); + imageList.add(imageFile.getPath()); + origImageList.add(origImageFilePath); + + boolean isOrig = false; + if (!isOrig) { + // 拍照不是原图发送的话,原图需要手动删掉 + AttachmentStore.delete(origImageFilePath); + } + + Intent intent = PreviewImageFromLocalActivity.initPreviewImageIntent(imageList, origImageList, isOrig); + intent.setClass(PreviewImageFromCameraActivity.this, getIntent().getClass()); + intent.putExtra(RESULT_SEND, true); + setResult(RESULT_OK, intent); + PreviewImageFromCameraActivity.this.finish(); + } + }); + } + + + private void initActionBar() { + TextView toolbarView = findView(R.id.action_bar_right_clickable_textview); + toolbarView.setText(R.string.recapture); + toolbarView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + deleteTempFile(); + Intent intent = new Intent(); + intent.setClass(PreviewImageFromCameraActivity.this, getIntent().getClass()); + intent.putExtra(RESULT_RETAKE, true); + setResult(RESULT_OK, intent); + PreviewImageFromCameraActivity.this.finish(); + } + }); + } + + @Override + public void onBackPressed() { + deleteTempFile(); + + Intent intent = new Intent(); + intent.setClass(PreviewImageFromCameraActivity.this, getIntent().getClass()); + setResult(RESULT_CANCELED, intent); + PreviewImageFromCameraActivity.this.finish(); + } + + @Override + public void onDestroy() { + Drawable dr = previewImageView.getDrawable(); + previewImageView.setImageBitmap(null); + + if (dr != null) { + Bitmap bitmap = getBitmap(dr); + if (bitmap != null) { + bitmap.recycle(); + } + } + + super.onDestroy(); + } + + public static final Bitmap getBitmap(Drawable dr) { + if (dr == null) { + return null; + } + + if (dr instanceof BitmapDrawable) { + return ((BitmapDrawable) dr).getBitmap(); + } + + return null; + } + + private void showPicture() { + try { + Bitmap bitmap = BitmapDecoder.decodeSampledForDisplay(imageFile.getAbsolutePath()); + + if (bitmap != null) { + previewImageView.setImageBitmap(bitmap); + } else { + ToastHelper.showToastLong(this, R.string.image_show_error); + } + } catch (OutOfMemoryError e) { + ToastHelper.showToastLong(this, R.string.memory_out); + } + } + + /** + * 获取本地图片 + */ + protected void choosePictureFromLocal() { + if (!StorageUtil.hasEnoughSpaceForWrite(PreviewImageFromCameraActivity.this, StorageType.TYPE_IMAGE, true)) { + return; + } + + new AsyncTask() { + + @Override + protected void onPreExecute() { + ToastHelper.showToastLong(PreviewImageFromCameraActivity.this, R.string.waitfor_image_local); + } + + @Override + protected Boolean doInBackground(String... params) { + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); + if (Build.VERSION.SDK_INT >= 11) { + intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); + } + try { + PreviewImageFromCameraActivity.this.startActivityForResult(intent, RequestCode.GET_LOCAL_IMAGE); + } catch (ActivityNotFoundException e) { + ToastHelper.showToastLong(PreviewImageFromCameraActivity.this, R.string.gallery_invalid); + } + } + }.execute(); + } + + private void deleteTempFile() { + if (imageFile != null) { + imageFile.delete(); + } + + AttachmentStore.delete(origImageFilePath); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PreviewImageFromLocalActivity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PreviewImageFromLocalActivity.java new file mode 100644 index 0000000..df4ff75 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/activity/PreviewImageFromLocalActivity.java @@ -0,0 +1,395 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.activity; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.RequestCode; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter.ImagePagerAdapterInImageSwitch; +import com.fengliyan.tianlesue.im.uikit.common.ui.dialog.EasyAlertDialog; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.BaseZoomableImageView; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.media.BitmapDecoder; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.netease.nim.uikit.R; + +import java.io.File; +import java.util.ArrayList; + +public class PreviewImageFromLocalActivity extends UI { + + private boolean needShowSendOriginal = false; + + private ImageButton originalImage; + + private boolean isSendOriginalImage; + + private TextView originalImageSizeTip; + + private File imageFile; + + private ArrayList selectImageList; + + private ArrayList origImageList; + + protected ViewPager imageViewPager; + + private ImagePagerAdapterInImageSwitch imageViewPagerAdapter; + + protected BaseZoomableImageView currentImageView; + + protected int currentPostion = -1; + + private int tempIndex = -1; + + private View sendButton; + + public static Intent initPreviewImageIntent( + ArrayList thumbnailImageList, + ArrayList orignialImageList, + boolean isOrignial + ) { + Intent intent = new Intent(); + intent.putStringArrayListExtra(Extras.EXTRA_SCALED_IMAGE_LIST, thumbnailImageList); + intent.putStringArrayListExtra(Extras.EXTRA_ORIG_IMAGE_LIST, orignialImageList); + intent.putExtra(Extras.EXTRA_IS_ORIGINAL, isOrignial); + return intent; + } + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_preview_image_from_local_activity); + + originalImageSizeTip = (TextView) findViewById(R.id.picker_image_preview_orignal_image_tip); + originalImage = (ImageButton) findViewById(R.id.picker_image_preview_orignal_image); + originalImage.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + isSendOriginalImage = !isSendOriginalImage; + updateOriImageSizeTip(isSendOriginalImage); + } + }); + + needShowSendOriginal = getIntent().getBooleanExtra(Extras.EXTRA_NEED_SHOW_SEND_ORIGINAL, false); + if (needShowSendOriginal) { + originalImage.setVisibility(View.VISIBLE); + originalImageSizeTip.setVisibility(View.VISIBLE); + } else { + originalImage.setVisibility(View.INVISIBLE); + originalImageSizeTip.setVisibility(View.INVISIBLE); + } + + sendButton = findViewById(R.id.buttonSend); + sendButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (isSendOriginalImage) { + sendOrigImage(); + } else { + sendSelectedImage(false); + } + } + }); + + initViewPager(); + } + + private void restoreList() { + if (tempIndex != -1) { + imageViewPager.setAdapter(imageViewPagerAdapter); + setTitleIndex(tempIndex); + imageViewPager.setCurrentItem(tempIndex); + tempIndex = -1; + } + } + + private void setTitleIndex(int index) { + if (selectImageList.size() <= 0) { + setTitle(""); + } else { + index++; + setTitle(index + "/" + selectImageList.size()); + } + } + + private void sendSelectedImage(boolean isOrig) { + Intent intent = initPreviewImageIntent(selectImageList, origImageList, isOrig); + intent.setClass(PreviewImageFromLocalActivity.this, getIntent().getClass()); + setResult(RESULT_OK, intent); + PreviewImageFromLocalActivity.this.finish(); + } + + @SuppressLint("NewApi") + private void sendOrigImage() { + final UI activity = PreviewImageFromLocalActivity.this; + final EasyAlertDialog allAlertDialog = new EasyAlertDialog(activity); + allAlertDialog.setTitle(getString(R.string.picker_image_preview_original)); + + long fileSize = 0; + for (String filepath : origImageList) { + fileSize += AttachmentStore.getFileLength(filepath); + } + + if (origImageList.size() == 1) { + allAlertDialog.setMessage(getString(R.string.image_compressed_size, FileUtil.formatFileSize(fileSize)) + + getString(R.string.is_send_image)); + } else { + allAlertDialog.setMessage(getString(R.string.multi_image_compressed_size, + FileUtil.formatFileSize(fileSize)) + + getString(R.string.is_send_multi_image)); + } + + allAlertDialog.addPositiveButton(getString(R.string.ok), EasyAlertDialog.NO_TEXT_COLOR, EasyAlertDialog.NO_TEXT_SIZE, + new OnClickListener() { + @Override + public void onClick(View view) { + sendSelectedImage(true); + } + }); + allAlertDialog.addNegativeButton(getString(R.string.cancel), EasyAlertDialog.NO_TEXT_COLOR, + EasyAlertDialog.NO_TEXT_SIZE, new OnClickListener() { + @Override + public void onClick(View view) { + allAlertDialog.dismiss(); + } + }); + if (!activity.isDestroyedCompatible()) { + allAlertDialog.show(); + } + } + + private void updateOriImageSizeTip(boolean isOrig) { + if (origImageList == null) + return; + if (isOrig) { + long totalSize = 0; + + for (String filepath : origImageList) { + totalSize += AttachmentStore.getFileLength(filepath); + } + originalImageSizeTip.setText(String.format(this.getResources().getString( + R.string.picker_image_preview_original_select), FileUtil.formatFileSize(totalSize))); + originalImage.setImageResource(R.drawable.nim_picker_orignal_checked); + } else { + originalImageSizeTip.setText(R.string.picker_image_preview_original); + originalImage.setImageResource(R.drawable.nim_picker_orignal_normal); + } + } + + /** + * 初始化图片查看 + */ + private void initViewPager() { + imageViewPager = (ViewPager) findViewById(R.id.viewPagerImage); + imageViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrollStateChanged(int arg0) { + } + + @Override + public void onPageScrolled(int arg0, float arg1, int arg2) { + } + + @Override + public void onPageSelected(int arg0) { + setTitleIndex(arg0); + } + }); + imageViewPager.setOffscreenPageLimit(2); + + String imageFilePath = getIntent().getExtras().getString("ImageFilePath"); + String origImageFilePath = getIntent().getExtras().getString("OrigImageFilePath"); + + imageFile = new File(imageFilePath); + + selectImageList = new ArrayList(); + selectImageList.add(imageFilePath); + + origImageList = new ArrayList(); + origImageList.add(origImageFilePath); + + imageViewPagerAdapter = new ImagePagerAdapterInImageSwitch(this, selectImageList, getLayoutInflater(), + imageViewPager.getLayoutParams().width, imageViewPager.getLayoutParams().height, this); + imageViewPager.setAdapter(imageViewPagerAdapter); + } + + @Override + public void onBackPressed() { + deleteTempFiles(); + + Intent intent = new Intent(); + intent.setClass(PreviewImageFromLocalActivity.this, getIntent().getClass()); + setResult(RESULT_CANCELED, intent); + PreviewImageFromLocalActivity.this.finish(); + } + + @Override + public void onResume() { + // restore the data source + restoreList(); + + super.onResume(); + } + + @Override + public void onPause() { + // recycleBitmap(previewImageView); + + // save the data source and recycle all bitmaps + imageViewPager.setAdapter(null); + tempIndex = currentPostion; + currentPostion = -1; + + super.onPause(); + } + + /** + * 获取本地图片 + */ + protected void choosePictureFromLocal() { + if (!StorageUtil.hasEnoughSpaceForWrite(PreviewImageFromLocalActivity.this, StorageType.TYPE_IMAGE, true)) { + return; + } + + new AsyncTask() { + @Override + protected void onPreExecute() { + ToastHelper.showToastLong(PreviewImageFromLocalActivity.this, R.string.waitfor_image_local); + } + + @Override + protected Boolean doInBackground(String... params) { + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + int from = PickImageActivity.FROM_LOCAL; + Activity thiz = PreviewImageFromLocalActivity.this; + PickImageActivity.start(thiz, RequestCode.GET_LOCAL_IMAGE, from, ""); + } + }.execute(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode != RESULT_CANCELED) { + if (requestCode == RequestCode.GET_LOCAL_IMAGE) { + onGetLocalPictureResult(requestCode, resultCode, data); + } + } else { + if (selectImageList.size() == 0) { + sendButton.setEnabled(false); + } + } + } + + public void onGetLocalPictureResult(int requestCode, int resultCode, final Intent data) { + if (data == null) { + return; + } + final String photoPath = data.getStringExtra(Extras.EXTRA_FILE_PATH); + if (TextUtils.isEmpty(photoPath)) { + return; + } + + imageFile = new File(photoPath); + String mimeType = FileUtil.getExtensionName(photoPath); + imageFile = ImageUtil.getScaledImageFileWithMD5(imageFile, mimeType); + if (imageFile == null) { + ToastHelper.showToastLong(this, R.string.picker_image_error); + return; + } else { + ImageUtil.makeThumbnail(imageFile); + } + + origImageList.add(photoPath); + selectImageList.add(imageFile.getAbsolutePath()); + imageViewPagerAdapter.notifyDataSetChanged(); + + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + imageViewPager.setCurrentItem(selectImageList.size() - 1); + } + }, 100); + //有可用的图片 + if (selectImageList.size() >= 1) { + sendButton.setEnabled(true); + } + } + + public void updateCurrentImageView(final int position) { + if (selectImageList == null + || (position > 0 + && position >= selectImageList.size())) + return; + + if (currentPostion == position) { + return; + } else { + currentPostion = position; + } + setTitleIndex(position); + + // LinearLayout currentLayout = (LinearLayout) + // imageViewPager.getChildAt(position); + LinearLayout currentLayout = (LinearLayout) imageViewPager.findViewWithTag(position); + + if (currentLayout == null) { + Handler mHandler = new Handler(); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + updateCurrentImageView(position); + } + }, 300); + return; + } + currentImageView = (BaseZoomableImageView) currentLayout.findViewById(R.id.imageView); + currentImageView.setViewPager(imageViewPager); + + setImageView(selectImageList.get(position)); + } + + public void setImageView(String imageFilePath) { + if (imageFilePath == null) { + return; + } + + Bitmap bitmap = BitmapDecoder.decodeSampledForDisplay(imageFilePath); + if (bitmap == null) { + currentImageView.setImageBitmap(ImageUtil.getDefaultBitmapWhenGetFail()); + ToastHelper.showToastLong(this, R.string.picker_image_error); + } else { + currentImageView.setImageBitmap(bitmap); + } + } + + private void deleteTempFiles() { + for (String file : selectImageList) { + new File(file).delete(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/ImagePagerAdapterInImageSwitch.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/ImagePagerAdapterInImageSwitch.java new file mode 100644 index 0000000..f8fcc1c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/ImagePagerAdapterInImageSwitch.java @@ -0,0 +1,82 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter; + +import android.content.Context; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.viewpager.widget.PagerAdapter; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.activity.PreviewImageFromLocalActivity; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.BaseZoomableImageView; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; + +import java.util.List; + +public class ImagePagerAdapterInImageSwitch extends PagerAdapter { + private Context mContext; + private List mList; + private LayoutInflater mInflater; + private int viewPagerWidth, viewPagerHeight; + private UI mActivity; + + public ImagePagerAdapterInImageSwitch(Context cx, List list, LayoutInflater inflater, int width, int height, UI activity) { + mContext = cx; + mList = list; + mInflater = inflater; + viewPagerHeight = height; + viewPagerWidth = width; + mActivity = activity; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + View layout = (View) object; + BaseZoomableImageView iv = (BaseZoomableImageView) layout.findViewById(R.id.imageView); + iv.clear(); + container.removeView(layout); + } + + @Override + public int getCount() { + return mList == null ? 0 : mList.size(); + } + + @Override + public boolean isViewFromObject(View arg0, Object arg1) { + return (arg0 == arg1); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { +// ImageView iv = new ImageView(mContext); + View layout = null; + +// if( Build.VERSION.SDK_INT >= 17 ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { + layout = mInflater.inflate(R.layout.nim_preview_image_layout_multi_touch, null); + } else { + layout = mInflater.inflate(R.layout.nim_preview_image_layout_zoom_control, null); + } + + container.addView(layout); + layout.setTag(position); + viewPagerWidth = ScreenUtil.screenWidth; + viewPagerHeight = ScreenUtil.screenHeight; + + return layout; + } + + @Override + public int getItemPosition(Object object) { + return POSITION_NONE; + } + + @Override + public void setPrimaryItem(View container, int position, Object object) { + ((PreviewImageFromLocalActivity) mActivity).updateCurrentImageView(position); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerAlbumAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerAlbumAdapter.java new file mode 100644 index 0000000..b52edcc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerAlbumAdapter.java @@ -0,0 +1,74 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter; + + +import android.content.Context; +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 com.fengliyan.tianlesue.im.uikit.common.media.picker.loader.PickerImageLoader; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.AlbumInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.util.ThumbnailsUtil; +import com.netease.nim.uikit.R; + +import java.util.List; + +public class PickerAlbumAdapter extends BaseAdapter { + + private LayoutInflater mInflater; + private List mList; + private Context mContext; + + public PickerAlbumAdapter(Context context, List list) { + mContext = context; + mInflater = LayoutInflater.from(context); + this.mList = list; + } + + @Override + public int getCount() { + return mList.size(); + } + + @Override + public Object getItem(int arg0) { + return mList.get(arg0); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + viewHolder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.nim_picker_photofolder_item, null); + viewHolder.folderCover = (ImageView) convertView.findViewById(R.id.picker_photofolder_cover); + viewHolder.folderName = (TextView) convertView.findViewById(R.id.picker_photofolder_info); + viewHolder.folderFileNum = (TextView) convertView.findViewById(R.id.picker_photofolder_num); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + + final AlbumInfo albumInfo = mList.get(position); + String thumbPath = ThumbnailsUtil.getThumbnailWithImageID(albumInfo.getImageId(), albumInfo.getFilePath()); + PickerImageLoader.display(thumbPath, albumInfo.getAbsolutePath(), viewHolder.folderCover, R.drawable.nim_image_default); + viewHolder.folderName.setText(albumInfo.getAlbumName()); + viewHolder.folderFileNum.setText(String.format(mContext.getResources().getString( + R.string.picker_image_folder_info), mList.get(position).getList().size())); + return convertView; + } + + public class ViewHolder { + public ImageView folderCover; + public TextView folderName; + public TextView folderFileNum; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerPhotoAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerPhotoAdapter.java new file mode 100644 index 0000000..d5e93ac --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerPhotoAdapter.java @@ -0,0 +1,153 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.fragment.PickerImageFragment; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.loader.PickerImageLoader; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.util.ThumbnailsUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +import java.util.List; + +public class PickerPhotoAdapter extends BaseAdapter { + + private Context mContext; + private LayoutInflater mInflater; + private List list; + private GridView gridView; + private int hasSelect = 0; + private int width = ScreenUtil.screenWidth / 4; + private boolean isMutiMode; + private int maxSelectSize; + + private PickerImageFragment.OnPhotoSelectClickListener onPhotoSelectClickListener; + + public PickerPhotoAdapter(Context context, List list, GridView gridView, + boolean isMutiMode, int hasSelect, int maxSelectSize) { + mContext = context; + mInflater = LayoutInflater.from(context); + this.list = list; + this.gridView = gridView; + this.isMutiMode = isMutiMode; + this.hasSelect = hasSelect; + this.maxSelectSize = maxSelectSize; + + if (onPhotoSelectClickListener == null) { + onPhotoSelectClickListener = (PickerImageFragment.OnPhotoSelectClickListener) context; + } + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public Object getItem(int position) { + return list.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + public void updateSelectNum(int hasSelectNum) { + this.hasSelect = hasSelectNum; + } + + public void refreshView(int index) { + int visiblePos = gridView.getFirstVisiblePosition(); + View view = gridView.getChildAt(index - visiblePos); + ViewHolder holder = (ViewHolder) view.getTag(); + if (list.get(index).isChoose()) { + holder.select.setImageResource(R.drawable.nim_picker_image_selected); + } else { + holder.select.setImageResource(R.drawable.nim_picker_image_normal); + } + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + viewHolder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.nim_picker_photo_grid_item, null); + viewHolder.image = (ImageView) convertView.findViewById(R.id.picker_photo_grid_item_img); + viewHolder.select = (ImageView) convertView.findViewById(R.id.picker_photo_grid_item_select); + viewHolder.selectHotPot = (RelativeLayout) convertView.findViewById(R.id.picker_photo_grid_item_select_hotpot); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + + if (isMutiMode) { + viewHolder.selectHotPot.setVisibility(View.VISIBLE); + } else { + viewHolder.selectHotPot.setVisibility(View.GONE); + } + + LayoutParams hotpotLayoutParams = viewHolder.selectHotPot.getLayoutParams(); + hotpotLayoutParams.width = width / 2; + hotpotLayoutParams.height = width / 2; + viewHolder.selectHotPot.setLayoutParams(hotpotLayoutParams); + viewHolder.selectHotPot.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + PhotoInfo photo = list.get(position); + if (photo.isChoose()) { + photo.setChoose(false); + hasSelect--; + } else if (hasSelect < maxSelectSize) { + photo.setChoose(true); + hasSelect++; + } else { + ToastHelper.showToast(mContext, String.format(mContext.getResources().getString( + R.string.picker_image_exceed_max_image_select), maxSelectSize)); + return; + } + + refreshView(position); + onPhotoSelectClickListener.onPhotoSelectClick(photo); + } + }); + + if (list.get(position).isChoose()) { + viewHolder.select.setImageResource(R.drawable.nim_picker_image_selected); + } else { + viewHolder.select.setImageResource(R.drawable.nim_picker_image_normal); + } + + LayoutParams imageLayoutParams = viewHolder.image.getLayoutParams(); + imageLayoutParams.width = width; + imageLayoutParams.height = width; + viewHolder.image.setLayoutParams(imageLayoutParams); + + final PhotoInfo photoInfo = list.get(position); + if (photoInfo != null) { + String thumbPath = ThumbnailsUtil.getThumbnailWithImageID(photoInfo.getImageId(), photoInfo.getFilePath()); + PickerImageLoader.display(thumbPath, photoInfo.getAbsolutePath(), viewHolder.image, R.drawable.nim_image_default); + } + + return convertView; + } + + public class ViewHolder { + public ImageView image; + public ImageView select; + public RelativeLayout selectHotPot; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerPreviewPagerAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerPreviewPagerAdapter.java new file mode 100644 index 0000000..f524407 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/adapter/PickerPreviewPagerAdapter.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter; + +import android.content.Context; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.viewpager.widget.PagerAdapter; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.activity.UI; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.activity.PickerAlbumPreviewActivity; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.BaseZoomableImageView; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; + +import java.util.List; + +public class PickerPreviewPagerAdapter extends PagerAdapter { + + private Context mContext; + private List mList; + private LayoutInflater mInflater; + private int viewPagerWidth, viewPagerHeight; + private UI mActivity; + + public PickerPreviewPagerAdapter(Context cx, List list, LayoutInflater inflater, int width, int height, UI activity) { + mContext = cx; + mList = list; + mInflater = inflater; + viewPagerHeight = height; + viewPagerWidth = width; + mActivity = activity; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + View layout = (View) object; + BaseZoomableImageView iv = (BaseZoomableImageView) layout.findViewById(R.id.imageView); + iv.clear(); + container.removeView(layout); + } + + @Override + public int getCount() { + return mList == null ? 0 : mList.size(); + } + + @Override + public boolean isViewFromObject(View arg0, Object arg1) { + return (arg0 == arg1); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + View layout = null; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { + layout = mInflater.inflate(R.layout.nim_preview_image_layout_multi_touch, null); + } else { + layout = mInflater.inflate(R.layout.nim_preview_image_layout_zoom_control, null); + } + + container.addView(layout); + layout.setTag(position); + viewPagerWidth = ScreenUtil.screenWidth; + viewPagerHeight = ScreenUtil.screenHeight; + + return layout; + } + + private void finishUpdate() { + + } + + @Override + public int getItemPosition(Object object) { + return POSITION_NONE; + } + + @Override + public void setPrimaryItem(View container, int position, Object object) { + ((PickerAlbumPreviewActivity) mActivity).updateCurrentImageView(position); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/fragment/PickerAlbumFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/fragment/PickerAlbumFragment.java new file mode 100644 index 0000000..7040ff8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/fragment/PickerAlbumFragment.java @@ -0,0 +1,234 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.fragment; + +import android.app.Activity; +import android.database.Cursor; +import android.os.AsyncTask; +import android.os.Bundle; +import android.provider.MediaStore; +import android.provider.MediaStore.Images.Thumbnails; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.fragment.TFragment; +import com.fengliyan.tianlesue.im.uikit.common.media.dao.MediaDAO; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter.PickerAlbumAdapter; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.AlbumInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.util.ThumbnailsUtil; +import com.netease.nim.uikit.R; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + + +public class PickerAlbumFragment extends TFragment implements OnItemClickListener { + public interface OnAlbumItemClickListener { + public void OnAlbumItemClick(AlbumInfo info); + } + + private OnAlbumItemClickListener onAlbumItemClickListener; + private LinearLayout loadingLay; + private TextView loadingTips; + private TextView loadingEmpty; + private ListView albumListView; + + public static final String FILE_PREFIX = "file://"; + + private List albumInfolist = new ArrayList(); + + private PickerAlbumAdapter albumAdapter; + + public PickerAlbumFragment() { + this.setContainerId(R.id.picker_album_fragment); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + if (onAlbumItemClickListener == null) { + onAlbumItemClickListener = (OnAlbumItemClickListener) activity; + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.nim_picker_image_folder_activity, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + findViews(); + startImageScanTask(); + } + + private void findViews() { + loadingLay = findView(R.id.picker_image_folder_loading); + loadingTips = findView(R.id.picker_image_folder_loading_tips); + loadingEmpty = findView(R.id.picker_image_folder_loading_empty); + albumListView = findView(R.id.picker_image_folder_listView); + albumListView.setOnItemClickListener(this); + } + + private void startImageScanTask() { + new ImageScanAsyncTask().execute(); + } + + private class ImageScanAsyncTask extends AsyncTask { + + @Override + protected Object doInBackground(Void... params) { + getAllMediaThumbnails(); + getAllMediaPhotos(); + + return null; + } + + @Override + protected void onPostExecute(Object result) { + super.onPostExecute(result); + if (getActivity() != null && albumInfolist != null) { + albumAdapter = new PickerAlbumAdapter(getActivity(), albumInfolist); + albumListView.setAdapter(albumAdapter); + + if (albumInfolist.size() > 0) { + loadingLay.setVisibility(View.GONE); + } else { + loadingLay.setVisibility(View.VISIBLE); + loadingTips.setVisibility(View.GONE); + loadingEmpty.setVisibility(View.VISIBLE); + } + } + } + } + + private void getAllMediaThumbnails() { + ThumbnailsUtil.clear(); + Cursor cursorThumb = null; + try { + cursorThumb = MediaDAO.getAllMediaThumbnails(getActivity()); + if (cursorThumb != null && cursorThumb.moveToFirst()) { + int imageID; + String imagePath; + do { + imageID = cursorThumb.getInt(cursorThumb.getColumnIndex(Thumbnails.IMAGE_ID)); + imagePath = cursorThumb.getString(cursorThumb.getColumnIndex(Thumbnails.DATA)); + ThumbnailsUtil.put(imageID, FILE_PREFIX + imagePath); + } while (cursorThumb.moveToNext()); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (cursorThumb != null) { + cursorThumb.close(); + } + } catch (Exception e) { + } + } + } + + private void getAllMediaPhotos() { + if (albumInfolist == null) { + albumInfolist = new ArrayList(); + } else { + albumInfolist.clear(); + } + + Cursor cursorPhotos = null; + try { + cursorPhotos = MediaDAO.getAllMediaPhotos(getActivity()); + HashMap hash = new HashMap(); + AlbumInfo albumInfo = null; + PhotoInfo photoInfo = null; + + if (cursorPhotos != null && cursorPhotos.moveToFirst()) { + do { + int index = 0; + int _id = cursorPhotos.getInt(cursorPhotos.getColumnIndex(MediaStore.Images.Media._ID)); + String path = cursorPhotos.getString(cursorPhotos.getColumnIndex(MediaStore.Images.Media.DATA)); + String album = cursorPhotos.getString(cursorPhotos.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); + long size = cursorPhotos.getLong(cursorPhotos.getColumnIndex(MediaStore.Images.Media.SIZE)); + + if (!isValidImageFile(path)) { + Log.d("PICKER", "it is not a vaild path:" + path); + continue; + } + + List photoList = new ArrayList(); + photoInfo = new PhotoInfo(); + if (hash.containsKey(album)) { + albumInfo = hash.remove(album); + if (albumInfolist.contains(albumInfo)) + index = albumInfolist.indexOf(albumInfo); + photoInfo.setImageId(_id); + photoInfo.setFilePath(FILE_PREFIX + path); + photoInfo.setAbsolutePath(path); + photoInfo.setSize(size); + albumInfo.getList().add(photoInfo); + albumInfolist.set(index, albumInfo); + hash.put(album, albumInfo); + } else { + albumInfo = new AlbumInfo(); + photoList.clear(); + photoInfo.setImageId(_id); + photoInfo.setFilePath(FILE_PREFIX + path); + photoInfo.setAbsolutePath(path); + photoInfo.setSize(size); + photoList.add(photoInfo); + albumInfo.setImageId(_id); + albumInfo.setFilePath(FILE_PREFIX + path); + albumInfo.setAbsolutePath(path); + albumInfo.setAlbumName(album); + albumInfo.setList(photoList); + albumInfolist.add(albumInfo); + hash.put(album, albumInfo); + } + } while (cursorPhotos.moveToNext()); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (cursorPhotos != null) { + cursorPhotos.close(); + } + } catch (Exception e) { + } + } + } + + private boolean isValidImageFile(String filePath) { + if (TextUtils.isEmpty(filePath)) { + return false; + } + + File imageFile = new File(filePath); + if (imageFile.exists()) { + return true; + } + + return false; + } + + @Override + public void onItemClick(AdapterView arg0, View arg1, int position, long arg3) { + onAlbumItemClickListener.OnAlbumItemClick(albumInfolist.get(position)); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/fragment/PickerImageFragment.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/fragment/PickerImageFragment.java new file mode 100644 index 0000000..41e485c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/fragment/PickerImageFragment.java @@ -0,0 +1,144 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.fragment; + +import android.app.Activity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.GridView; + +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.common.fragment.TFragment; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.adapter.PickerPhotoAdapter; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.model.PhotoInfo; +import com.netease.nim.uikit.R; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class PickerImageFragment extends TFragment implements OnItemClickListener { + + public interface OnPhotoSelectClickListener { + public void onPhotoSelectClick(PhotoInfo selectPhoto); + + public void onPhotoSingleClick(List photos, int position); + } + + private GridView pickerImageGridView; + + private OnPhotoSelectClickListener onPhotoSelectClickListener; + + private List photoList; + + private PickerPhotoAdapter photoAdapter; + + private boolean isMutiMode; + + private int mutiSelectLimitSize; + + public PickerImageFragment() { + this.setContainerId(R.id.picker_photos_fragment); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (onPhotoSelectClickListener == null) { + onPhotoSelectClickListener = (OnPhotoSelectClickListener) activity; + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.nim_picker_images_fragment, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + proceedExtra(); + findViews(); + } + + private void proceedExtra() { + Bundle bundle = getArguments(); + photoList = new ArrayList(); + photoList.addAll(getPhotos(bundle)); + isMutiMode = bundle.getBoolean(Extras.EXTRA_MUTI_SELECT_MODE); + mutiSelectLimitSize = bundle.getInt(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, 9); + } + + private void findViews() { + pickerImageGridView = findView(R.id.picker_images_gridview); + photoAdapter = new PickerPhotoAdapter(getActivity(), photoList, pickerImageGridView, isMutiMode, 0, mutiSelectLimitSize); + pickerImageGridView.setAdapter(photoAdapter); + pickerImageGridView.setOnItemClickListener(this); + } + + public void resetFragment(List list, int hasSelect) { + pickerImageGridView.setAdapter(null); + if (photoList == null) { + photoList = new ArrayList(); + } else { + photoList.clear(); + } + if (list != null) { + photoList.addAll(list); + } + photoAdapter = new PickerPhotoAdapter(getActivity(), photoList, pickerImageGridView, isMutiMode, hasSelect, mutiSelectLimitSize); + pickerImageGridView.setAdapter(photoAdapter); + } + + public void updateGridview(List list) { + if (list == null) + return; + for (int i = 0; i < list.size(); i++) { + PhotoInfo info = list.get(i); + int imageID = info.getImageId(); + boolean choose = info.isChoose(); + for (int j = 0; j < photoList.size(); j++) { + PhotoInfo phone = photoList.get(j); + if (phone.getImageId() == imageID) { + phone.setChoose(choose); + break; + } + } + } + if (photoAdapter != null) { + photoAdapter.notifyDataSetChanged(); + } + } + + public void updateSelectedForAdapter(int hasSelectNum) { + if (photoAdapter != null) { + photoAdapter.updateSelectNum(hasSelectNum); + } + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, + long id) { + onPhotoSelectClickListener.onPhotoSingleClick(photoList, position); + } + + public List getPhotos(Bundle bundle) { + return toPhotos(bundle.getSerializable(Extras.EXTRA_PHOTO_LISTS)); + } + + @SuppressWarnings("unchecked") + private List toPhotos(Serializable sPhotos) { + if (sPhotos != null && sPhotos instanceof List) { + return (List) sPhotos; + } + + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/loader/PickerImageLoader.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/loader/PickerImageLoader.java new file mode 100644 index 0000000..b65dfde --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/loader/PickerImageLoader.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.loader; + +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.RequestOptions; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; + +public class PickerImageLoader { + public static void initCache() { + } + + public static void clearCache() { + } + + public static void display(final String thumbPath, final String originalPath, final ImageView imageView, final int defResource) { + + RequestOptions requestOptions = new RequestOptions() + .centerCrop() + .placeholder(defResource) + .error(defResource) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .transform(new RotateTransformation(NimUIKit.getContext(), originalPath)); + + Glide.with(NimUIKit.getContext()) + .asBitmap() + .load(thumbPath) + .apply(requestOptions) + .into(imageView); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/loader/RotateTransformation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/loader/RotateTransformation.java new file mode 100644 index 0000000..b09416a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/loader/RotateTransformation.java @@ -0,0 +1,37 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.loader; + +import android.content.Context; +import android.graphics.Bitmap; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; +import com.fengliyan.tianlesue.im.uikit.common.media.picker.util.BitmapUtil; + +import java.security.MessageDigest; + +/** + * Created by huangjun on 2017/4/11. + */ + +class RotateTransformation extends BitmapTransformation { + private String path; + + RotateTransformation(Context context, String path) { + super(); + this.path = path; + } + + @Override + public void updateDiskCacheKey(MessageDigest messageDigest) { + messageDigest.update(getId().getBytes()); + } + + @Override + protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { + return BitmapUtil.reviewPicRotate(toTransform, path); + } + + public String getId() { + return "rotate_" + path.hashCode(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/AlbumInfo.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/AlbumInfo.java new file mode 100644 index 0000000..7afeeda --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/AlbumInfo.java @@ -0,0 +1,55 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.model; + +import java.io.Serializable; +import java.util.List; + +public class AlbumInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + private int imageID; + private String pathAbsolute; + private String pathFile; + private String nameAlbum; + private List list; + + public int getImageId() { + return imageID; + } + + public void setImageId(int imageID) { + this.imageID = imageID; + } + + public String getAbsolutePath() { + return pathAbsolute; + } + + public void setAbsolutePath(String pathAbsolute) { + this.pathAbsolute = pathAbsolute; + } + + public String getFilePath() { + return pathFile; + } + + public void setFilePath(String pathFile) { + this.pathFile = pathFile; + } + + public String getAlbumName() { + return nameAlbum; + } + + public void setAlbumName(String nameAlbum) { + this.nameAlbum = nameAlbum; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/GenericFileProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/GenericFileProvider.java new file mode 100644 index 0000000..8a26a5b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/GenericFileProvider.java @@ -0,0 +1,10 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.model; + +import androidx.core.content.FileProvider; + +/** + * Created by winnie on 2017/7/26. + */ + +public class GenericFileProvider extends FileProvider { +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/PhotoInfo.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/PhotoInfo.java new file mode 100644 index 0000000..fcbe038 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/PhotoInfo.java @@ -0,0 +1,54 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.model; + +import java.io.Serializable; + +public class PhotoInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + private int imageId; + private String filePath; + private String absolutePath; + private long size; + private boolean choose = false; + + public int getImageId() { + return imageId; + } + + public void setImageId(int id) { + this.imageId = id; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getAbsolutePath() { + return absolutePath; + } + + public void setAbsolutePath(String absolutePath) { + this.absolutePath = absolutePath; + } + + public boolean isChoose() { + return choose; + } + + public void setChoose(boolean choose) { + this.choose = choose; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/PickerContract.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/PickerContract.java new file mode 100644 index 0000000..53c4083 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/model/PickerContract.java @@ -0,0 +1,92 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.model; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class PickerContract { + // NOTE MAINTAIN PICKER ACTIVITY CLASS NAME + private static final String PICKER_CLASS = "im.yixin.media.picker.activity.PickerAlbumActivity"; + + + public static final Intent makeLaunchIntent(Context context, boolean mutiSelectMode, int mutiSelectLimitSize, boolean isSupportOrig) { + + Intent intent = new Intent(); + intent.setComponent(new ComponentName(context, PICKER_CLASS)); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_MODE, mutiSelectMode); + intent.putExtra(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, + mutiSelectLimitSize); + intent.putExtra(Extras.EXTRA_SUPPORT_ORIGINAL, isSupportOrig); + + return intent; + } + + public static final Intent makeDataIntent(List photos, boolean origin) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_PHOTO_LISTS, new ArrayList(photos)); + intent.putExtra(Extras.EXTRA_IS_ORIGINAL, origin); + + return intent; + } + + public static final Intent makeDataIntent(List photos) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_PHOTO_LISTS, new ArrayList(photos)); + + return intent; + } + + public static final Intent makePreviewDataIntent(List photos, List selectPhotos) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_PHOTO_LISTS, new ArrayList(photos)); + intent.putExtra(Extras.EXTRA_SELECTED_IMAGE_LIST, new ArrayList(selectPhotos)); + + return intent; + } + + public static final Intent makePreviewDataIntent(List photos, List selectPhotos, boolean origin) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_PHOTO_LISTS, new ArrayList(photos)); + intent.putExtra(Extras.EXTRA_SELECTED_IMAGE_LIST, new ArrayList(selectPhotos)); + intent.putExtra(Extras.EXTRA_IS_ORIGINAL, origin); + + return intent; + } + + public static final Bundle makeDataBundle(List photos, boolean mutiMode, int mutiSelectLimitSize) { + Bundle bundle = new Bundle(); + bundle.putSerializable(Extras.EXTRA_PHOTO_LISTS, new ArrayList(photos)); + bundle.putBoolean(Extras.EXTRA_MUTI_SELECT_MODE, mutiMode); + bundle.putInt(Extras.EXTRA_MUTI_SELECT_SIZE_LIMIT, mutiSelectLimitSize); + + return bundle; + } + + public static final List getPhotos(Bundle bundle) { + return toPhotos(bundle.getSerializable(Extras.EXTRA_PHOTO_LISTS)); + } + + public static final List getPhotos(Intent intent) { + return toPhotos(intent.getSerializableExtra(Extras.EXTRA_PHOTO_LISTS)); + } + + public static final List getSelectPhotos(Intent intent) { + return toPhotos(intent.getSerializableExtra(Extras.EXTRA_SELECTED_IMAGE_LIST)); + } + + @SuppressWarnings("unchecked") + private static final List toPhotos(Serializable sPhotos) { + if (sPhotos != null && sPhotos instanceof List) { + return (List) sPhotos; + } + + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/BitmapUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/BitmapUtil.java new file mode 100644 index 0000000..a61d8e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/BitmapUtil.java @@ -0,0 +1,94 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.util; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.media.ExifInterface; +import android.text.TextUtils; + +import java.io.IOException; + + +public class BitmapUtil { + + public static Bitmap reviewPicRotate(Bitmap bitmap, String path) { + int degree = 0; + String mimeType = getImageType(path); + if (!TextUtils.isEmpty(mimeType) && !mimeType.equals("image/png")) { + degree = getPicRotate(path); // PNG没有旋转信息 + } + if (degree != 0) { + try { + Matrix m = new Matrix(); + int width = bitmap.getWidth(); + int height = bitmap.getHeight(); + m.setRotate(degree); + bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, true); + } catch (Exception e) { + e.printStackTrace(); + } + } + return bitmap; + } + + /** + * 获取图片类型 + * + * @param path 图片绝对路径 + * @return 图片类型image/jpeg image/png + */ + public static String getImageType(String path) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(path, options); + return options.outMimeType; + } + + /** + * 读取图片属性:旋转的角度 + * + * @param path 图片绝对路径 + * @return degree旋转的角度 + */ + public static int getPicRotate(String path) { + int degree = 0; + try { + ExifInterface exifInterface = new ExifInterface(path); + int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); + switch (orientation) { + case ExifInterface.ORIENTATION_ROTATE_90: + degree = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + degree = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + degree = 270; + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + return degree; + } + + public static Bitmap resizeBitmap(Bitmap bitmap, int w, int h) { + if (bitmap == null) { + return null; + } + + Bitmap BitmapOrg = bitmap; + int width = BitmapOrg.getWidth(); + int height = BitmapOrg.getHeight(); + int newWidth = w; + int newHeight = h; + + float scaleWidth = ((float) newWidth) / width; + float scaleHeight = ((float) newHeight) / height; + + Matrix matrix = new Matrix(); + matrix.postScale(scaleWidth, scaleHeight); + + return Bitmap.createBitmap(BitmapOrg, 0, 0, width, height, matrix, true); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/PickerUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/PickerUtil.java new file mode 100644 index 0000000..2889c3d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/PickerUtil.java @@ -0,0 +1,37 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.util; + +import java.math.BigDecimal; + +public class PickerUtil { + + public static String getFileSizeString(long size) { + if (size <= 0) { + return "0B"; + } + + // < 1K + if (size < 1024) { + return size + "B"; + } + // 1K -- 1M + else if (size >= 1024 && size < 1048576) { + double dout = (size * 1.0) / 1024; + BigDecimal bd = new BigDecimal(dout); + bd = bd.setScale(0, BigDecimal.ROUND_HALF_UP); + return (int) bd.doubleValue() + "K"; + } + // > 1M + else if (size >= 1048576 && size < 1073741824) { + double dout = (size * 1.0) / 1048576; + BigDecimal bd = new BigDecimal(dout); + bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP); + return bd.doubleValue() + "M"; + } else { + double dout = (size * 1.0) / 1073741824; + BigDecimal bd = new BigDecimal(dout); + bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP); + return bd.doubleValue() + "GB"; + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/ThumbnailsUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/ThumbnailsUtil.java new file mode 100644 index 0000000..76c3487 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/media/picker/util/ThumbnailsUtil.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.im.uikit.common.media.picker.util; + +import android.annotation.SuppressLint; +import android.text.TextUtils; + +import java.io.File; +import java.util.HashMap; + +public class ThumbnailsUtil { + + @SuppressLint("UseSparseArrays") + private static HashMap hash = new HashMap(); + + public static String getThumbnailWithImageID(int key, String defalt) { + if (hash == null || !hash.containsKey(key)) { + return defalt; + } + + try { + String thumbFilePath = hash.get(key); + if (TextUtils.isEmpty(thumbFilePath)) { + return defalt; + } + String thumbPath = thumbFilePath.substring("file://".length()); + File file = new File(thumbPath); + if (file.exists()) { + return thumbFilePath; + } + } catch (Exception e) { + } + + return defalt; + } + + public static void put(Integer key, String value) { + hash.put(key, value); + } + + public static void clear() { + hash.clear(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageConfig.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageConfig.java new file mode 100644 index 0000000..a525dac --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageConfig.java @@ -0,0 +1,51 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.barrage; + +import java.util.List; + +/** + * 弹幕全局配置: + * 1.最大最小的文本尺寸SP + * 2.文本颜色集合 + * 3.一个文本弹幕在屏幕上滚动的时间 + */ +public class BarrageConfig { + private int minTextSizeSp = 14; + private int maxTextSizeSp = 18; + private int duration = 5000; + private List colors; + + public BarrageConfig() { + } + + public int getMinTextSizeSp() { + return minTextSizeSp; + } + + public void setMinTextSizeSp(int minTextSizeSp) { + this.minTextSizeSp = minTextSizeSp; + } + + public int getMaxTextSizeSp() { + return maxTextSizeSp; + } + + public void setMaxTextSizeSp(int maxTextSizeSp) { + this.maxTextSizeSp = maxTextSizeSp; + } + + public List getColors() { + return colors; + } + + public void setColors(List colors) { + this.colors = colors; + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.duration = duration; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageSurfaceView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageSurfaceView.java new file mode 100644 index 0000000..0ff717c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageSurfaceView.java @@ -0,0 +1,263 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.barrage; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; + +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Random; +import java.util.Set; + +/** + * 弹幕控件 + *

+ * Created by huangjun on 2016/5/8. + */ +public class BarrageSurfaceView extends SurfaceViewTemplate { + + private static final String TAG = "BarrageSurfaceView"; + + private static final boolean OUTPUT_LOG = true; + + private static final int DEFAULT_RANDOM_COLOR_NUM = 30; + + private static final int TIME_INTERVAL = 30; + + private static final int MESSAGE_FREE_LINE = 0x01; + + private static final int MESSAGE_END = 0x02; + + private static final String MESSAGE_DATA_LINE = "LINE"; + + private Random random; + + // 配置管理 + private BarrageConfig config; + + // 轨道管理 + private Set linesUnavailable = new HashSet<>(); + private int lineCount; + private int lineHeight; + + // 字幕管理 + private Queue textCache = new LinkedList<>(); + + // 执行者管理(多线程访问) + private final List tasks = new LinkedList<>(); + + public BarrageSurfaceView(Context context) { + super(context); + } + + public BarrageSurfaceView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void init(final BarrageConfig config) { + this.random = new Random(); + int totalLineHeight = getBottom() - getTop() - getPaddingTop() - getPaddingBottom(); + this.lineHeight = ScreenUtil.sp2px(config.getMaxTextSizeSp()); + this.lineCount = totalLineHeight / lineHeight; + + // random colors + if (config.getColors() == null || config.getColors().isEmpty()) { + List colors = new ArrayList<>(DEFAULT_RANDOM_COLOR_NUM); + for (int i = 0; i < DEFAULT_RANDOM_COLOR_NUM; i++) { + colors.add(Color.rgb(random.nextInt(256), random.nextInt(256), random.nextInt(256))); + } + config.setColors(colors); + } + this.config = config; + + log("barrage init, lineHeight=" + lineHeight + ", lineCount=" + lineCount); + } + + public void addTextBarrage(String text) { + if (TextUtils.isEmpty(text)) { + return; + } + + textCache.add(text); + + checkAndRunTextBarrage(); + } + + private void checkAndRunTextBarrage() { + if (textCache.isEmpty()) { + return; + } + + int availableLine = getAvailableLine(); + if (availableLine < 0) { + return; // pend + } + + BarrageTextTask task = buildBarrageTextTask(textCache.poll(), availableLine); + synchronized (tasks) { + tasks.add(task); + } + + notifyHasTask(); // 通知有绘制任务 + } + + private int getAvailableLine() { + int line = -1; + for (int i = 0; i < lineCount; i++) { + if (!linesUnavailable.contains(i)) { + line = i; + break; + } + } + + if (line >= 0 && line < lineCount) { + linesUnavailable.add(line); // 占用 + } + + return line; + } + + private BarrageTextTask buildBarrageTextTask(String text, int line) { + if (TextUtils.isEmpty(text)) { + return null; + } + + // text size, length + int size = config.getMinTextSizeSp() + random.nextInt(config.getMaxTextSizeSp() - config.getMinTextSizeSp() + 1); + size = ScreenUtil.sp2px(size); + + // text color + int color; + if (config.getColors() != null && !config.getColors().isEmpty()) { + color = config.getColors().get(random.nextInt(config.getColors().size())); + } else { + color = Color.rgb(random.nextInt(256), random.nextInt(256), random.nextInt(256)); + } + + // duration + int duration = config.getDuration() + random.nextInt() % 500; + + // start position + float x = getWidth(); + float y = size + line * lineHeight; + + // speed + float deltaX = (1.0f * getWidth() / duration) * TIME_INTERVAL; + + // log + StringBuilder log = new StringBuilder(); + log.append("build text barrage task") + .append(", line=").append(line) + .append(", text=").append(text) + .append(", speed=").append(deltaX); + log(log.toString()); + + return new BarrageTextTask(text, line, color, size, duration, x, y, deltaX); + } + + private Handler mHandler = new Handler(getContext().getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_FREE_LINE: + onLineAvailable(msg.getData().getInt(MESSAGE_DATA_LINE)); + break; + case MESSAGE_END: + onTextBarrageDone(msg.getData().getInt(MESSAGE_DATA_LINE)); + break; + default: + super.handleMessage(msg); + } + } + }; + + private void onLineAvailable(final int line) { + log("free line, line=" + line); + + linesUnavailable.remove(line); + checkAndRunTextBarrage(); + } + + private void onTextBarrageDone(final int line) { + log("text barrage completed, line=" + line); + + checkAndRunTextBarrage(); + } + + + /** + * ******************************** 在线程中执行绘制 ************************************ + */ + @Override + public void onDrawView(Canvas canvas) { + synchronized (tasks) { + if (tasks.size() <= 0) { + return; + } + + Iterator iterator = tasks.iterator(); + BarrageTextTask task; + while (iterator.hasNext()) { + task = iterator.next(); + // draw + task.updatePosition(); + canvas.drawText(task.getText(), task.getX(), task.getY(), task.getPaint()); + + // check end + if (task.isEnd()) { + iterator.remove(); // reach the end,remove + Message message = new Message(); + message.what = MESSAGE_END; + Bundle data = new Bundle(); + data.putInt(MESSAGE_DATA_LINE, task.getLine()); + message.setData(data); + mHandler.sendMessage(message); + continue; + } + + // check free line + if (task.canFreeLine()) { + Message message = new Message(); + message.what = MESSAGE_FREE_LINE; + Bundle data = new Bundle(); + data.putInt(MESSAGE_DATA_LINE, task.getLine()); + message.setData(data); + mHandler.sendMessage(message); + } + } + } + } + + @Override + public int getRunTimeInterval() { + return TIME_INTERVAL; + } + + @Override + protected boolean hasTask() { + boolean hasTask; + synchronized (tasks) { + hasTask = tasks.size() > 0; + } + + return hasTask; + } + + private void log(String message) { + if (OUTPUT_LOG) { + Log.i(TAG, message); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageTextTask.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageTextTask.java new file mode 100644 index 0000000..ef13219 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/BarrageTextTask.java @@ -0,0 +1,83 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.barrage; + +import android.text.TextPaint; + +/** + * Created by huangjun on 2016/5/8. + */ +class BarrageTextTask { + // build + private String text; + private int line; + private int duration; + private float x; + private float y; + private float deltaX; + private float length; + private TextPaint paint; + + // inner + private float runX; + private boolean hasFree; + + BarrageTextTask(String text, int line, int color, int size, int duration, float x, float y, float deltaX) { + this.text = text; + this.line = line; + this.duration = duration; + this.x = x; + this.y = y; + this.deltaX = deltaX; + this.paint = new TextPaint(); + this.paint.setTextSize(size); + this.paint.setColor(color); + this.length = paint.measureText(text); + this.runX = 0.0f; + this.hasFree = false; + } + + void updatePosition() { + runX += deltaX; + x -= deltaX; + } + + boolean canFreeLine() { + if (hasFree) { + return false; + } + + if (runX > length + 60.0f) { + hasFree = true; + return true; + } + + return false; + } + + boolean isEnd() { + return x < -1 * length; // 是否应该结束 + } + + String getText() { + return text; + } + + int getLine() { + return line; + } + + int getDuration() { + return duration; + } + + float getX() { + return x; + } + + float getY() { + return y; + } + + TextPaint getPaint() { + return paint; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/SurfaceViewTemplate.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/SurfaceViewTemplate.java new file mode 100644 index 0000000..c8621bc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/barrage/SurfaceViewTemplate.java @@ -0,0 +1,123 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.barrage; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.util.AttributeSet; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +/** + * SurfaceView 任务队列驱动/间隔绘制模板 + * Created by huangjun on 2016/5/8. + */ +public abstract class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable { + + private SurfaceHolder mHolder; + private Canvas canvas; + private boolean isRunning; + private final Object lock = new Object(); + + public SurfaceViewTemplate(Context context) { + this(context, null); + } + + public SurfaceViewTemplate(Context context, AttributeSet attrs) { + super(context, attrs); + + mHolder = getHolder(); + mHolder.addCallback(this); + + // 设置Surface在Window(普通视图架构)之上 + setZOrderOnTop(true); + // 设置色彩格式,半透明 + mHolder.setFormat(PixelFormat.TRANSLUCENT); + + // 设置可获得焦点 + setFocusable(true); + setFocusableInTouchMode(true); + + // 设置保持屏幕亮 + this.setKeepScreenOn(true); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + isRunning = true; + new Thread(this).start(); // 开启线程 + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + notifyHasTask(); // 释放锁 + isRunning = false; // 通知关闭线程 + } + + @Override + public void run() { + while (isRunning) { + try { + // 判断是否还有绘制任务,任务队列空可以先wait,等待任务唤醒 + synchronized (lock) { + if (!hasTask()) { + lock.wait(); + } + } + + // 执行绘制任务 + draw(); + + // 控制绘制的时间间隔 + Thread.sleep(getRunTimeInterval()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void draw() { + try { + // get canvas + canvas = mHolder.lockCanvas(); // 如果SurfaceView不在前台,这里会阻塞 + if (canvas != null) { + // clear screen + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + + // do draw task + onDrawView(canvas); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (canvas != null) + mHolder.unlockCanvasAndPost(canvas); + } + } + + /** + * 执行绘制任务 + */ + protected abstract void onDrawView(Canvas canvas); + + /** + * 绘制任务执行间隔 + */ + protected abstract int getRunTimeInterval(); + + /** + * 是否有绘制任务 + */ + protected abstract boolean hasTask(); + + protected void notifyHasTask() { + synchronized (lock) { + lock.notify(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/CustomAlertDialog.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/CustomAlertDialog.java new file mode 100644 index 0000000..0eed7a7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/CustomAlertDialog.java @@ -0,0 +1,243 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.app.AlertDialog; +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Pair; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.BaseAdapter; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapter; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TAdapterDelegate; +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +import java.util.LinkedList; +import java.util.List; + +public class CustomAlertDialog extends AlertDialog { + + private Context context; + + private int itemSize = 0; + + private View titleView; + + private TextView titleTextView; + + private ImageButton titleBtn; + + private ListView listView; + + private boolean isTitleVisible = false; + + private boolean isTitleBtnVisible = false; + + private String title; + + private View.OnClickListener titleListener = null; + + private List> itemTextList = new LinkedList>(); + + private List itemListenerList = new LinkedList(); + + private OnClickListener listListener; + + private BaseAdapter listAdapter; + + private OnItemClickListener itemListener; + + private int defaultColor = R.color.color_black_333333; + + public CustomAlertDialog(Context context) { + super(context, R.style.dialog_default_style); + this.context = context; + initAdapter(); + } + + public CustomAlertDialog(Context context, int itemSize) { + super(context, R.style.dialog_default_style); + this.context = context; + this.itemSize = itemSize; + } + + private void initAdapter() { + listAdapter = new TAdapter(context, itemTextList, new TAdapterDelegate() { + + @Override + public int getViewTypeCount() { + return itemTextList.size(); + } + + @Override + public Class viewHolderAtPosition(int position) { + return CustomDialogViewHolder.class; + } + + @Override + public boolean enabled(int position) { + return true; + } + }); + itemListener = new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + itemListenerList.get(position).onClick(); + dismiss(); + } + }; + } + + public void setAdapter(final BaseAdapter adapter, final OnClickListener listener) { + listAdapter = adapter; + listListener = listener; + itemListener = new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + dismiss(); + listListener.onClick(CustomAlertDialog.this, position); + } + }; + } + + public void setAdapter(final BaseAdapter adapter, final OnItemClickListener listener) { + listAdapter = adapter; + itemListener = listener; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.nim_easy_alert_dialog_with_listview); + LinearLayout root = (LinearLayout) findViewById(R.id.easy_alert_dialog_layout); + ViewGroup.LayoutParams params = root.getLayoutParams(); + params.width = (int) ScreenUtil.getDialogWidth(); + root.setLayoutParams(params); + addFootView(root); + titleView = findViewById(R.id.easy_dialog_title_view); + if (titleView != null) { + setTitleVisible(isTitleVisible); + } + titleTextView = (TextView) findViewById(R.id.easy_dialog_title_text_view); + if (titleTextView != null) { + setTitle(title); + } + titleBtn = (ImageButton) findViewById(R.id.easy_dialog_title_button); + if (titleBtn != null) { + setTitleBtnVisible(isTitleBtnVisible); + setTitleBtnListener(titleListener); + } + listView = (ListView) findViewById(R.id.easy_dialog_list_view); + if (itemSize > 0) { + updateListView(); + } + } + + protected void addFootView(LinearLayout parent) { + + } + + public void setTitle(String title) { + this.title = title; + isTitleVisible = TextUtils.isEmpty(title) ? false : true; + setTitleVisible(isTitleVisible); + if (isTitleVisible && titleTextView != null) { + titleTextView.setText(title); + } + } + + public void setTitle(int resId) { + this.title = context.getString(resId); + isTitleVisible = TextUtils.isEmpty(title) ? false : true; + setTitleVisible(isTitleVisible); + if (isTitleVisible && titleTextView != null) { + titleTextView.setText(title); + } + } + + public void setTitleVisible(boolean visible) { + isTitleVisible = visible; + if (titleView != null) { + titleView.setVisibility(isTitleVisible ? View.VISIBLE : View.GONE); + } + } + + public void setTitleBtnVisible(boolean visible) { + isTitleBtnVisible = visible; + if (titleBtn != null) { + titleBtn.setVisibility(isTitleBtnVisible ? View.VISIBLE : View.GONE); + } + } + + public void setTitleBtnListener(View.OnClickListener titleListener) { + this.titleListener = titleListener; + if (titleListener != null && titleBtn != null) { + titleBtn.setOnClickListener(titleListener); + } + } + + public void addItem(String itemText, onSeparateItemClickListener listener) { + addItem(itemText, defaultColor, listener); + } + + public void addItem(String itemText, int color, onSeparateItemClickListener listener) { + itemTextList.add(new Pair(itemText, color)); + itemListenerList.add(listener); + itemSize = itemTextList.size(); + } + + public void addItem(int resId, onSeparateItemClickListener listener) { + addItem(context.getString(resId), listener); + } + + public void addItem(int resId, int color, onSeparateItemClickListener listener) { + addItem(context.getString(resId), color, listener); + } + + public void addItemAfterAnother(String itemText, String another, onSeparateItemClickListener listener) { + int index = itemTextList.indexOf(another); + itemTextList.add(index + 1, new Pair(itemText, defaultColor)); + itemListenerList.add(index + 1, listener); + itemSize = itemTextList.size(); + } + + public void clearData() { + itemTextList.clear(); + itemListenerList.clear(); + itemSize = 0; + } + + private void updateListView() { + listAdapter.notifyDataSetChanged(); + if (listView != null) { + listView.setAdapter(listAdapter); + listView.setOnItemClickListener(itemListener); + } + } + + public interface onSeparateItemClickListener { + + void onClick(); + } + + @Override + public void show() { + if (itemSize <= 0) { + return; + } + updateListView(); + super.show(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/CustomDialogViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/CustomDialogViewHolder.java new file mode 100644 index 0000000..9b1f34e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/CustomDialogViewHolder.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.util.Pair; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.adapter.TViewHolder; +import com.netease.nim.uikit.R; + +public class CustomDialogViewHolder extends TViewHolder { + + private TextView itemView; + + @Override + protected int getResId() { + return R.layout.nim_custom_dialog_list_item; + } + + @Override + protected void inflate() { + itemView = (TextView) view.findViewById(R.id.custom_dialog_text_view); + } + + @Override + protected void refresh(Object item) { + if (item instanceof Pair) { + Pair pair = (Pair) item; + itemView.setText(pair.first); + itemView.setTextColor(context.getResources().getColor(pair.second)); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/DialogMaker.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/DialogMaker.java new file mode 100644 index 0000000..deba6e0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/DialogMaker.java @@ -0,0 +1,91 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.content.Context; +import android.content.DialogInterface.OnCancelListener; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; + +import java.lang.ref.WeakReference; + +public class DialogMaker { + + private static WeakReference sProgressDialogRef; + + public static EasyProgressDialog showProgressDialog(Context context, String message) { + return showProgressDialog(context, null, message, true, null); + } + + public static EasyProgressDialog showProgressDialog(Context context, String message, boolean cancelable) { + return showProgressDialog(context, null, message, cancelable, null); + } + + @Deprecated + public static EasyProgressDialog showProgressDialog(Context context, String title, String message, + boolean canCancelable, OnCancelListener listener) { + + EasyProgressDialog dialog = getDialog(); + + if (dialog != null && dialog.getContext() != context) { + // maybe existing dialog is running in a destroyed activity cotext we should recreate one + dismissProgressDialog(); + dialog = null; + LogUtil.e("dialog", "there is a leaked window here,orign context: " + dialog.getContext() + " now: " + context); + } + + if (dialog == null) { + dialog = new EasyProgressDialog(context, message); + sProgressDialogRef = new WeakReference<>(dialog); + } + + if (!TextUtils.isEmpty(title)) { + dialog.setTitle(title); + } + if (!TextUtils.isEmpty(message)) { + dialog.setMessage(message); + } + dialog.setCancelable(canCancelable); + dialog.setOnCancelListener(listener); + dialog.show(); + return dialog; + } + + public static void dismissProgressDialog() { + EasyProgressDialog dialog = getDialog(); + if (null == dialog) { + return; + } + sProgressDialogRef.clear(); + if (dialog.isShowing()) { + try { + dialog.dismiss(); + } catch (Exception e) { + // maybe we catch IllegalArgumentException here. + } + } + + } + + public static void setMessage(String message) { + EasyProgressDialog dialog = getDialog(); + if (null != dialog && dialog.isShowing() && !TextUtils.isEmpty(message)) { + dialog.setMessage(message); + } + } + + public static void updateLoadingMessage(String message) { + EasyProgressDialog dialog = getDialog(); + if (null != dialog && dialog.isShowing() && !TextUtils.isEmpty(message)) { + dialog.updateLoadingMessage(message); + } + } + + public static boolean isShowing() { + EasyProgressDialog dialog = getDialog(); + return (dialog != null && dialog.isShowing()); + } + + private static EasyProgressDialog getDialog() { + return sProgressDialogRef == null ? null : sProgressDialogRef.get(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyAlertDialog.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyAlertDialog.java new file mode 100644 index 0000000..3f90fb9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyAlertDialog.java @@ -0,0 +1,320 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager.LayoutParams; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * 普通提示包含两个按钮以及Title和Message(居中显示). + *

+ * 警告提示使用包含一个按钮以及Title和Message(居中显示). + *

+ * 错误提示使用包含一个按钮(红色背景)以及Title和Message(居中显示). + *

+ * 特殊布局需求可以自定义布局. + */ +public class EasyAlertDialog extends Dialog { + private Context context; + + public static final int NO_TEXT_COLOR = -99999999; + + public static final int NO_TEXT_SIZE = -99999999; + + private View titleView; + + private ImageButton titleBtn; + + private TextView titleTV; + + private TextView messageTV; + + private TextView message2TV; + + private Button positiveBtn, negativeBtn; + + private View btnDivideView; + + private CharSequence title = "", message = "", message2 = "", positiveBtnTitle = "", negativeBtnTitle = ""; + + private int titleTextColor = NO_TEXT_COLOR, msgTextColor = NO_TEXT_COLOR, + positiveBtnTitleTextColor = NO_TEXT_COLOR, negativeBtnTitleTextColor = NO_TEXT_COLOR; + + private float titleTextSize = NO_TEXT_SIZE, msgTextSize = NO_TEXT_SIZE, positiveBtnTitleTextSize = NO_TEXT_SIZE, + negativeBtnTitleTextSize = NO_TEXT_SIZE; + + private int resourceId; + + private boolean isPositiveBtnVisible = true, isNegativeBtnVisible = false; + + private boolean isTitleVisible = false, isMessageVisble = true, isTitleBtnVisible = false; + + private View.OnClickListener positiveBtnListener, negativeBtnListener; + + private HashMap mViewListener = new HashMap(); + + public EasyAlertDialog(Context context, int resourceId, int style) { + super(context, style); + this.context = context; + if (-1 != resourceId) { + setContentView(resourceId); + this.resourceId = resourceId; + } + LayoutParams Params = getWindow().getAttributes(); + Params.width = LayoutParams.MATCH_PARENT; + Params.height = LayoutParams.MATCH_PARENT; + getWindow().setAttributes((LayoutParams) Params); + } + + public EasyAlertDialog(Context context, int style) { + this(context, -1, style); + resourceId = R.layout.nim_easy_alert_dialog_default_layout; + } + + public EasyAlertDialog(Context context) { + this(context, R.style.dialog_default_style); + resourceId = R.layout.nim_easy_alert_dialog_default_layout; + } + + public void setTitle(CharSequence title) { + isTitleVisible = TextUtils.isEmpty(title) ? false : true; + setTitleVisible(isTitleVisible); + if (null != title) { + this.title = title; + if (null != titleTV) + titleTV.setText(title); + } + } + + public void setTitleVisible(boolean visible) { + isTitleVisible = visible; + if (titleView != null) { + titleView.setVisibility(isTitleVisible ? View.VISIBLE : View.GONE); + } + } + + public void setTitleBtnVisible(boolean visible) { + isTitleBtnVisible = visible; + if (titleBtn != null) { + titleBtn.setVisibility(isTitleBtnVisible ? View.VISIBLE : View.GONE); + } + } + + public void setTitleTextColor(int color) { + titleTextColor = color; + if (null != titleTV && NO_TEXT_COLOR != color) + titleTV.setTextColor(color); + } + + public void setMessageTextColor(int color) { + msgTextColor = color; + if (null != messageTV && NO_TEXT_COLOR != color) + messageTV.setTextColor(color); + + } + + public void setMessageTextSize(float size) { + msgTextSize = size; + if (null != messageTV && NO_TEXT_SIZE != size) + messageTV.setTextSize(size); + } + + public void setTitleTextSize(float size) { + titleTextSize = size; + if (null != titleTV && NO_TEXT_SIZE != size) + titleTV.setTextSize(size); + } + + public void setMessageVisible(boolean visible) { + isMessageVisble = visible; + if (messageTV != null) { + messageTV.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + + public void setMessage(CharSequence message) { + if (null != message) { + this.message = message; + if (null != messageTV) + messageTV.setText(message); + } + } + + public void setMessage2(CharSequence message) { + if (!TextUtils.isEmpty(message)) { + this.message2 = message; + if (null != message2TV) { + message2TV.setText(message); + } + } + } + + public void addPositiveButton(CharSequence title, int color, float size, + View.OnClickListener positiveBtnListener) { + isPositiveBtnVisible = true; + positiveBtnTitle = TextUtils.isEmpty(title) ? context + .getString(R.string.ok) : title; + positiveBtnTitleTextColor = color; + positiveBtnTitleTextSize = size; + this.positiveBtnListener = positiveBtnListener; + + if (positiveBtn != null) { + positiveBtn.setText(positiveBtnTitle); + positiveBtn.setTextColor(positiveBtnTitleTextColor); + positiveBtn.setTextSize(positiveBtnTitleTextSize); + positiveBtn.setOnClickListener(positiveBtnListener); + } + } + + public void addNegativeButton(CharSequence title, int color, float size, + View.OnClickListener negativeBtnListener) { + isNegativeBtnVisible = true; + negativeBtnTitle = TextUtils.isEmpty(title) ? context + .getString(R.string.cancel) : title; + negativeBtnTitleTextColor = color; + negativeBtnTitleTextSize = size; + this.negativeBtnListener = negativeBtnListener; + + if (negativeBtn != null) { + negativeBtn.setText(negativeBtnTitle); + negativeBtn.setTextColor(negativeBtnTitleTextColor); + negativeBtn.setTextSize(negativeBtnTitleTextSize); + negativeBtn.setOnClickListener(negativeBtnListener); + } + } + + public void addPositiveButton(CharSequence title, + View.OnClickListener positiveBtnListener) { + addPositiveButton(title, NO_TEXT_COLOR, NO_TEXT_SIZE, + positiveBtnListener); + } + + public void addNegativeButton(CharSequence title, + View.OnClickListener negativeBtnListener) { + addNegativeButton(title, NO_TEXT_COLOR, NO_TEXT_SIZE, + negativeBtnListener); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(resourceId); + try { + ViewGroup root = (ViewGroup) findViewById(R.id.easy_alert_dialog_layout); + if (root != null) { + ViewGroup.LayoutParams params = root.getLayoutParams(); + params.width = (int) ScreenUtil.getDialogWidth(); + root.setLayoutParams(params); + } + + titleView = findViewById(R.id.easy_dialog_title_view); + if (titleView != null) { + setTitleVisible(isTitleVisible); + } + titleBtn = (ImageButton) findViewById(R.id.easy_dialog_title_button); + if (titleBtn != null) { + setTitleBtnVisible(isTitleBtnVisible); + } + titleTV = (TextView) findViewById(R.id.easy_dialog_title_text_view); + if (titleTV != null) { + titleTV.setText(title); + if (NO_TEXT_COLOR != titleTextColor) + titleTV.setTextColor(titleTextColor); + if (NO_TEXT_SIZE != titleTextSize) + titleTV.setTextSize(titleTextSize); + } + + messageTV = (TextView) findViewById(R.id.easy_dialog_message_text_view); + if (messageTV != null) { + messageTV.setText(message); + setMessageVisible(isMessageVisble); + if (NO_TEXT_COLOR != msgTextColor) + messageTV.setTextColor(msgTextColor); + if (NO_TEXT_SIZE != msgTextSize) + messageTV.setTextSize(msgTextSize); + } + + message2TV = (TextView) findViewById(R.id.easy_dialog_message_2); + if (message2TV != null && !TextUtils.isEmpty(message2)) { + message2TV.setVisibility(View.VISIBLE); + message2TV.setText(message2); + } + + positiveBtn = (Button) findViewById(R.id.easy_dialog_positive_btn); + if (isPositiveBtnVisible && positiveBtn != null) { + positiveBtn.setVisibility(View.VISIBLE); + if (NO_TEXT_COLOR != positiveBtnTitleTextColor) { + positiveBtn.setTextColor(positiveBtnTitleTextColor); + } + if (NO_TEXT_SIZE != positiveBtnTitleTextSize) { + positiveBtn.setTextSize(positiveBtnTitleTextSize); + } + positiveBtn.setText(positiveBtnTitle); + positiveBtn.setOnClickListener(positiveBtnListener); + } + + negativeBtn = (Button) findViewById(R.id.easy_dialog_negative_btn); + btnDivideView = findViewById(R.id.easy_dialog_btn_divide_view); + if (isNegativeBtnVisible) { + negativeBtn.setVisibility(View.VISIBLE); + btnDivideView.setVisibility(View.VISIBLE); + if (NO_TEXT_COLOR != this.negativeBtnTitleTextColor) { + negativeBtn.setTextColor(negativeBtnTitleTextColor); + } + if (NO_TEXT_SIZE != this.negativeBtnTitleTextSize) { + negativeBtn.setTextSize(negativeBtnTitleTextSize); + } + negativeBtn.setText(negativeBtnTitle); + negativeBtn.setOnClickListener(negativeBtnListener); + } + + if (mViewListener != null && mViewListener.size() != 0) { + Iterator iter = mViewListener.entrySet().iterator(); + View view = null; + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry) iter.next(); + view = findViewById(entry.getKey()); + if (view != null && entry.getValue() != null) { + view.setOnClickListener(entry.getValue()); + } + } + } + + } catch (Exception e) { + + } + } + + public int getResourceId() { + return resourceId; + } + + public void setResourceId(int resourceId) { + this.resourceId = resourceId; + } + + public Button getPositiveBtn() { + return positiveBtn; + } + + public Button getNegativeBtn() { + return negativeBtn; + } + + public void setViewListener(int viewId, View.OnClickListener listener) { + mViewListener.put(viewId, listener); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyAlertDialogHelper.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyAlertDialogHelper.java new file mode 100644 index 0000000..94b8c7b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyAlertDialogHelper.java @@ -0,0 +1,126 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.app.Activity; +import android.content.Context; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; + +import com.netease.nim.uikit.R; + +public class EasyAlertDialogHelper { + public static void popClearMessageConfirmDialog(final Activity activity, final OnClearMessageListener listener, + String title) { + OnDialogActionListener actionListener = new OnDialogActionListener() { + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + listener.clearAllMessage(); + // activity.finish(); + } + }; + final EasyAlertDialog dialog = createOkCancelDiolag(activity, null, title, + activity.getString(R.string.clear_empty), null, true, actionListener); + dialog.show(); + } + + public interface OnClearMessageListener { + void clearAllMessage(); + } + + public static void showOneButtonDiolag(Context mContext, int titleResId, int msgResId, int btnResId, + boolean cancelable, final OnClickListener positiveListener) { + showOneButtonDiolag(mContext, getString(mContext, titleResId), getString(mContext, msgResId), + getString(mContext, btnResId), cancelable, positiveListener); + } + + public static void showOneButtonDiolag(Context mContext, CharSequence titleString, CharSequence msgString, + CharSequence btnString, boolean cancelable, final OnClickListener positiveListener) { + final EasyAlertDialog dialog = new EasyAlertDialog(mContext); + if (TextUtils.isEmpty(titleString)) { + dialog.setTitleVisible(false); + } else { + dialog.setTitle(titleString); + } + if (TextUtils.isEmpty(msgString)) { + dialog.setMessageVisible(false); + } else { + dialog.setMessage(msgString); + } + dialog.setCancelable(cancelable); + dialog.addPositiveButton(TextUtils.isEmpty(btnString) ? mContext.getString(R.string.iknow) : btnString, + EasyAlertDialog.NO_TEXT_COLOR, EasyAlertDialog.NO_TEXT_SIZE, new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + if (positiveListener != null) + positiveListener.onClick(v); + } + }); + dialog.show(); + } + + public static EasyAlertDialog createOkCancelDiolag(Context context, CharSequence title, CharSequence message, + boolean cancelable, final OnDialogActionListener listener) { + return createOkCancelDiolag(context, title, message, null, null, cancelable, listener); + } + + /** + * 两个按钮的dialog + * + * @param context + * @param title + * @param message + * @param okStr + * @param cancelStr + * @param cancelable + * @param listener + * @return + */ + public static EasyAlertDialog createOkCancelDiolag(Context context, CharSequence title, CharSequence message, + CharSequence okStr, CharSequence cancelStr, boolean cancelable, final OnDialogActionListener listener) { + final EasyAlertDialog dialog = new EasyAlertDialog(context); + OnClickListener okListener = new OnClickListener() { + public void onClick(View v) { + dialog.dismiss(); + listener.doOkAction(); + } + }; + OnClickListener cancelListener = new OnClickListener() { + public void onClick(View v) { + dialog.dismiss(); + listener.doCancelAction(); + } + }; + if (TextUtils.isEmpty(title)) { + dialog.setTitleVisible(false); + } else { + dialog.setTitle(title); + } + if (TextUtils.isEmpty(message)) { + dialog.setMessageVisible(false); + } else { + dialog.setMessage(message); + } + dialog.addPositiveButton(okStr, okListener); + dialog.addNegativeButton(cancelStr, cancelListener); + dialog.setCancelable(cancelable); + return dialog; + } + + public interface OnDialogActionListener { + void doCancelAction(); + + void doOkAction(); + } + + private static String getString(Context context, int id) { + if (id == 0) { + return null; + } + return context.getString(id); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyEditDialog.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyEditDialog.java new file mode 100644 index 0000000..c28d912 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyEditDialog.java @@ -0,0 +1,279 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager.LayoutParams; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +/** + * 简单的带有输入框的对话框 + *

+ * Created by huangjun on 2015/5/28.股灾 + */ +public class EasyEditDialog extends Dialog { + + private TextView mTitleTextView; + + private TextView mMessageTextView; + + private EditText mEdit; + + private TextView mLengthTextView; + + private Button mPositiveBtn; + + private Button mNegativeBtn; + + private int mResourceId; + + private View.OnClickListener mPositiveBtnListener; + + private View.OnClickListener mNegativeBtnListener; + + private String mTitle; + + private int mPositiveBtnStrResId = R.string.ok; + + private int mNegativeBtnStrResId = R.string.cancel; + + private String mMessage; + + private String mEditHint; + + private int mMaxEditTextLength; + + private int mMaxLines = 0; + + private boolean mSingleLine = false; + + private boolean mShowEditTextLength = false; + + private int inputType = -1; + + public EasyEditDialog(Context context, int resourceId, int style) { + super(context, style); + mMaxEditTextLength = 16; + if (-1 != resourceId) { + setContentView(resourceId); + this.mResourceId = resourceId; + } + LayoutParams Params = getWindow().getAttributes(); + Params.width = LayoutParams.MATCH_PARENT; + Params.height = LayoutParams.MATCH_PARENT; + getWindow().setAttributes(Params); + } + + public EasyEditDialog(Context context, int style) { + this(context, -1, style); + mResourceId = R.layout.nim_easy_alert_dialog_with_edit_text; + } + + public EasyEditDialog(Context context) { + this(context, R.style.sdk_share_dialog); + mResourceId = R.layout.nim_easy_alert_dialog_with_edit_text; + } + + public void setTitle(String title) { + if (null != title) { + this.mTitle = title; + if (null != mTitleTextView) + mTitleTextView.setText(title); + } + } + + public void setMessage(String message) { + if (null != message) { + this.mMessage = message; + if (null != mMessageTextView) + mMessageTextView.setText(message); + } + } + + public void setEditHint(String hint) { + if (!TextUtils.isEmpty(hint)) { + this.mEditHint = hint; + if (null != mEdit) { + mEdit.setHint(hint); + } + } + } + + public void setInputType(int type) { + this.inputType = type; + } + + public void setEditTextMaxLength(int maxLength) { + this.mMaxEditTextLength = maxLength; + this.mShowEditTextLength = true; + } + + public void setEditTextMaxLines(int maxLines) { + this.mMaxLines = maxLines; + } + + public void setEditTextSingleLine() { + this.mSingleLine = true; + } + + public void addPositiveButtonListener(View.OnClickListener positiveBtnListener) { + this.mPositiveBtnListener = positiveBtnListener; + } + + public void addPositiveButtonListener(int resId, View.OnClickListener positiveBtnListener) { + this.mPositiveBtnStrResId = resId; + this.mPositiveBtnListener = positiveBtnListener; + } + + public void addNegativeButtonListener(View.OnClickListener negativeBtnListener) { + this.mNegativeBtnListener = negativeBtnListener; + } + + public void addNegativeButtonListener(int resId, View.OnClickListener negativeBtnListener) { + this.mNegativeBtnStrResId = resId; + this.mNegativeBtnListener = negativeBtnListener; + } + + public int getResourceId() { + return mResourceId; + } + + public void setResourceId(int resourceId) { + this.mResourceId = resourceId; + } + + public Button getPositiveBtn() { + return mPositiveBtn; + } + + public Button getNegativeBtn() { + return mNegativeBtn; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(mResourceId); + + try { + LinearLayout root = (LinearLayout) findViewById(R.id.easy_edit_dialog_root); + ViewGroup.LayoutParams params = root.getLayoutParams(); + params.width = (int) ScreenUtil.getDialogWidth(); + root.setLayoutParams(params); + + if (mTitle != null) { + mTitleTextView = (TextView) findViewById(R.id.easy_dialog_title_text_view); + mTitleTextView.setText(mTitle); + } + + if (mMessage != null) { + mMessageTextView = (TextView) findViewById(R.id.easy_dialog_message_text_view); + mMessageTextView.setText(mMessage); + mMessageTextView.setVisibility(View.VISIBLE); + } + + mEdit = (EditText) findViewById(R.id.easy_alert_dialog_edit_text); + mLengthTextView = (TextView) findViewById(R.id.edit_text_length); + // mEdit.setFilters(new InputFilter[] { new InputFilter.LengthFilter(mMaxEditTextLength) }); + mLengthTextView.setVisibility(mShowEditTextLength ? View.VISIBLE : View.GONE); + if (inputType != -1) { + mEdit.setInputType(inputType); + } + mEdit.addTextChangedListener(new EditTextWatcher(mEdit, mLengthTextView, mMaxEditTextLength, + mShowEditTextLength)); + + if (!TextUtils.isEmpty(mEditHint)) { + mEdit.setHint(mEditHint); + } + if (mMaxLines > 0) { + mEdit.setMaxLines(mMaxLines); + } + if (mSingleLine) { + mEdit.setSingleLine(); + } + + mPositiveBtn = (Button) findViewById(R.id.easy_dialog_positive_btn); + if (mPositiveBtnStrResId != 0) { + mPositiveBtn.setText(mPositiveBtnStrResId); + } + mPositiveBtn.setOnClickListener(mPositiveBtnListener); + + mNegativeBtn = (Button) findViewById(R.id.easy_dialog_negative_btn); + if (mNegativeBtnStrResId != 0) { + mNegativeBtn.setText(mNegativeBtnStrResId); + } + mNegativeBtn.setOnClickListener(mNegativeBtnListener); + mNegativeBtn.setVisibility(View.VISIBLE); + findViewById(R.id.easy_dialog_btn_divide_view).setVisibility(View.VISIBLE); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getEditMessage() { + if (mEdit != null) + return mEdit.getEditableText().toString(); + else return null; + } + + public static class EditTextWatcher implements TextWatcher { + + private EditText editText; + + private TextView lengthTV; + + private int maxLength; + + private boolean show = false; + + public EditTextWatcher(EditText editText, TextView lengthTV, int maxLength, boolean show) { + this.maxLength = maxLength; + this.editText = editText; + this.lengthTV = lengthTV; + this.show = show; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (editText == null) + return; + int editStart = editText.getSelectionStart(); + int editEnd = editText.getSelectionEnd(); + editText.removeTextChangedListener(this); + while (StringUtil.counterChars(s.toString()) > maxLength) { + s.delete(editStart - 1, editEnd); + editStart--; + editEnd--; + } + editText.setSelection(editStart); + editText.addTextChangedListener(this); + if (show && lengthTV != null) { + long remainLength = maxLength - StringUtil.counterChars(s.toString()); + lengthTV.setText("" + remainLength / 2); + lengthTV.setVisibility(View.VISIBLE); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyProgressDialog.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyProgressDialog.java new file mode 100644 index 0000000..03e91bf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/EasyProgressDialog.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.view.WindowManager.LayoutParams; +import android.widget.TextView; + +import com.netease.nim.uikit.R; + +/** + * 一个半透明窗口,包含一个Progressbar 和 Message部分. 其中Message部分可选. 可单独使用,也可以使用 + * {@link DialogMaker} 进行相关窗口显示. + * + * @author Qijun + */ +public class EasyProgressDialog extends Dialog { + private Context mContext; + + private String mMessage; + + private int mLayoutId; + + private TextView message; + + public EasyProgressDialog(Context context, int style, int layout) { + super(context, style); + mContext = context; + LayoutParams Params = getWindow().getAttributes(); + Params.width = LayoutParams.FILL_PARENT; + Params.height = LayoutParams.FILL_PARENT; + getWindow().setAttributes(Params); + mLayoutId = layout; + } + + public EasyProgressDialog(Context context, int layout, String msg) { + this(context, R.style.easy_dialog_style, layout); + setMessage(msg); + } + + public EasyProgressDialog(Context context, String msg) { + this(context, R.style.easy_dialog_style, R.layout.nim_easy_progress_dialog); + setMessage(msg); + } + + public EasyProgressDialog(Context context) { + this(context, R.style.easy_dialog_style, R.layout.nim_easy_progress_dialog); + } + + public void setMessage(String msg) { + mMessage = msg; + } + + public void updateLoadingMessage(String msg) { + mMessage = msg; + showMessage(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(mLayoutId); + message = (TextView) findViewById(R.id.easy_progress_dialog_message); + showMessage(); + } + + private void showMessage() { + if (message != null && !TextUtils.isEmpty(mMessage)) { + message.setVisibility(View.VISIBLE); + message.setText(mMessage); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/MenuDialog.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/MenuDialog.java new file mode 100644 index 0000000..59573b7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/dialog/MenuDialog.java @@ -0,0 +1,127 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by huangjun on 2015/3/21. + */ +public class MenuDialog extends Dialog implements View.OnClickListener { + public interface MenuDialogOnButtonClickListener { + public void onButtonClick(final String name); + } + + private Context context; + private ViewGroup rootView; + private LinearLayout itemsRootView; + + private List btnNames; + private List itemViews; + private MenuDialogOnButtonClickListener clickListener; + private boolean selectMode = false; + private int selectIndex = -1; // 要勾选的项 + private int invalidSelectIndex = -1; // 不能勾选的项目 + private int preSelectIndex = -1; // 之前勾选的项目 + + public MenuDialog(Context context, List btnNames, MenuDialogOnButtonClickListener listener) { + super(context, R.style.dialog_default_style); + this.context = context; + this.btnNames = btnNames; + this.clickListener = listener; + } + + public MenuDialog(Context context, List btnNames, int selectIndex, int invalidSelectIndex, + MenuDialogOnButtonClickListener listener) { + this(context, btnNames, listener); + + if (selectIndex >= 0 && selectIndex < btnNames.size()) { + this.selectMode = true; + this.selectIndex = selectIndex; + this.preSelectIndex = selectIndex; + this.invalidSelectIndex = invalidSelectIndex; + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + + rootView = (ViewGroup) View.inflate(context, R.layout.nim_menu_dialog, null); + itemsRootView = (LinearLayout) rootView.findViewById(R.id.menu_dialog_items_root); + if (selectMode) { + itemViews = new ArrayList<>(); + } + + View itemView; + for (int i = 0; i < btnNames.size(); i++) { + itemView = View.inflate(context, R.layout.nim_menu_dialog_item, null); + ((TextView) itemView.findViewById(R.id.menu_button)).setText(btnNames.get(i)); + itemView.setTag(i); + itemView.setOnClickListener(this); + if (selectMode) { + itemViews.add(itemView); + } + + itemsRootView.addView(itemView); + } + + selectItem(); + + rootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + setContentView(rootView); + } + + // 撤销最后一次选择,恢复上一次选择 + public void undoLastSelect() { + if (selectMode && preSelectIndex >= 0 && preSelectIndex < btnNames.size()) { + selectIndex = preSelectIndex; + selectItem(); + } + } + + private void selectItem() { + if (selectMode == false || selectIndex < 0 || selectIndex >= btnNames.size() || itemViews == null || itemViews + .isEmpty()) { + return; + } + + View item; + for (int i = 0; i < itemViews.size(); i++) { + item = itemViews.get(i); + item.findViewById(R.id.menu_select_icon).setVisibility(selectIndex == i ? View.VISIBLE : View.GONE); + } + } + + @Override + public void onClick(View v) { + int index = (int) v.getTag(); + if (selectMode && index != invalidSelectIndex) { + preSelectIndex = selectIndex; + selectIndex = index; + selectItem(); + } + + String btnName = btnNames.get(index); + if (clickListener != null) { + clickListener.onButtonClick(btnName); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropCover.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropCover.java new file mode 100644 index 0000000..f15a85a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropCover.java @@ -0,0 +1,363 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.drop; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.CycleInterpolator; +import android.view.animation.TranslateAnimation; + +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * 悬浮在屏幕上的红点拖拽动画绘制区域 + *

+ * Created by huangjun on 2016/9/13. + */ +public class DropCover extends View { + + public interface IDropCompletedListener { + void onCompleted(Object id, boolean explosive); + } + + private final float MAX_RATIO = 0.8f; // 固定圆最大的缩放比例 + private final float MIN_RATIO = 0.4f; // 固定圆最小的缩放比例 + private final int DISTANCE_LIMIT = ScreenUtil.dip2px(70); // 固定圆和移动圆的圆心之间的断裂距离 + private static final int SHAKE_ANIM_DURATION = 150; // 抖动动画执行的时间 + private static final int EXPLOSION_ANIM_FRAME_INTERVAL = 50; // 爆裂动画帧之间的间隔 + private static final int CLICK_DISTANCE_LIMIT = ScreenUtil.dip2px(15); // 不超过此距离视为点击 + private static final int CLICK_DELTA_TIME_LIMIT = 10; // 超过此时长需要爆裂 + + private View dropFake; + private Path path = new Path(); + private int radius; // 移动圆形半径 + private float curX; // 当前手指x坐标 + private float curY; // 当前手指y坐标 + private float circleX; // 固定圆的圆心x坐标 + private float circleY; // 固定圆的圆心y坐标 + private float ratio = 1; // 圆缩放的比例,随着手指的移动,固定的圆越来越小 + private boolean needDraw = true; // 是否需要执行onDraw方法 + private boolean hasBroken = false; // 是否已经断裂过,断裂过就不需要再画Path了 + private boolean isDistanceOverLimit = false; // 当前移动圆和固定圆的距离是否超过限值 + private boolean click = true; // 是否在点击的距离限制范围内,超过了clickDistance则不属于点击 + private long clickTime; // 记录down的时间点 + private String text; // 显示的数字 + + private Bitmap[] explosionAnim; // 爆裂动画位图 + private boolean explosionAnimStart; // 爆裂动画是否开始 + private int explosionAnimNumber; // 爆裂动画帧的个数 + private int curExplosionAnimIndex; // 爆裂动画当前帧 + private int explosionAnimWidth; // 爆裂动画帧的宽度 + private int explosionAnimHeight; // 爆裂动画帧的高度 + private List dropCompletedListeners; // 拖拽动作完成,回调 + + /** + * ************************* 绘制 ************************* + */ + public DropCover(Context context, AttributeSet attrs) { + super(context, attrs); + + DropManager.getInstance().initPaint(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // 绘制两个圆/Path/文本 + if (needDraw) { + drawCore(canvas); + } + + // 爆裂动画 + if (explosionAnimStart) { + drawExplosionAnimation(canvas); + } + } + + private void drawCore(Canvas canvas) { + if (!needDraw) { + return; + } + + final Paint circlePaint = DropManager.getInstance().getCirclePaint(); + // 画固定圆(如果已经断裂过了,就不需要画固定圆了) + if (!hasBroken && !isDistanceOverLimit) { + canvas.drawCircle(circleX, circleY, radius * ratio, circlePaint); + } + + // 画移动圆和连线(如果已经断裂过了,就不需要再画Path了) + if (curX != 0 && curY != 0) { + canvas.drawCircle(curX, curY, radius, circlePaint); + if (!hasBroken && !isDistanceOverLimit) { + drawPath(canvas); + } + } + + // 数字要最后画,否则会被连线遮掩 + if (!TextUtils.isEmpty(text)) { + final float textMove = DropManager.getInstance().getTextYOffset(); + final TextPaint textPaint = DropManager.getInstance().getTextPaint(); + if (curX != 0 && curY != 0) { + // 移动圆里面的数字 + canvas.drawText(text, curX, curY + textMove, textPaint); + } else { + // 只有初始时需要绘制固定圆里面的数字 + canvas.drawText(text, circleX, circleY + textMove, textPaint); + } + } + } + + /** + * 画固定圆和移动圆之间的连线 + */ + private void drawPath(Canvas canvas) { + path.reset(); + + float distance = (float) distance(circleX, circleY, curX, curY); // 移动圆和固定圆圆心之间的距离 + float sina = (curY - circleY) / distance; // 移动圆圆心和固定圆圆心之间的连线与X轴相交形成的角度的sin值 + float cosa = (circleX - curX) / distance; // 移动圆圆心和固定圆圆心之间的连线与X轴相交形成的角度的cos值 + + float AX = circleX - sina * radius * ratio; + float AY = circleY - cosa * radius * ratio; + float BX = circleX + sina * radius * ratio; + float BY = circleY + cosa * radius * ratio; + float OX = (circleX + curX) / 2; + float OY = (circleY + curY) / 2; + float CX = curX + sina * radius; + float CY = curY + cosa * radius; + float DX = curX - sina * radius; + float DY = curY - cosa * radius; + path.moveTo(AX, AY); // A点坐标 + path.lineTo(BX, BY); // AB连线 + path.quadTo(OX, OY, CX, CY); // 控制点为两个圆心的中间点,贝塞尔曲线,BC连线 + path.lineTo(DX, DY); // CD连线 + path.quadTo(OX, OY, AX, AY); // 控制点也是两个圆心的中间点,贝塞尔曲线,DA连线 + + canvas.drawPath(path, DropManager.getInstance().getCirclePaint()); + } + + /** + * ************************* TouchListener回调 ************************* + */ + public void down(View fakeView, String text) { + this.needDraw = true; // 由于DropCover是公用的,每次进来时都要确保needDraw的值为true + this.hasBroken = false; // 未断裂 + this.isDistanceOverLimit = false; // 当前移动圆和固定圆的距离是否超过限值 + this.click = true; // 点击开始 + + this.dropFake = fakeView; + int[] position = new int[2]; + dropFake.getLocationOnScreen(position); + + this.radius = DropManager.CIRCLE_RADIUS; + // 固定圆圆心坐标,固定圆圆心坐标y,需要减去系统状态栏高度 + this.circleX = position[0] + dropFake.getWidth() / 2; + this.circleY = position[1] - DropManager.getInstance().getTop() + dropFake.getHeight() / 2; + // 移动圆圆心坐标 + this.curX = this.circleX; + this.curY = this.circleY; + + this.text = text; + this.clickTime = System.currentTimeMillis(); + + // hide fake view, show current + dropFake.setVisibility(View.INVISIBLE); // 隐藏固定范围的DropFake + this.setVisibility(View.VISIBLE); // 当前全屏范围的DropCover可见 + + invalidate(); + } + + public void move(float curX, float curY) { + curY -= DropManager.getInstance().getTop(); // 位置校准,去掉通知栏高度 + + this.curX = curX; + this.curY = curY; + + calculateRatio((float) distance(curX, curY, circleX, circleY)); // 计算固定圆缩放的比例 + + invalidate(); + } + + /** + * 计算固定圆缩放的比例 + */ + private void calculateRatio(float distance) { + if (isDistanceOverLimit = distance > DISTANCE_LIMIT) { + hasBroken = true; // 已经断裂过了 + } + + // 固定圆缩放比例0.4-0.8之间 + ratio = MIN_RATIO + (MAX_RATIO - MIN_RATIO) * (1.0f * Math.max(DISTANCE_LIMIT - distance, 0)) / DISTANCE_LIMIT; + } + + public void up() { + boolean longClick = click && (System.currentTimeMillis() - this.clickTime > CLICK_DELTA_TIME_LIMIT); // 长按 + + // 没有超出最大移动距离&&不是长按点击事件,UP时需要让移动圆回到固定圆的位置 + if (!isDistanceOverLimit && !longClick) { + if (hasBroken) { + // 如果已经断裂,那么直接回原点,显示FakeView + onDropCompleted(false); + } else { + // 如果还未断裂,那么执行抖动动画 + shakeAnimation(); + } + // reset + curX = 0; + curY = 0; + ratio = 1; + } else { + // 超出最大移动距离,那么执行爆裂帧动画 + initExplosionAnimation(); + + needDraw = false; + explosionAnimStart = true; + } + + invalidate(); + } + + public double distance(float x1, float y1, float x2, float y2) { + double distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + if (distance > CLICK_DISTANCE_LIMIT) { + click = false; // 已经不是点击了 + } + + return distance; + } + + /** + * ************************* 爆炸动画(帧动画) ************************* + */ + private void initExplosionAnimation() { + if (explosionAnim == null) { + int[] explosionResIds = DropManager.getInstance().getExplosionResIds(); + explosionAnimNumber = explosionResIds.length; + explosionAnim = new Bitmap[explosionAnimNumber]; + for (int i = 0; i < explosionAnimNumber; i++) { + explosionAnim[i] = BitmapFactory.decodeResource(getResources(), explosionResIds[i]); + } + + explosionAnimHeight = explosionAnimWidth = explosionAnim[0].getWidth(); // 每帧长宽都一致 + } + } + + private void drawExplosionAnimation(Canvas canvas) { + if (!explosionAnimStart) { + return; + } + + if (curExplosionAnimIndex < explosionAnimNumber) { + canvas.drawBitmap(explosionAnim[curExplosionAnimIndex], + curX - explosionAnimWidth / 2, curY - explosionAnimHeight / 2, null); + curExplosionAnimIndex++; + // 每隔固定时间执行 + postInvalidateDelayed(EXPLOSION_ANIM_FRAME_INTERVAL); + } else { + // 动画结束 + explosionAnimStart = false; + curExplosionAnimIndex = 0; + curX = 0; + curY = 0; + onDropCompleted(true); // explosive true + } + } + + private void recycleBitmap() { + if (explosionAnim != null && explosionAnim.length != 0) { + for (int i = 0; i < explosionAnim.length; i++) { + if (explosionAnim[i] != null && !explosionAnim[i].isRecycled()) { + explosionAnim[i].recycle(); + explosionAnim[i] = null; + } + } + + explosionAnim = null; + } + } + + /** + * ************************* 抖动动画(View平移动画) ************************* + */ + public void shakeAnimation() { + // 避免动画抖动的频率过大,所以除以10,另外,抖动的方向跟手指滑动的方向要相反 + Animation translateAnimation = new TranslateAnimation((circleX - curX) / 10, 0, (circleY - curY) / 10, 0); + translateAnimation.setInterpolator(new CycleInterpolator(1)); + translateAnimation.setDuration(SHAKE_ANIM_DURATION); + startAnimation(translateAnimation); + + translateAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + // 抖动动画结束时,show Fake, hide current + onDropCompleted(false); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + } + + /** + * ************************* 拖拽动作结束事件 ************************* + */ + public void addDropCompletedListener(IDropCompletedListener listener) { + if (listener == null) { + return; + } + + if (dropCompletedListeners == null) { + dropCompletedListeners = new ArrayList<>(1); + } + + dropCompletedListeners.add(listener); + } + + public void removeDropCompletedListener(IDropCompletedListener listener) { + if (listener == null || dropCompletedListeners == null) { + return; + } + + dropCompletedListeners.remove(listener); + } + + public void removeAllDropCompletedListeners() { + if (dropCompletedListeners == null) { + return; + } + + dropCompletedListeners.clear(); + } + + private void onDropCompleted(boolean explosive) { + dropFake.setVisibility(explosive ? View.INVISIBLE : View.VISIBLE); // show or hide fake view + this.setVisibility(View.INVISIBLE); // hide current + recycleBitmap(); // recycle + + // notify observer + if (dropCompletedListeners != null) { + for (IDropCompletedListener listener : dropCompletedListeners) { + listener.onCompleted(DropManager.getInstance().getCurrentId(), explosive); + } + } + + // free + DropManager.getInstance().setTouchable(true); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropFake.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropFake.java new file mode 100644 index 0000000..eda7cc3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropFake.java @@ -0,0 +1,154 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.drop; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Shader; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.GridView; +import android.widget.ListView; +import android.widget.ScrollView; + +import androidx.recyclerview.widget.RecyclerView; + +/** + * 未读数红点View(自绘红色的圆和数字) + * 触摸之产生DOWN/MOVE/UP事件(不允许父容器处理TouchEvent),回调给浮在上层的DropCover进行拖拽过程绘制。 + * View启动过程:Constructors -> onAttachedToWindow -> onMeasure() -> onSizeChanged() -> onLayout() -> onDraw() + *

+ * Created by huangjun on 2016/9/13. + */ +public class DropFake extends View { + + /** + * 未读数红点检测触摸事件产生DOWN/MOVE/UP + */ + public interface ITouchListener { + void onDown(); + + void onMove(float curX, float curY); + + void onUp(); + } + + private int radius; // 圆形半径 + private float circleX; // 圆心x坐标 + private float circleY; // 圆心y坐标 + private String text; // 要显示的文本(数字) + private boolean firstInit = true; // params init once + private ITouchListener touchListener; + + public DropFake(Context context, AttributeSet attrs) { + super(context, attrs); + + DropManager.getInstance().initPaint(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (firstInit) { + firstInit = false; + radius = DropManager.CIRCLE_RADIUS; // 或者view.getWidth()/2 + circleX = w / 2; + circleY = h / 2; + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // circle + int[] mColors = {0xFFE69EFF, 0xFF925BF7}; + Paint circlePaint = DropManager.getInstance().getCirclePaint(); + circlePaint.setShader(new LinearGradient(0, 0, circleX + radius, circleY + radius, mColors, null, Shader.TileMode.CLAMP)); + canvas.drawCircle(circleX, circleY, radius, circlePaint); + // text + if (!TextUtils.isEmpty(text)) { + canvas.drawText(text, circleX, circleY + DropManager.getInstance().getTextYOffset(), + DropManager.getInstance().getTextPaint()); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + // 如果未初始化 DropManager,则默认任何事件都不处理 + if (!DropManager.getInstance().isEnable()) { + return super.onTouchEvent(event); + } + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (DropManager.getInstance().isTouchable()) { + if (touchListener != null) { + DropManager.getInstance().setTouchable(false); + // 不允许父控件处理TouchEvent,当父控件为ListView这种本身可滑动的控件时必须要控制 + disallowInterceptTouchEvent(true); + touchListener.onDown(); + } + return true; // eat + } + + return false; + case MotionEvent.ACTION_MOVE: + if (touchListener != null) { + // getRaw:获取手指当前所处的相对整个屏幕的坐标 + touchListener.onMove(event.getRawX(), event.getRawY()); + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (touchListener != null) { + // 将控制权还给父控件 + disallowInterceptTouchEvent(false); + touchListener.onUp(); + } + break; + default: + break; + } + return super.onTouchEvent(event); + } + + public void setText(String text) { + this.text = text; + invalidate(); + } + + public String getText() { + return text; + } + + public void setTouchListener(ITouchListener listener) { + touchListener = listener; + } + + private void disallowInterceptTouchEvent(boolean disable) { + ViewGroup parent = (ViewGroup) getParent(); + parent.requestDisallowInterceptTouchEvent(disable); + + while (true) { + if (parent == null) { + return; + } + + if (parent instanceof RecyclerView || parent instanceof ListView || parent instanceof GridView || + parent instanceof ScrollView) { + parent.requestDisallowInterceptTouchEvent(disable); + return; + } + + ViewParent vp = parent.getParent(); + if (vp instanceof ViewGroup) { + parent = (ViewGroup) parent.getParent(); + } else { + return; // DecorView + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropManager.java new file mode 100644 index 0000000..f50d5b6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/drop/DropManager.java @@ -0,0 +1,215 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.drop; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.Paint; +import android.text.TextPaint; +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +/** + * Created by huangjun on 2016/9/13. + */ +public class DropManager { + + // constant + private static final String TAG = "DropManager"; + + static final int TEXT_SIZE = ScreenUtil.sp2px(12); // 12sp + + static final int CIRCLE_RADIUS = ScreenUtil.dip2px(10); // 10dip + + public interface IDropListener { + void onDropBegin(); + + void onDropEnd(); + } + + // single instance + private static DropManager instance; + + public static synchronized DropManager getInstance() { + if (instance == null) { + instance = new DropManager(); + } + + return instance; + } + + // field + private boolean isTouchable; // 是否响应按键事件,如果一个红点已经在响应,其它红点就不响应,同一界面始终最多只有一个红点响应触摸 + + private int statusBarHeight; // 状态栏(通知栏)高度 + + private DropCover dropCover; // Drop全屏动画 + + private Object currentId; // 当前正在执行动画的业务节点 + + private TextPaint textPaint; // 文本画笔共享 + + private float textYOffset; // 文本y轴居中需要的offset + + private Paint circlePaint; // 圆形画笔共享 + + private IDropListener innerListener; // 红点拖拽动画监听器 + + private boolean enable; + private int[] explosionResIds = new int[]{ + R.drawable.nim_explosion_one, + R.drawable.nim_explosion_two, + R.drawable.nim_explosion_three, + R.drawable.nim_explosion_four, + R.drawable.nim_explosion_five + }; + + // interface + public void init(Context context, DropCover dropCover, DropCover.IDropCompletedListener listener) { + this.isTouchable = true; + this.statusBarHeight = ScreenUtil.getStatusBarHeight(context); + this.dropCover = dropCover; + this.dropCover.addDropCompletedListener(listener); + this.innerListener = null; + this.enable = true; + + LogUtil.i(TAG, "init DropManager, statusBarHeight=" + statusBarHeight); + } + + public void initPaint() { + getCirclePaint(); + getTextPaint(); + } + + public void destroy() { + this.isTouchable = false; + this.statusBarHeight = 0; + if (this.dropCover != null) { + this.dropCover.removeAllDropCompletedListeners(); + this.dropCover = null; + } + this.currentId = null; + this.textPaint = null; + this.textYOffset = 0; + this.circlePaint = null; + this.enable = false; + LogUtil.i(TAG, "destroy DropManager"); + } + + public boolean isEnable() { + return enable; + } + + public boolean isTouchable() { + if (!enable) { + return true; + } + return isTouchable; + } + + public void setTouchable(boolean isTouchable) { + this.isTouchable = isTouchable; + if (innerListener == null) { + return; + } + + if (!isTouchable) { + innerListener.onDropBegin(); // touchable = false + } else { + innerListener.onDropEnd(); // touchable = true + } + + } + + public int getTop() { + return statusBarHeight; + } + + public void down(View fakeView, String text) { + if (dropCover == null) { + return; + } + + dropCover.down(fakeView, text); + } + + public void move(float curX, float curY) { + if (dropCover == null) { + return; + } + + dropCover.move(curX, curY); + } + + public void up() { + if (dropCover == null) { + return; + } + + dropCover.up(); + } + + public void addDropCompletedListener(DropCover.IDropCompletedListener listener) { + if (dropCover != null) { + dropCover.addDropCompletedListener(listener); + } + } + + public void removeDropCompletedListener(DropCover.IDropCompletedListener listener) { + if (dropCover != null) { + dropCover.removeDropCompletedListener(listener); + } + } + + public void setCurrentId(Object currentId) { + this.currentId = currentId; + } + + public Object getCurrentId() { + return currentId; + } + + public Paint getCirclePaint() { + if (circlePaint == null) { + circlePaint = new Paint(); + circlePaint.setColor(Color.RED); + circlePaint.setAntiAlias(true); + } + + return circlePaint; + } + + public TextPaint getTextPaint() { + if (textPaint == null) { + textPaint = new TextPaint(); + textPaint.setAntiAlias(true); + textPaint.setColor(Color.WHITE); + textPaint.setTextAlign(Paint.Align.CENTER); + textPaint.setTextSize(TEXT_SIZE); + Paint.FontMetrics textFontMetrics = textPaint.getFontMetrics(); + + /* + * drawText从baseline开始,baseline的值为0,baseline的上面为负值,baseline的下面为正值, + * 即这里ascent为负值,descent为正值。 + * 比如ascent为-20,descent为5,那需要移动的距离就是20 - (20 + 5)/ 2 + */ + textYOffset = -textFontMetrics.ascent - (-textFontMetrics.ascent + textFontMetrics.descent) / 2; + } + + return textPaint; + } + + public float getTextYOffset() { + getTextPaint(); + return textYOffset; + } + + public int[] getExplosionResIds() { + return explosionResIds; + } + + public void setDropListener(IDropListener listener) { + this.innerListener = listener; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/BaseZoomableImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/BaseZoomableImageView.java new file mode 100644 index 0000000..cb05b2d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/BaseZoomableImageView.java @@ -0,0 +1,718 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +/* + * Copyright 2012 Laurence Dawson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This class is based upon the file ImageViewTouchBase.java which can be found at: + * https://dl-ssl.google.com/dl/googlesource/git-repo/repo + * + * Copyright (C) 2009 The Android Open Source Project + */ + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Build; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.TranslateAnimation; + +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.im.uikit.common.util.media.SampleSizeUtil; + +public abstract class BaseZoomableImageView extends View { + // Statics + static final float sPanRate = 7; + static final float sScaleRate = 1.25F; + static final int sPaintDelay = 250; + static final int sAnimationDelay = 500; + public static final int MIN_SDK_ENABLE_LAYER_TYPE_HARDWARE = Build.VERSION_CODES.ICE_CREAM_SANDWICH; + + // 横屏时特殊处理,但高大于宽的2倍时,就以宽充满 + private static final float MAX_IMAGE_RATIO_WIDTH_LARGE_LANDSCAPE = 2F; + + private static final float MAX_IMAGE_RATIO_LARGE = 5F; + + // This is the base transformation which is used to show the image + // initially. The current computation for this shows the image in + // it's entirety, letterboxing as needed. One could chose to + // show the image as cropped instead. + // + // This matrix is recomputed when we go from the thumbnail image to + // the full size image. + private Matrix mBaseMatrix = new Matrix(); + + // This is the supplementary transformation which reflects what + // the user has done in terms of zooming and panning. + // + // This matrix remains the same when we go from the thumbnail image + // to the full size image. + private Matrix mSuppMatrix = new Matrix(); + + // This is the final matrix which is computed as the concatentation + // of the base matrix and the supplementary matrix. + private Matrix mDisplayMatrix = new Matrix(); + + // A replacement ImageView matrix + private Matrix mMatrix = new Matrix(); + + // Used to filter the bitmaps when hardware acceleration is not enabled + private Paint mPaint; + + // Temporary buffer used for getting the values out of a matrix. + private float[] mMatrixValues = new float[9]; + + // Dimensions for the view + private int mThisWidth = -1, mThisHeight = -1; + + // The max zoom for the view, determined programatically + private float mMaxZoom; + + // If not null, calls setImageBitmap when onLayout is triggered + private Runnable mOnLayoutRunnable = null; + + // Stacked to the internal queue to invalidate the view + private Runnable mRefresh = null; + + // The time of the last draw operation + private double mLastDraw = 0; + + // The current bitmap being displayed. + protected Bitmap mBitmap; + + // Stacked to the internal queue to scroll the view + private Runnable mFling = null; + private boolean fling = false; + + // Single tap listener + protected ImageGestureListener mImageGestureListener; + + protected ViewPager mViewPager; + + private boolean landscape = false; + + // Programatic entry point + public BaseZoomableImageView(Context context) { + super(context); + initBaseZoomableImageView(context); + } + + // XML entry point + public BaseZoomableImageView(Context context, AttributeSet attrs) { + super(context, attrs); + initBaseZoomableImageView(context); + } + + // Setup the view + @SuppressLint("NewApi") + protected void initBaseZoomableImageView(Context context) { + mPaint = new Paint(); + mPaint.setDither(true); + mPaint.setFilterBitmap(true); + mPaint.setAntiAlias(true); + if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + landscape = true; + } else { + landscape = false; + } + // Setup the refresh runnable + mRefresh = new Runnable() { + @Override + public void run() { + postInvalidate(); + } + }; + } + + // Set the single tap listener + public void setImageGestureListener(ImageGestureListener listener) { + this.mImageGestureListener = listener; + } + + public void setViewPager(ViewPager viewPager) { + this.mViewPager = viewPager; + } + + // Get the bitmap for the view + public Bitmap getImageBitmap() { + return mBitmap; + } + + // Free the bitmaps and matrices + public void clear() { + if (mBitmap != null && !mBitmap.isRecycled()) { + mBitmap.recycle(); + } + mBitmap = null; + } + + // When the layout is calculated, set the + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + mThisWidth = right - left; + mThisHeight = bottom - top; + Runnable r = mOnLayoutRunnable; + if (r != null) { + mOnLayoutRunnable = null; + r.run(); + } + // if (mBitmap != null) { + // setBaseMatrix(mBitmap, mBaseMatrix); + // setImageMatrix(getImageViewMatrix()); + // } + } + + // Translate a given point through a given matrix. + static protected void translatePoint(Matrix matrix, float[] xy) { + matrix.mapPoints(xy); + } + + // Identical to the setImageMatrix method in ImageView + public void setImageMatrix(Matrix m) { + if (m != null && m.isIdentity()) { + m = null; + } + + // don't invalidate unless we're actually changing our matrix + if (m == null && !this.mMatrix.isIdentity() || m != null && !this.mMatrix.equals(m)) { + this.mMatrix.set(m); + invalidate(); + } + } + + // Sets the bitmap for the image and resets the base + public void setImageBitmap(final Bitmap bitmap) { + setImageBitmap(bitmap, true); + } + + // Sets the bitmap for the image and resets the base + @SuppressLint("NewApi") + public void setImageBitmap(final Bitmap bitmap, final boolean fitScreen) { + + //版本过低或者长度大于最大纹理限制,不采用硬件加速 + if (Build.VERSION.SDK_INT >= MIN_SDK_ENABLE_LAYER_TYPE_HARDWARE) { + if (bitmap != null && (bitmap.getHeight() > SampleSizeUtil.getTextureSize() + || bitmap.getWidth() > SampleSizeUtil.getTextureSize())) { + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } else { + setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + } + + final int viewWidth = getWidth(); + if (viewWidth <= 0) { + mOnLayoutRunnable = new Runnable() { + public void run() { + setImageBitmap(bitmap, fitScreen); + } + }; + return; + } + + Bitmap oldBitmap = this.mBitmap; + if (bitmap != null) { + setBaseMatrix(bitmap, mBaseMatrix); + this.mBitmap = bitmap; + } else { + mBaseMatrix.reset(); + this.mBitmap = bitmap; + } + if (oldBitmap != null && oldBitmap != mBitmap && !oldBitmap.isRecycled()) { + oldBitmap.recycle(); + } + + mSuppMatrix.reset(); + setImageMatrix(getImageViewMatrix()); + mMaxZoom = maxZoom(); + + // Set the image to fit the screen + if (fitScreen) { + zoomToScreen(); + } + } + + /** + * Sets the bitmap for the image and resets the base + * + * @param bitmap + * @param selection + * @date 2014-4-29 + */ + public void setImageBitmap(final Bitmap bitmap, final Rect selection) { + final int viewWidth = getWidth(); + + + if (viewWidth <= 0) { + mOnLayoutRunnable = new Runnable() { + public void run() { + setImageBitmap(bitmap, updateSelection()); + } + }; + return; + } + + Bitmap oldBitmap = this.mBitmap; + if (bitmap != null) { + setBaseMatrix(bitmap, mBaseMatrix, selection); + this.mBitmap = bitmap; + } else { + mBaseMatrix.reset(); + this.mBitmap = bitmap; + } + if (oldBitmap != null && !oldBitmap.isRecycled()) { + oldBitmap.recycle(); + } + + mSuppMatrix.reset(); + setImageMatrix(getImageViewMatrix()); + mMaxZoom = maxZoom(); + + + } + + + // Unchanged from ImageViewTouchBase + // Center as much as possible in one or both axis. Centering is + // defined as follows: if the image is scaled down below the + // view's dimensions then center it (literally). If the image + // is scaled larger than the view and is translated out of view + // then translate it back into view (i.e. eliminate black bars). + protected void center(boolean vertical, boolean horizontal, boolean animate) { + if (mBitmap == null) + return; + + Matrix m = getImageViewMatrix(); + + float[] topLeft = new float[]{0, 0}; + float[] botRight = new float[]{mBitmap.getWidth(), mBitmap.getHeight()}; + + translatePoint(m, topLeft); + translatePoint(m, botRight); + + float height = botRight[1] - topLeft[1]; + float width = botRight[0] - topLeft[0]; + + float deltaX = 0, deltaY = 0; + + if (vertical) { + int viewHeight = getHeight(); + if (height < viewHeight) { + deltaY = (viewHeight - height) / 2 - topLeft[1]; + } else if (topLeft[1] > 0) { + deltaY = -topLeft[1]; + } else if (botRight[1] < viewHeight) { + deltaY = getHeight() - botRight[1]; + } + } + + if (horizontal) { + int viewWidth = getWidth(); + if (width < viewWidth) { + deltaX = (viewWidth - width) / 2 - topLeft[0]; + } else if (topLeft[0] > 0) { + deltaX = -topLeft[0]; + } else if (botRight[0] < viewWidth) { + deltaX = viewWidth - botRight[0]; + } + } + + postTranslate(deltaX, deltaY); + if (animate) { + Animation a = new TranslateAnimation(-deltaX, 0, -deltaY, 0); + a.setStartTime(SystemClock.elapsedRealtime()); + a.setDuration(250); + setAnimation(a); + } + setImageMatrix(getImageViewMatrix()); + } + + // Unchanged from ImageViewTouchBase + protected float getValue(Matrix matrix, int whichValue) { + matrix.getValues(mMatrixValues); + return mMatrixValues[whichValue]; + } + + // Get the scale factor out of the matrix. + protected float getScale(Matrix matrix) { + + // If the bitmap is set return the scale + if (mBitmap != null) + return getValue(matrix, Matrix.MSCALE_X); + // Otherwise return the default value of 1 + else + return 1f; + } + + // Returns the current scale of the view + public float getScale() { + return getScale(mSuppMatrix); + } + + // Setup the base matrix so that the image is centered and scaled properly. + private void setBaseMatrix(Bitmap bitmap, Matrix matrix) { + float viewWidth = getWidth(); + float viewHeight = getHeight(); + + matrix.reset(); + float widthScale = Math.min(viewWidth / (float) bitmap.getWidth(), 1.0f); + float heightScale = Math.min(viewHeight / (float) bitmap.getHeight(), 1.0f); + float scale; + if (widthScale > heightScale) { + scale = heightScale; + } else { + scale = widthScale; + } + matrix.setScale(scale, scale); + matrix.postTranslate( + (viewWidth - ((float) bitmap.getWidth() * scale)) / 2F, + (viewHeight - ((float) bitmap.getHeight() * scale)) / 2F); + } + + + /** + * Setup the base matrix so that the image is centered and scaled properly. + * 根据Bitmap和Rect,设置初始的显示矩阵Matrix + * + * @param bitmap + * @param matrix + * @param selection + * @author Linleja + * @date 2014-4-29 + */ + private void setBaseMatrix(Bitmap bitmap, Matrix matrix, Rect selection) { + if (selection == null) { + return; + } + + float viewWidth = selection.right - selection.left; + float viewHeight = selection.bottom - selection.top; + + matrix.reset(); + + + float widthRatio = viewWidth / (float) bitmap.getWidth(); + float heighRatio = viewHeight / (float) bitmap.getHeight(); + float scale = 1.0f; + if (widthRatio > heighRatio) { + scale = widthRatio; + + + } else { + scale = heighRatio; + + + } + + matrix.setScale(scale, scale); + matrix.postTranslate( + ((getWidth() - (float) bitmap.getWidth() * scale)) / 2F, + ((getHeight() - (float) bitmap.getHeight() * scale)) / 2F); + } + + + // Combine the base matrix and the supp matrix to make the final matrix. + protected Matrix getImageViewMatrix() { + mDisplayMatrix.set(mBaseMatrix); + mDisplayMatrix.postConcat(mSuppMatrix); + return mDisplayMatrix; + } + + // Sets the maximum zoom, which is a scale relative to the base matrix. It is calculated to show + // the image at 400% zoom regardless of screen or image orientation. If in the future we decode + // the full 3 megapixel image, rather than the current 1024x768, this should be changed down to + // 200%. + protected float maxZoom() { + if (mBitmap == null) + return 1F; + + float fw = (float) mBitmap.getWidth() / (float) mThisWidth; + float fh = (float) mBitmap.getHeight() / (float) mThisHeight; + float max = Math.max(fw, fh) * 16; + + + //设置放大的下限 + if (max < 1F) { + max = 1F; + } + + + return max; + } + + // Tries to make best use of the space by zooming the picture + public float zoomDefault() { + if (mBitmap == null) + return 1F; + + float fw = (float) mThisWidth / (float) mBitmap.getWidth(); + float fh = (float) mThisHeight / (float) mBitmap.getHeight(); + return Math.max(Math.min(fw, fh), 1); + } + + // Unchanged from ImageViewTouchBase + protected void zoomTo(float scale, float centerX, float centerY) { + if (scale > mMaxZoom) { + scale = mMaxZoom; + } + + float oldScale = getScale(); + float deltaScale = scale / oldScale; + + mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY); + setImageMatrix(getImageViewMatrix()); + center(true, true, false); + } + + // Unchanged from ImageViewTouchBase + protected void zoomTo(final float scale, final float centerX, final float centerY, final float durationMs) { + final float incrementPerMs = (scale - getScale()) / durationMs; + final float oldScale = getScale(); + final long startTime = System.currentTimeMillis(); + + // Setup the zoom runnable + post(new Runnable() { + public void run() { + long now = System.currentTimeMillis(); + float currentMs = Math.min(durationMs, (float) (now - startTime)); + float target = oldScale + (incrementPerMs * currentMs); + zoomTo(target, centerX, centerY); + + if (currentMs < durationMs) { + post(this); + } + } + }); + } + + private boolean adjustLongImageEnable = true; + + public void setAdjustLongImageEnable(boolean enable) { + this.adjustLongImageEnable = enable; + } + + public void zoomToScreen() { + if (mBitmap == null) + return; + + float scale = 1f; + float fw = (float) mThisWidth / (float) mBitmap.getWidth(); + + boolean needAdjust = false; + if (adjustLongImageEnable) { + //长>>>宽 比如长微博 横向撑满屏幕,上下滑动浏览全文 + if ((float) mBitmap.getHeight() / (float) mBitmap.getWidth() > MAX_IMAGE_RATIO_LARGE) { + needAdjust = true; + scale = fw; + } else if (landscape && (float) mBitmap.getHeight() / (float) mBitmap.getWidth() > MAX_IMAGE_RATIO_WIDTH_LARGE_LANDSCAPE) { + needAdjust = true; + scale = fw; + } + } + + if (needAdjust) { + float oldScale = getScale(); + float deltaScale = scale / oldScale; + + mBaseMatrix.reset(); + mSuppMatrix.postScale(deltaScale, deltaScale, 0, 0); + setImageMatrix(getImageViewMatrix()); + } else { + zoomTo(zoomDefault()); + } + } + + // Unchanged from ImageViewTouchBase + public void zoomTo(float scale) { + float width = getWidth(); + float height = getHeight(); + + zoomTo(scale, width / 2F, height / 2F); + } + + // Unchanged from ImageViewTouchBase + public void zoomIn() { + zoomIn(sScaleRate); + } + + // Unchanged from ImageViewTouchBase + public void zoomOut() { + zoomOut(sScaleRate); + } + + // Unchanged from ImageViewTouchBase + protected void zoomIn(float rate) { + if (getScale() >= mMaxZoom) { + return; // Don't let the user zoom into the molecular level. + } + if (mBitmap == null) { + return; + } + + float width = getWidth(); + float height = getHeight(); + + mSuppMatrix.postScale(rate, rate, width / 2F, height / 2F); + setImageMatrix(getImageViewMatrix()); + + } + + // Unchanged from ImageViewTouchBase + protected void zoomOut(float rate) { + if (mBitmap == null) { + return; + } + + float width = getWidth(); + float height = getHeight(); + + Matrix tmp = new Matrix(mSuppMatrix); + tmp.postScale(1F / sScaleRate, 1F / sScaleRate, width / 2F, height / 2F); + if (getScale(tmp) < 1F) { + mSuppMatrix.setScale(1F, 1F, width / 2F, height / 2F); + } else { + mSuppMatrix.postScale(1F / rate, 1F / rate, width / 2F, height / 2F); + } + setImageMatrix(getImageViewMatrix()); + center(true, true, false); + + } + + // Unchanged from ImageViewTouchBase + protected boolean postTranslate(float dx, float dy) { + return mSuppMatrix.postTranslate(dx, dy); + } + + // Fling a view by a distance over time + protected void scrollBy(float distanceX, float distanceY, final float durationMs) { + final float dx = distanceX; + final float dy = distanceY; + final long startTime = System.currentTimeMillis(); + + mFling = new Runnable() { + float old_x = 0; + float old_y = 0; + + public void run() { + long now = System.currentTimeMillis(); + float currentMs = Math.min(durationMs, now - startTime); + float x = easeOut(currentMs, 0, dx, durationMs); + float y = easeOut(currentMs, 0, dy, durationMs); + postTranslate((x - old_x), (y - old_y)); + center(true, true, false); + + old_x = x; + old_y = y; + if (currentMs < durationMs) { + fling = post(this); + } else { + stopFling(); + } + } + }; + + fling = post(mFling); + } + + protected void stopFling() { + removeCallbacks(mFling); + if (fling) { + fling = false; + onScrollFinish(); + } + } + + protected boolean fling() { + return fling; + } + + // Gradually slows down a fling velocity + private float easeOut(float time, float start, float end, float duration) { + return end * ((time = time / duration - 1) * time * time + 1) + start; + } + + protected void onScrollFinish() { + + } + + // Custom draw operation to draw the bitmap using mMatrix + @SuppressLint("NewApi") + @Override + protected void onDraw(Canvas canvas) { + // Check if the bitmap was ever set + if (mBitmap != null && !mBitmap.isRecycled()) { + + // If the current version is above Gingerbread and the layer type is + // hardware accelerated, the paint is no longer needed + if (Build.VERSION.SDK_INT >= MIN_SDK_ENABLE_LAYER_TYPE_HARDWARE + && getLayerType() == View.LAYER_TYPE_HARDWARE) { + canvas.drawBitmap(mBitmap, mMatrix, null); + } else { + // Check if the time between draws has been met and draw the bitmap + if ((System.currentTimeMillis() - mLastDraw) > sPaintDelay) { + canvas.drawBitmap(mBitmap, mMatrix, mPaint); + mLastDraw = System.currentTimeMillis(); + } + + // Otherwise draw the bitmap without the paint and resubmit a new request + else { + canvas.drawBitmap(mBitmap, mMatrix, null); + removeCallbacks(mRefresh); + postDelayed(mRefresh, sPaintDelay); + } + } + } + } + + protected boolean isScrollOver(float distanceX) { + try { + if (mDisplayMatrix != null) { + float m_x = getValue(mDisplayMatrix, Matrix.MTRANS_X); //图片的左边离屏宽度 + float width = getWidth() - m_x; + //width 代表 屏幕宽度+左边离屏宽度 + //mBitmap.getWidth() * getValue(mDisplayMatrix, Matrix.MSCALE_X) 代表 当前图片显示宽度 + //width == mBitmap.getWidth() * getValue(mDisplayMatrix, Matrix.MSCALE_X) 意味着图片右边离屏宽度 == 0,已经滑到最右边 + if ((m_x == 0 && distanceX <= 0) //到达图片的最左边继续往左边滑 + || (width == mBitmap.getWidth() //到达图片的最右边继续往右边滑 + * getValue(mDisplayMatrix, Matrix.MSCALE_X) && distanceX >= 0)) { + System.out.println("ScrollOver"); + return true; + } + } + } catch (IllegalArgumentException e) { + Log.v("Vincent", "isScrollOver"); + e.printStackTrace(); + } + + return false; + } + + + protected Rect updateSelection() { + return null; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CheckedImageButton.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CheckedImageButton.java new file mode 100644 index 0000000..0423420 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CheckedImageButton.java @@ -0,0 +1,108 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.ImageButton; + +/** + * 选中图片控件 + */ +public class CheckedImageButton extends ImageButton { + + private boolean checked; + + private int normalBkResId; + + private int checkedBkResId; + + private Drawable normalImage; + + private Drawable checkedImage; + + private int leftPadding, topPadding, rightPadding, bottomPadding; + + public CheckedImageButton(Context context) { + super(context); + } + + public CheckedImageButton(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CheckedImageButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setPaddingValue(int value) { + setPaddingValue(value, value, value, value); + } + + public void setPaddingValue(int left, int top, int right, int bottom) { + leftPadding = left; + topPadding = top; + rightPadding = right; + bottomPadding = bottom; + setPadding(leftPadding, topPadding, rightPadding, bottomPadding); + } + + public boolean isChecked() { + return checked; + } + + public void setChecked(boolean push) { + this.checked = push; + + Drawable image = push ? checkedImage : normalImage; + if (image != null) { + updateImage(image); + } + + int background = push ? checkedBkResId : normalBkResId; + if (background != 0) { + updateBackground(background); + } + } + + public void setNormalBkResId(int normalBkResId) { + this.normalBkResId = normalBkResId; + updateBackground(normalBkResId); + } + + public void setCheckedBkResId(int checkedBkResId) { + this.checkedBkResId = checkedBkResId; + } + + public void setNormalImageId(int normalResId) { + normalImage = getResources().getDrawable(normalResId); + updateImage(normalImage); + } + + public void setCheckedImageId(int pushedResId) { + checkedImage = getResources().getDrawable(pushedResId); + } + + public void setNormalImage(Bitmap bitmap) { + + this.normalImage = new BitmapDrawable(getResources(), bitmap); + updateImage(this.normalImage); + } + + public void setCheckedImage(Bitmap bitmap) { + this.checkedImage = new BitmapDrawable(getResources(), bitmap); + } + + private void updateBackground(int resId) { + setBackgroundResource(resId); + setPadding(leftPadding, topPadding, rightPadding, bottomPadding); +// int padding = ScreenUtil.dip2px(7); +// setPadding(padding, padding, padding, padding); + } + + private void updateImage(Drawable drawable) { + // setScaleType(ScaleType.FIT_CENTER); + setImageDrawable(drawable); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CircleImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CircleImageView.java new file mode 100644 index 0000000..8616322 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CircleImageView.java @@ -0,0 +1,346 @@ +/* + * Copyright 2014 - 2015 Henning Dodenhof + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.netease.nim.uikit.R; + +public class CircleImageView extends ImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 2; + + private static final int DEFAULT_BORDER_WIDTH = 0; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT; + private static final boolean DEFAULT_BORDER_OVERLAY = false; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + private final Paint mFillPaint = new Paint(); + + private int mBorderColor = DEFAULT_BORDER_COLOR; + private int mBorderWidth = DEFAULT_BORDER_WIDTH; + private int mFillColor = DEFAULT_FILL_COLOR; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private ColorFilter mColorFilter; + + private boolean mReady; + private boolean mSetupPending; + private boolean mBorderOverlay; + + public CircleImageView(Context context) { + super(context); + + init(); + } + + public CircleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); + + mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH); + mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR); + mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY); + mFillColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, DEFAULT_FILL_COLOR); + + a.recycle(); + + init(); + } + + private void init() { + super.setScaleType(SCALE_TYPE); + mReady = true; + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); + } + } + + @Override + public void setAdjustViewBounds(boolean adjustViewBounds) { + if (adjustViewBounds) { + throw new IllegalArgumentException("adjustViewBounds not supported."); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mBitmap == null) { + return; + } + + if (mFillColor != Color.TRANSPARENT) { + canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mFillPaint); + } + canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mBitmapPaint); + if (mBorderWidth != 0) { + canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mBorderRadius, mBorderPaint); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + public int getBorderColor() { + return mBorderColor; + } + + public void setBorderColor(int borderColor) { + if (borderColor == mBorderColor) { + return; + } + + mBorderColor = borderColor; + mBorderPaint.setColor(mBorderColor); + invalidate(); + } + + public void setBorderColorResource(int borderColorRes) { + setBorderColor(getContext().getResources().getColor(borderColorRes)); + } + + public int getFillColor() { + return mFillColor; + } + + public void setFillColor(int fillColor) { + if (fillColor == mFillColor) { + return; + } + + mFillColor = fillColor; + mFillPaint.setColor(fillColor); + invalidate(); + } + + public void setFillColorResource(int fillColorRes) { + setFillColor(getContext().getResources().getColor(fillColorRes)); + } + + public int getBorderWidth() { + return mBorderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth == mBorderWidth) { + return; + } + + mBorderWidth = borderWidth; + setup(); + } + + public boolean isBorderOverlay() { + return mBorderOverlay; + } + + public void setBorderOverlay(boolean borderOverlay) { + if (borderOverlay == mBorderOverlay) { + return; + } + + mBorderOverlay = borderOverlay; + setup(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + mBitmap = bm; + setup(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + mBitmap = getBitmapFromDrawable(drawable); + setup(); + } + + @Override + public void setImageResource(int resId) { + super.setImageResource(resId); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + mBitmap = uri != null ? getBitmapFromDrawable(getDrawable()) : null; + setup(); + } + + @Override + public void setColorFilter(ColorFilter cf) { + if (cf == mColorFilter) { + return; + } + + mColorFilter = cf; + mBitmapPaint.setColorFilter(mColorFilter); + invalidate(); + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (getWidth() == 0 && getHeight() == 0) { + return; + } + + if (mBitmap == null) { + invalidate(); + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + mBorderPaint.setColor(mBorderColor); + mBorderPaint.setStrokeWidth(mBorderWidth); + + mFillPaint.setStyle(Paint.Style.FILL); + mFillPaint.setAntiAlias(true); + mFillPaint.setColor(mFillColor); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(0, 0, getWidth(), getHeight()); + mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f); + + mDrawableRect.set(mBorderRect); + if (!mBorderOverlay) { + mDrawableRect.inset(mBorderWidth, mBorderWidth); + } + mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f); + + updateShaderMatrix(); + invalidate(); + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CropImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CropImageView.java new file mode 100644 index 0000000..742fc06 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/CropImageView.java @@ -0,0 +1,314 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.animation.Animation; +import android.view.animation.TranslateAnimation; + +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class CropImageView extends MultiTouchZoomableImageView { + + private static final int MARGIN = 50; + + private int outputX; + private int outputY; + + Paint shadowPaint; + Paint linePaint; + + private Rect drawRect; + private Rect selection; + + // Programatic entry point + public CropImageView(Context context) { + super(context); + initCropImageView(context); + } + + // XML entry point + public CropImageView(Context context, AttributeSet attrs) { + super(context, attrs); + initCropImageView(context); + } + + protected void initCropImageView(Context context) { + + shadowPaint = new Paint(); + shadowPaint.setColor(Color.argb((int) (255 * 0.6), 0, 0, 0)); + linePaint = new Paint(); + linePaint.setColor(Color.rgb(0x99, 0x99, 0x99)); + + drawRect = new Rect(); + + transIgnoreScale = true; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, + int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (changed) { + selection = updateSelection(); + } + } + + public void setOutput(int outputX, int outputY) { + this.outputX = outputX; + this.outputY = outputY; + } + + public byte[] getCroppedImage() { + Bitmap cropped = getCroppedBitmap(); + if (cropped == null) { + return null; + } + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + cropped.compress(Bitmap.CompressFormat.JPEG, 100, stream); + if (cropped != mBitmap) { + cropped.recycle(); + } + byte[] data = stream.toByteArray(); + try { + stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return data; + } + + public boolean saveCroppedImage(String path) { + Bitmap cropped = getCroppedBitmap(); + return AttachmentStore.saveBitmap(cropped, path, cropped != mBitmap); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (selection != null) { + canvas.drawLine(selection.left, selection.top, selection.right, selection.top, linePaint); + canvas.drawLine(selection.left, selection.top, selection.left, selection.bottom, linePaint); + canvas.drawLine(selection.right, selection.top, selection.right, selection.bottom, linePaint); + canvas.drawLine(selection.left, selection.bottom, selection.right, selection.bottom, linePaint); + + drawRect.set(0, 0, getRight(), selection.top); + canvas.drawRect(drawRect, shadowPaint); + drawRect.set(0, selection.top, selection.left, selection.bottom); + canvas.drawRect(drawRect, shadowPaint); + drawRect.set(selection.right, selection.top, getRight(), selection.bottom); + canvas.drawRect(drawRect, shadowPaint); + drawRect.set(0, selection.bottom, getRight(), getBottom()); + canvas.drawRect(drawRect, shadowPaint); + } + } + + @Override + protected Rect updateSelection() { + if (outputX <= 0 || outputY <= 0) { + return null; + } + Rect selection; + + int viewWidth = getWidth(); + int viewHeight = getHeight(); + float outputRatio = ((float) outputY) / outputX; + float screenRatio = ((float) viewHeight) / viewWidth; + if (outputRatio < screenRatio) { + int width = viewWidth - MARGIN * 2; + int height = outputY * width / outputX; + int x = MARGIN; + int y = (viewHeight - height) / 2; + selection = new Rect(x, y, x + width, y + height); + } else { + int height = viewHeight - MARGIN * 2; + int width = outputX * height / outputY; + int y = MARGIN; + int x = (viewWidth - width) / 2; + selection = new Rect(x, y, x + width, y + height); + } + + return selection; + } + + private Bitmap getCroppedBitmap() { + Bitmap bitmap = getImageBitmap(); + if (bitmap == null) { + return null; + } + if (selection == null) { + return bitmap; + } + + Matrix matrix = getImageViewMatrix(); + float transX = getValue(matrix, Matrix.MTRANS_X); + float transY = getValue(matrix, Matrix.MTRANS_Y); + float scale = getValue(matrix, Matrix.MSCALE_X); + + int x = (int) ((selection.left - transX) / scale); + int y = (int) ((selection.top - transY) / scale); + int width = (int) (selection.width() / scale); + int height = (int) (selection.height() / scale); + + // 边界判断 + x = (x >= 0 ? x : 0); + y = (y >= 0 ? y : 0); + width = (width <= bitmap.getWidth() - x ? width : bitmap.getWidth() - x); + height = (height <= bitmap.getHeight() - y ? height : bitmap.getHeight() - y); + + // 保持长宽比 + float outputRatio = ((float) outputY) / outputX; + float screenRatio = ((float) height) / width; + if (outputRatio < screenRatio) { + height = (int) (width * outputRatio); + } else { + width = (int) (height / outputRatio); + } + + Matrix m = new Matrix(); + final float sx = outputX / (float) width; + m.setScale(sx, sx); + try { + + return Bitmap.createBitmap(bitmap, x, y, width, height, m, false); + } catch (Exception e) { + + return null; + } + + } + + @Override + protected void center(boolean vertical, boolean horizontal, boolean animate) { + if (mBitmap == null) + return; + if (selection == null) { + invalidate(); + return; + } + + Matrix m = getImageViewMatrix(); + + float[] topLeft = new float[]{0, 0}; + float[] botRight = new float[]{mBitmap.getWidth(), mBitmap.getHeight()}; + + translatePoint(m, topLeft); + translatePoint(m, botRight); + + float deltaX = 0, deltaY = 0; + + if (vertical) { + if (topLeft[1] > selection.bottom) { + deltaY = selection.bottom - topLeft[1]; + } else if (botRight[1] < selection.top) { + deltaY = selection.top - botRight[1]; + } + } + + if (horizontal) { + if (topLeft[0] > selection.right) { + deltaX = selection.right - topLeft[0]; + } else if (botRight[0] < selection.left) { + deltaX = selection.left - botRight[0]; + } + } + + postTranslate(deltaX, deltaY); + if (animate) { + Animation a = new TranslateAnimation(-deltaX, 0, -deltaY, 0); + a.setStartTime(SystemClock.elapsedRealtime()); + a.setDuration(250); + setAnimation(a); + } + setImageMatrix(getImageViewMatrix()); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + boolean handled = super.onTouchEvent(event); + + if (mBitmap != null) { + if (event.getAction() == MotionEvent.ACTION_UP) { + if (fling()) { + if (checkImagePosition(false)) { + stopFling(); + } + } else { + checkImagePosition(true); + } + } + } + + return handled; + } + + + // Sets the bitmap for the image and resets the base + public void setImageBitmap(final Bitmap bitmap) { + super.setImageBitmap(bitmap, selection); + } + + /** + * 把图片移动回到截屏的矩形框内,保证图片能完全覆盖截屏矩形 + * + * @return + * @date 2014年5月22日 + */ + protected boolean checkImagePosition(boolean scroll) { + + boolean translate = false; + if (mBitmap == null || selection == null) { + return translate; + } + Matrix m = getImageViewMatrix(); + + float[] topLeft = new float[]{0, 0}; + float[] botRight = new float[]{mBitmap.getWidth(), mBitmap.getHeight()}; + + translatePoint(m, topLeft); + translatePoint(m, botRight); + float transX = 0.0f; + float transY = 0.0f; + + if (topLeft[0] > selection.left) { + transX = selection.left - topLeft[0]; + translate = true; + } else if (botRight[0] < selection.right) { + transX = selection.right - botRight[0]; + translate = true; + } + + if (topLeft[1] > selection.top) { + transY = selection.top - topLeft[1]; + translate = true; + } else if (botRight[1] < selection.bottom) { + transY = selection.bottom - botRight[1]; + translate = true; + } + + if (scroll && translate) { + //直线动画的效果移回 + scrollBy(transX, transY, 200); + } + + return translate; + } + + @Override + protected void onScrollFinish() { + checkImagePosition(true); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/HeadImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/HeadImageView.java new file mode 100644 index 0000000..5d8c174 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/HeadImageView.java @@ -0,0 +1,145 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.nos.model.NosThumbParam; +import com.netease.nimlib.sdk.nos.util.NosThumbImageUtil; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +/** + * Created by huangjun on 2015/11/13. + */ +public class HeadImageView extends CircleImageView { + + public static final int DEFAULT_AVATAR_THUMB_SIZE = (int) NimUIKit.getContext().getResources().getDimension(R.dimen.avatar_max_size); + public static final int DEFAULT_AVATAR_NOTIFICATION_ICON_SIZE = (int) NimUIKit.getContext().getResources().getDimension(R.dimen.avatar_notification_size); + private static int DEFAULT_AVATAR_RES_ID = R.drawable.nim_avatar_default; + private Context mContext; + + public HeadImageView(Context context) { + super(context); + this.mContext = context; + } + + public HeadImageView(Context context, AttributeSet attrs) { + super(context, attrs); + this.mContext = context; + } + + public HeadImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.mContext = context; + } + + /** + * 加载用户头像(默认大小的缩略图) + * + * @param url 头像地址 + */ + public void loadAvatar(final String url) { + DEFAULT_AVATAR_RES_ID = R.drawable.woman; + doLoadImage(url, DEFAULT_AVATAR_RES_ID, DEFAULT_AVATAR_THUMB_SIZE); + } + + /** + * 加载用户头像(默认大小的缩略图) + * + * @param account 用户账号 + */ + public void loadBuddyAvatar(String account) { + final UserInfo userInfo = NimUIKit.getUserInfoProvider().getUserInfo(account); + NimUserInfo nimUserInfo = (NimUserInfo) NimUIKit.getUserInfoProvider().getUserInfo(account); + + if (null != nimUserInfo) { + if (null != nimUserInfo.getGenderEnum()) { + //修改默认图 + if (nimUserInfo.getGenderEnum().getValue() == 2) { //女 + DEFAULT_AVATAR_RES_ID = R.drawable.man; + } else if (nimUserInfo.getGenderEnum().getValue() == 1) { //男 + DEFAULT_AVATAR_RES_ID = R.drawable.woman; + } + } + } + + doLoadImage(userInfo != null ? (Constans.IMAGE_URL + userInfo.getAvatar()) : null, DEFAULT_AVATAR_RES_ID, DEFAULT_AVATAR_THUMB_SIZE); + } + + /** + * 加载用户头像(默认大小的缩略图) + * + * @param message 消息 + */ + public void loadBuddyAvatar(IMMessage message) { + String account = message.getFromAccount(); + if (message.getMsgType() == MsgTypeEnum.robot) { + RobotAttachment attachment = (RobotAttachment) message.getAttachment(); + if (attachment.isRobotSend()) { + account = attachment.getFromRobotAccount(); + } + } + loadBuddyAvatar(account); + } + + /** + * 加载群头像(默认大小的缩略图) + * + * @param team 群 + */ + public void loadTeamIconByTeam(final Team team) { + doLoadImage(team != null ? team.getIcon() : null, R.drawable.nim_avatar_group, DEFAULT_AVATAR_THUMB_SIZE); + } + + /** + * ImageLoader异步加载 + */ + private void doLoadImage(final String url, final int defaultResId, final int thumbSize) { + /* + * 若使用网易云信云存储,这里可以设置下载图片的压缩尺寸,生成下载URL + * 如果图片来源是非网易云信云存储,请不要使用NosThumbImageUtil + */ + final String thumbUrl = makeAvatarThumbNosUrl(url, thumbSize); + RequestOptions requestOptions = new RequestOptions() + .centerCrop() + .placeholder(defaultResId) + .error(defaultResId) + .override(thumbSize, thumbSize); + Glide.with(getContext().getApplicationContext()).asBitmap() + .load(thumbUrl) + .apply(requestOptions) + .into(this); + } + + /** + * 解决ViewHolder复用问题 + */ + public void resetImageView() { + setImageBitmap(null); + } + + /** + * 生成头像缩略图NOS URL地址(用作ImageLoader缓存的key) + */ + private static String makeAvatarThumbNosUrl(final String url, final int thumbSize) { + if (TextUtils.isEmpty(url)) { + return url; + } + + return thumbSize > 0 ? NosThumbImageUtil.makeImageThumbUrl(url, NosThumbParam.ThumbType.Crop, thumbSize, thumbSize) : url; + } + + public static String getAvatarCacheKey(final String url) { + return makeAvatarThumbNosUrl(url, DEFAULT_AVATAR_THUMB_SIZE); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/ImageGestureListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/ImageGestureListener.java new file mode 100644 index 0000000..fce8967 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/ImageGestureListener.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +/* + * Copyright 2012 Laurence Dawson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public interface ImageGestureListener { + + void onImageGestureSingleTapConfirmed(); + + void onImageGestureLongPress(); + + void onImageGestureFlingDown(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/MsgThumbImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/MsgThumbImageView.java new file mode 100644 index 0000000..f7539c3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/MsgThumbImageView.java @@ -0,0 +1,131 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestBuilder; +import com.bumptech.glide.request.RequestOptions; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.netease.nim.uikit.R; + +import java.io.File; + +public class MsgThumbImageView extends ImageView { + + public MsgThumbImageView(Context context) { + super(context); + } + + public MsgThumbImageView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public MsgThumbImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * *************************** 自定义绘制 ********************************** + */ + + private Drawable mask; // blend mask drawable + + private static final Paint paintMask = createMaskPaint(); + + private static Paint createMaskPaint() { + Paint paint = new Paint(); + + paint.setAntiAlias(true); + paint.setFilterBitmap(true); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + + return paint; + } + + @Override + protected void onDraw(Canvas canvas) { + if (mask != null) { + // bounds + int width = getWidth(); + int height = getHeight(); + + // create blend layer + canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG); + + // + // mask + // + if (mask != null) { + mask.setBounds(0, 0, width, height); + mask.draw(canvas); + } + + // + // source + // + { + canvas.saveLayer(0, 0, width, height, paintMask, Canvas.ALL_SAVE_FLAG); + super.onDraw(canvas); + canvas.restore(); + } + + // apply blend layer + canvas.restore(); + } else { + super.onDraw(canvas); + } + } + + @Override + public boolean isOpaque() { + return false; + } + + /** + * *************************** 对外接口 ********************************** + */ + + public void loadAsResource(final int resId, final int maskId) { + setBlendDrawable(maskId); + Glide.with(getContext().getApplicationContext()).load(resId).into(this); + } + + public void loadAsPath(final String path, final int width, final int height, final int maskId, final String ext) { + if (TextUtils.isEmpty(path)) { + loadAsResource(R.drawable.nim_image_default, maskId); + return; + } + + setBlendDrawable(maskId); + + RequestBuilder builder; + if (ImageUtil.isGif(ext)) { + builder = Glide.with(getContext().getApplicationContext()).asGif().load(new File(path)); + } else { + RequestOptions options = new RequestOptions() + .override(width, height) + .fitCenter() + .placeholder(R.drawable.nim_image_default) + .error(R.drawable.nim_image_default); + + builder = Glide.with(getContext().getApplicationContext()) + .asBitmap() + .apply(options) + .load(new File(path)) + ; + } + builder.into(this); + } + + private void setBlendDrawable(int maskId) { + mask = maskId != 0 ? getResources().getDrawable(maskId) : null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/MultiTouchZoomableImageView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/MultiTouchZoomableImageView.java new file mode 100644 index 0000000..f630835 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/imageview/MultiTouchZoomableImageView.java @@ -0,0 +1,236 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.imageview; + +/* + * Copyright 2012 Laurence Dawson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This class is based upon the file ImageViewTouchBase.java which can be found at: + * https://dl-ssl.google.com/dl/googlesource/git-repo/repo + * + * Copyright (C) 2009 The Android Open Source Project + */ + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; + +public class MultiTouchZoomableImageView extends BaseZoomableImageView { + // Scale and gesture listeners for the view + private GestureDetector mGestureDetector; + private ScaleGestureDetector mScaleDetector; + protected boolean transIgnoreScale = false; + private boolean scaleRecognized = false; + + // Programatic entry point + public MultiTouchZoomableImageView(Context context) { + super(context); + initMultiTouchZoomableImageView(context); + } + + // XML entry point + public MultiTouchZoomableImageView(Context context, AttributeSet attrs) { + super(context, attrs); + initMultiTouchZoomableImageView(context); + } + + // Setup the view + protected void initMultiTouchZoomableImageView(Context context) { + // Setup the gesture and scale listeners + mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); + mGestureDetector = new GestureDetector(context, new MyGestureListener()); + } + + + // Adjusts the zoom of the view + class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + + @Override + public boolean onScale(ScaleGestureDetector detector) { + // Check if the detector is in progress in order to proceed + if (detector != null && detector.isInProgress()) { + try { + // Grab the scale + float targetScale = getScale() * detector.getScaleFactor(); + // Correct for the min scale + targetScale = Math.min(maxZoom(), Math.max(targetScale, 1.0f)); + + // Zoom and invalidate the view + zoomTo(targetScale, detector.getFocusX(), detector.getFocusY()); + invalidate(); + + scaleRecognized = true; + + return true; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } + return false; + } + } + + // Handles taps and scrolls of the view + private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + if (mImageGestureListener != null) { + mImageGestureListener.onImageGestureSingleTapConfirmed(); + return false; + } + + return super.onSingleTapConfirmed(e); + } + + public void onLongPress(MotionEvent e) { + if (mImageGestureListener != null && !scaleRecognized) { + mImageGestureListener.onImageGestureLongPress(); + } + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + try { + // Skip if there are multiple points of contact + if ((e1 != null && e1.getPointerCount() > 1) || (e2 != null && e2.getPointerCount() > 1) || (mScaleDetector != null && mScaleDetector.isInProgress())) + return false; + + // Scroll the bitmap + if (transIgnoreScale || getScale() > zoomDefault()) { + stopFling(); + postTranslate(-distanceX, -distanceY); + + if (isScrollOver(distanceX)) { + if (mViewPager != null) { + mViewPager.requestDisallowInterceptTouchEvent(false); + } + } else { + if (mViewPager != null) { + mViewPager.requestDisallowInterceptTouchEvent(true); + } + } + + center(true, true, false); + } else { + if (mViewPager != null) { + mViewPager.requestDisallowInterceptTouchEvent(false); + } + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + + // Default case + return true; + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + // If the zoom is over 1x, reset to 1x + if (getScale() != zoomDefault()) { + zoomTo(zoomDefault()); + } + // If the zoom is default, zoom into 2x + else + zoomTo(zoomDefault() * 3, e.getX(), e.getY(), 200); + + // Always true as double tap was performed + return true; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if ((e1 != null && e1.getPointerCount() > 1) || (e2 != null && e2.getPointerCount() > 1)) + return false; + if (mScaleDetector.isInProgress()) return false; + + final float FLING_MIN_DISTANCE = 100; + final float FLING_MIN_VELOCITY = 200; + if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE + && Math.abs(velocityX) > FLING_MIN_VELOCITY) { + Log.i("MultiTouchZoomableImageView", "Fling Left"); + } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE + && Math.abs(velocityX) > FLING_MIN_VELOCITY) { + Log.i("MultiTouchZoomableImageView", "Fling Right"); + } else if (e1.getY() - e2.getY() > FLING_MIN_DISTANCE + && Math.abs(velocityY) > FLING_MIN_VELOCITY) { + Log.i("MultiTouchZoomableImageView", "Fling Up"); + } else if (e2.getY() - e1.getY() > FLING_MIN_DISTANCE + && Math.abs(velocityY) > FLING_MIN_VELOCITY) { + Log.i("MultiTouchZoomableImageView", "Fling Down"); + + if (!transIgnoreScale && getScale() <= zoomDefault()) { + mImageGestureListener.onImageGestureFlingDown(); + return true; + } + } + + try { + float diffX = e2.getX() - e1.getX(); + float diffY = e2.getY() - e1.getY(); + + if (Math.abs(velocityX) > 800 || Math.abs(velocityY) > 800) { + scrollBy(diffX / 2, diffY / 2, 300); + invalidate(); + } + } catch (NullPointerException e) { + + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + + return super.onFling(e1, e2, velocityX, velocityY); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + try { + if (mViewPager != null) { + switch (event.getAction()) { + case MotionEvent.ACTION_MOVE: + mViewPager.requestDisallowInterceptTouchEvent(true); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mViewPager.requestDisallowInterceptTouchEvent(false); + scaleRecognized = false; + break; + } + } + + // If the bitmap was set, check the scale and gesture detectors + if (mBitmap != null) { + // Check the scale detector + mScaleDetector.onTouchEvent(event); + + // Check the gesture detector + if (!mScaleDetector.isInProgress()) + mGestureDetector.onTouchEvent(event); + } else { + mImageGestureListener.onImageGestureSingleTapConfirmed(); + return false; + } + } catch (Exception e) { + e.printStackTrace(); + } + + return true; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/AutoRefreshListView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/AutoRefreshListView.java new file mode 100644 index 0000000..7112cee --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/AutoRefreshListView.java @@ -0,0 +1,293 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.listview; + +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.ListView; + +import com.netease.nim.uikit.R; + +import java.util.ArrayList; +import java.util.List; + +public class AutoRefreshListView extends ListView { + + public enum State { + REFRESHING, + RESET, + } + + public enum Mode { + START, + END, + BOTH, + } + + public interface OnRefreshListener { + public void onRefreshFromStart(); + + public void onRefreshFromEnd(); + } + + private OnRefreshListener refreshListener; + private List scrollListeners = new ArrayList(); + + private State state = State.RESET; + private Mode mode = Mode.START; + private Mode currentMode = Mode.START; + + private boolean refreshableStart = true; + private boolean refreshableEnd = true; + + private ViewGroup refreshHeader; + private ViewGroup refreshFooter; + + private int offsetY; + + public AutoRefreshListView(Context context) { + super(context); + init(context); + } + + public AutoRefreshListView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public AutoRefreshListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context); + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + public void setOnRefreshListener(OnRefreshListener refreshListener) { + this.refreshListener = refreshListener; + } + + @Override + public void setOnScrollListener(OnScrollListener l) { + // replaced by addOnScrollListener + throw new UnsupportedOperationException("Use addOnScrollListener instead!"); + } + + public void addOnScrollListener(OnScrollListener l) { + scrollListeners.add(l); + } + + public void removeOnScrollListener(OnScrollListener l) { + scrollListeners.remove(l); + } + + private void init(Context context) { + addRefreshView(context); + + super.setOnScrollListener(new OnScrollListener() { + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + for (OnScrollListener listener : scrollListeners) { + listener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); + } + } + + public void onScrollStateChanged(AbsListView view, int scrollState) { + for (OnScrollListener listener : scrollListeners) { + listener.onScrollStateChanged(view, scrollState); + } + } + }); + + initRefreshListener(); + + state = State.RESET; + } + + private void addRefreshView(Context context) { + refreshHeader = (ViewGroup) View.inflate(context, R.layout.nim_listview_refresh, null); + addHeaderView(refreshHeader, null, false); + refreshFooter = (ViewGroup) View.inflate(context, R.layout.nim_listview_refresh, null); + addFooterView(refreshFooter, null, false); + } + + private void initRefreshListener() { + OnScrollListener listener = new OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + if (scrollState == SCROLL_STATE_IDLE && state == State.RESET) { + boolean reachTop = (getFirstVisiblePosition() < getHeaderViewsCount() && getCount() > getHeaderViewsCount()); + if (reachTop) { + onRefresh(true); + } else { + boolean reachBottom = getLastVisiblePosition() >= getCount() - 1; + if (reachBottom) { + onRefresh(false); + } + } + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }; + + addOnScrollListener(listener); + } + + private void onRefresh(boolean start) { + if (refreshListener != null) { + View firstVisibleChild = getChildAt(getHeaderViewsCount()); + if (firstVisibleChild != null) { + offsetY = firstVisibleChild.getTop(); + } + + if (start && refreshableStart && mode != Mode.END) { + currentMode = Mode.START; + state = State.REFRESHING; + refreshListener.onRefreshFromStart(); + } else if (refreshableEnd && mode != Mode.START) { + currentMode = Mode.END; + state = State.REFRESHING; + refreshListener.onRefreshFromEnd(); + } + updateRefreshView(); + } + } + + private void updateRefreshView() { + switch (state) { + case REFRESHING: + getRefreshView().getChildAt(0).setVisibility(View.VISIBLE); + break; + case RESET: + if (currentMode == Mode.START) { + refreshHeader.getChildAt(0).setVisibility(refreshableStart ? View.INVISIBLE : View.GONE); + } else { + refreshFooter.getChildAt(0).setVisibility(View.GONE); + } + break; + } + } + + private ViewGroup getRefreshView() { + switch (currentMode) { + case END: + return refreshFooter; + case START: + default: + return refreshHeader; + } + } + + public void onRefreshStart(Mode mode) { + state = State.REFRESHING; + currentMode = mode; + } + + /** + * 加载完成 + */ + public void onRefreshComplete(int count, int requestCount, boolean needOffset) { + state = State.RESET; + resetRefreshView(count, requestCount); + if (!needOffset) { + return; + } + + if (currentMode == Mode.START) { + setSelectionFromTop(count + getHeaderViewsCount(), refreshableStart ? offsetY : 0); + } + } + + public void onRefreshComplete() { + state = State.RESET; + updateRefreshView(); + } + + private void resetRefreshView(int count, int requestCount) { + if (currentMode == Mode.START) { + /** 如果是第一次加载,如果count0, 就保留header的高度 + */ + if (getCount() == count + getHeaderViewsCount() + getFooterViewsCount()) { + refreshableStart = (count == requestCount); + } else { + refreshableStart = (count > 0); + } + } else { + refreshableEnd = (count > 0); + } + updateRefreshView(); + } + + /** + * handle over scroll when no more data + */ + private boolean isBeingDragged = false; + private int startY = 0; + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT < 11) { + try { + return onTouchEventInternal(event); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + return false; + } + } else { + return onTouchEventInternal(event); + } + } + + private boolean onTouchEventInternal(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + onTouchBegin(event); + break; + case MotionEvent.ACTION_MOVE: + onTouchMove(event); + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + onTouchEnd(); + break; + } + return super.onTouchEvent(event); + } + + private void onTouchBegin(MotionEvent event) { + int firstItemIndex = getFirstVisiblePosition(); + if (!refreshableStart && firstItemIndex <= getHeaderViewsCount() && !isBeingDragged) { + isBeingDragged = true; + startY = (int) event.getY(); + } + } + + private void onTouchMove(MotionEvent event) { + /** check state again */ + onTouchBegin(event); + if (!isBeingDragged) { + return; + } + + /** scroll to dragged position */ + int offsetY = (int) (event.getY() - startY); + offsetY = Math.max(offsetY, 0) / 2; + refreshHeader.setPadding(0, offsetY, 0, 0); + } + + private void onTouchEnd() { + if (isBeingDragged) { + refreshHeader.setPadding(0, 0, 0, 0); + } + + isBeingDragged = false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/ListViewUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/ListViewUtil.java new file mode 100644 index 0000000..cea27c3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/ListViewUtil.java @@ -0,0 +1,68 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.listview; + +import android.annotation.TargetApi; +import android.os.Build; +import android.view.View; +import android.widget.ListView; + +public class ListViewUtil { + + public static boolean isLastMessageVisible(ListView messageListView) { + if (messageListView == null || messageListView.getAdapter() == null) { + return false; + } + + if (messageListView.getLastVisiblePosition() >= messageListView.getAdapter().getCount() - 1 - messageListView.getFooterViewsCount()) { + return true; + } else { + return false; + } + } + + //index是items的index,不包含header + public static Object getViewHolderByIndex(ListView listView, int index) { + int firstVisibleFeedPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); + int lastVisibleFeedPosition = listView.getLastVisiblePosition() - listView.getHeaderViewsCount(); + + //只有获取可见区域的 + if (index >= firstVisibleFeedPosition && index <= lastVisibleFeedPosition) { + View view = listView.getChildAt(index - firstVisibleFeedPosition); + Object tag = view.getTag(); + return tag; + } else { + return null; + } + } + + public interface ScrollToPositionListener { + void onScrollEnd(); + } + + public static void scrollToBottom(ListView listView) { + scrollToPosition(listView, listView.getAdapter().getCount() - 1, 0); + } + + public static void scrollToBottom(ListView listView, ScrollToPositionListener listener) { + scrollToPosition(listView, listView.getAdapter().getCount() - 1, 0, listener); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static void scrollToPosition(ListView messageListView, int position, int y) { + scrollToPosition(messageListView, position, y, null); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private static void scrollToPosition(final ListView messageListView, final int position, final int y, final ScrollToPositionListener listener) { + messageListView.post(new Runnable() { + + @Override + public void run() { + messageListView.setSelectionFromTop(position, y); + + if (listener != null) { + listener.onScrollEnd(); + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/MessageListView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/MessageListView.java new file mode 100644 index 0000000..c8524b4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/listview/MessageListView.java @@ -0,0 +1,108 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.listview; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; +import android.widget.BaseAdapter; + +import com.fengliyan.tianlesue.im.uikit.common.adapter.IViewReclaimer; + +public class MessageListView extends AutoRefreshListView { + + private IViewReclaimer viewReclaimer; + + private GestureDetector gestureDetector; + + private OnListViewEventListener listener; + + private RecyclerListener recyclerListener = new RecyclerListener() { + + @Override + public void onMovedToScrapHeap(View view) { + if (viewReclaimer != null) { + viewReclaimer.reclaimView(view); + } + } + }; + + public MessageListView(Context context) { + super(context); + init(context); + } + + public MessageListView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public MessageListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context); + } + + private void init(Context context) { + setRecyclerListener(recyclerListener); + + gestureDetector = new GestureDetector(context, new GestureListener()); + } + + private boolean isScroll = false; + + @Override + public boolean onTouchEvent(MotionEvent event) { + gestureDetector.onTouchEvent(event); + + if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) { + isScroll = false; + } + + return super.onTouchEvent(event); + } + + public void setListViewEventListener(OnListViewEventListener listener) { + this.listener = listener; + } + + private class GestureListener extends GestureDetector.SimpleOnGestureListener { + @Override + public boolean onSingleTapUp(MotionEvent e) { + if (!isScroll) { + if (listener != null) { + listener.onListViewStartScroll(); + isScroll = true; + } + } + + return true; + } + + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (!isScroll) { + if (listener != null) { + listener.onListViewStartScroll(); + isScroll = true; + } + } + + return true; + } + } + + public void setAdapter(BaseAdapter adapter) { + // view reclaimer + viewReclaimer = adapter != null && adapter instanceof IViewReclaimer ? (IViewReclaimer) adapter : null; + + super.setAdapter(adapter); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + } + + public interface OnListViewEventListener { + public void onListViewStartScroll(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/liv/LetterIndexView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/liv/LetterIndexView.java new file mode 100644 index 0000000..c7a00ab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/liv/LetterIndexView.java @@ -0,0 +1,145 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.liv; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import com.netease.nim.uikit.R; + +public class LetterIndexView extends View { + + private OnTouchingLetterChangedListener listener; + + private String[] letters = null; + + private Paint mPaint; + + private float offset; + + private boolean hit; + + private int normalColor; + + private int touchColor; + + private Drawable hintDrawable; + + private int stringArrayId = R.array.letter_list; + + public LetterIndexView(Context paramContext) { + this(paramContext, null); + } + + public LetterIndexView(Context paramContext, AttributeSet paramAttributeSet) { + this(paramContext, paramAttributeSet, 0); + } + + public LetterIndexView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) { + super(paramContext, paramAttributeSet, paramInt); + this.mPaint = new Paint(); + this.offset = 0.0F; + this.hit = false; + this.normalColor = Color.GRAY; + this.touchColor = Color.WHITE; + + hintDrawable = paramContext.getResources().getDrawable(R.drawable.nim_contact_letter_view_hit_point); + hintDrawable.setBounds(0, 0, hintDrawable.getIntrinsicWidth(), hintDrawable.getIntrinsicHeight()); + + mPaint.setAntiAlias(true); + mPaint.setTextAlign(Paint.Align.CENTER); + mPaint.setColor(normalColor); + + letters = paramContext.getResources().getStringArray(stringArrayId); + } + + public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) { + this.listener = onTouchingLetterChangedListener; + } + + public void setLetters(String[] letters) { + this.letters = letters; + } + + public void setNormalColor(int color) { + this.normalColor = color; + mPaint.setColor(normalColor); + } + + public boolean dispatchTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + hit = true; + setBackgroundColor(getResources().getColor(R.color.contact_letter_idx_bg)); + mPaint.setColor(touchColor); + onHit(event.getY()); + break; + case MotionEvent.ACTION_MOVE: + onHit(event.getY()); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + onCancel(); + break; + } + invalidate(); + return true; + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + float letterHeight = ((float) getHeight()) / letters.length; + float width = getWidth(); + float textSize = letterHeight * 5 / 6; + mPaint.setTextSize(textSize); + for (int i = 0; i < letters.length; ++i) { + float halfWidth = width / 2; + float letterPosY = letterHeight * i + textSize; + canvas.drawText(letters[i], halfWidth, letterPosY, mPaint); + } + if (hit) { + int halfWidth = getWidth() / 2; + int halfDrawWidth = hintDrawable.getIntrinsicWidth() / 2; + float translateX = halfWidth - halfDrawWidth; + float halfDrawHeight = hintDrawable.getIntrinsicHeight() / 2; + float translateY = offset - halfDrawHeight; + canvas.save(); + canvas.translate(translateX, translateY); + hintDrawable.draw(canvas); + canvas.restore(); + } + } + + private void onHit(float offset) { + this.offset = offset; + if (hit && listener != null) { + int index = (int) (offset / getHeight() * letters.length); + index = Math.max(index, 0); + index = Math.min(index, letters.length - 1); + String str = letters[index]; + listener.onHit(str); + } + } + + private void onCancel() { + hit = false; + setBackgroundColor(Color.TRANSPARENT); + mPaint.setColor(this.normalColor); + refreshDrawableState(); + + if (listener != null) { + listener.onCancel(); + } + } + + public interface OnTouchingLetterChangedListener { + void onHit(String letter); + + void onCancel(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/liv/LivIndex.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/liv/LivIndex.java new file mode 100644 index 0000000..6ad001f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/liv/LivIndex.java @@ -0,0 +1,82 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.liv; + +import android.view.View; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.Map; + +/** + * 字母导航,点击字母,列表滑动到指定字母集合上。 + * + * @author huangjun + */ +public class LivIndex { + + private final ListView lvContacts; + + private final LetterIndexView livIndex; + + private final TextView lblLetterHit; + + private final ImageView imgBackLetter; + + private final Map mapABC; // 字母:所在的行的index + + public LivIndex(ListView contactsListView, LetterIndexView letterIndexView, TextView letterHit, ImageView + imgBackLetter, + Map abcMap) { + this.lvContacts = contactsListView; + this.livIndex = letterIndexView; + this.lblLetterHit = letterHit; + this.imgBackLetter = imgBackLetter; + this.mapABC = abcMap; + this.livIndex.setOnTouchingLetterChangedListener(new LetterChangedListener()); + } + + /** + * 显示 + */ + public void show() { + this.livIndex.setVisibility(View.VISIBLE); + } + + /** + * 隐藏 + */ + public void hide() { + this.livIndex.setVisibility(View.GONE); + } + + private class LetterChangedListener implements LetterIndexView.OnTouchingLetterChangedListener { + + @Override + public void onHit(String letter) { + lblLetterHit.setVisibility(View.VISIBLE); + imgBackLetter.setVisibility(View.VISIBLE); + lblLetterHit.setText(letter); + + int index = -1; + if ("↑".equals(letter)) { + index = 0; + } else if (mapABC.containsKey(letter)) { + index = mapABC.get(letter); + } + if (index < 0) { + return; + } + index += lvContacts.getHeaderViewsCount(); + if (index >= 0 && index < lvContacts.getCount()) { + lvContacts.setSelectionFromTop(index, 0); + } + } + + @Override + public void onCancel() { + lblLetterHit.setVisibility(View.INVISIBLE); + imgBackLetter.setVisibility(View.INVISIBLE); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/NIMPopupMenu.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/NIMPopupMenu.java new file mode 100644 index 0000000..a70c0c2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/NIMPopupMenu.java @@ -0,0 +1,195 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.popupmenu; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.drawable.BitmapDrawable; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnKeyListener; +import android.view.ViewGroup.LayoutParams; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ListView; +import android.widget.PopupWindow; +import android.widget.PopupWindow.OnDismissListener; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; + +import java.util.List; + +public class NIMPopupMenu { + + public static int TYPE_BG_WHITE = 0; + public static int TYPE_BG_BLACK = 1; + + private int typeBg = 0; + + private Context context; + + private List items; + + private PopupMenuAdapter adapter; + + private MenuItemClickListener listener; + + public PopupWindow popWindow; + + private View rootView; + + private boolean scroll = false; + + private void init() { + initListView(); + initPopupWindow(); + } + + public NIMPopupMenu(Context context, List items, MenuItemClickListener listener) { + this.context = context; + this.items = items; + this.listener = listener; + init(); + } + + /** + * @param context + * @param items + * @param listener + * @param typeBg + */ + public NIMPopupMenu(Context context, List items, MenuItemClickListener listener, int typeBg) { + this.context = context; + this.items = items; + this.listener = listener; + this.typeBg = typeBg; + init(); + + } + + public NIMPopupMenu(Context context, List items, MenuItemClickListener listener, int typeBg, boolean scroll) { + this.context = context; + this.items = items; + this.listener = listener; + this.typeBg = typeBg; + this.scroll = scroll; + init(); + } + + /** + * 初始化列表界面 + */ + private void initListView() { + if (rootView == null) { + if (typeBg == TYPE_BG_BLACK) { + rootView = LayoutInflater.from(context).inflate(R.layout.nim_popup_menu_black_layout, null); + } else { + rootView = LayoutInflater.from(context).inflate(R.layout.nim_popup_menu_layout, null); + } + ListView listView = (ListView) rootView.findViewById(R.id.popmenu_listview); + listView.setOnItemClickListener(new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (listener != null) { + popWindow.dismiss(); + listener.onItemClick(items.get(position)); + } + } + }); + adapter = new PopupMenuAdapter(context, items, typeBg); + listView.setAdapter(adapter); + } + rootView.setFocusableInTouchMode(true); + rootView.setOnKeyListener(new OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MENU && popWindow.isShowing() + && event.getAction() == KeyEvent.ACTION_DOWN) { + popWindow.dismiss(); + return true; + } + return false; + } + }); + } + + @SuppressWarnings("deprecation") + private void initPopupWindow() { + if (popWindow == null) { + //popWindow = new PopupWindow(rootView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + popWindow = new PopupWindow(context); + popWindow.setContentView(rootView); + popWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT); + if (scroll) { + popWindow.setHeight(ScreenUtil.getDisplayHeight() * 2 / 3); + } else { + popWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); + } + popWindow.setTouchable(true); + popWindow.setBackgroundDrawable(new BitmapDrawable()); + // popWindow.setContentView(rootView); + //setPopupWindowSize(); + // popWindow.setHeight(rootView.getMeasuredHeight()); + + popWindow.setOnDismissListener(new OnDismissListener() { + + @Override + public void onDismiss() { + + } + }); + } + } + + private void setPopupWindowSize() { + // popWindow.setContentView(rootView); + rootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + rootView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + popWindow.setWidth(rootView.getMeasuredWidth() + ScreenUtil.dip2px(15)); + // popWindow.setHeight(rootView.getMeasuredHeight()); + popWindow.update(); + } + + public void notifyData() { + adapter.notifyDataSetChanged(); + } + + public void show(View v) { + if (popWindow == null) { + return; + } + if (popWindow.isShowing()) { + popWindow.dismiss(); + } else { + //setPopupWindowSize(); + if (scroll) {// 当可以滚动时,横竖屏切换时,重新确定高度 + Configuration configuration = context.getResources().getConfiguration(); + int ori = configuration.orientation; + if (ori == Configuration.ORIENTATION_LANDSCAPE) { + popWindow.setHeight(ScreenUtil.getDialogWidth() * 2 / 3); + } else { + popWindow.setHeight(ScreenUtil.getDisplayHeight() * 2 / 3); + } + } + popWindow.setFocusable(true); + popWindow.showAsDropDown(v, -10, 0); + } + } + + public boolean isShowing() { + return popWindow != null && popWindow.isShowing(); + } + + public void dissmiss() { + if (isShowing()) + popWindow.dismiss(); + } + + public abstract interface MenuItemClickListener { + + public void onItemClick(PopupMenuItem item); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuAdapter.java new file mode 100644 index 0000000..e2b4fde --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuAdapter.java @@ -0,0 +1,91 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.popupmenu; + +import android.content.Context; +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 com.netease.nim.uikit.R; + +import java.util.List; + +public class PopupMenuAdapter extends BaseAdapter { + + public static int TYPE_BG_WHITE = 0; + public static int TYPE_BG_BLACK = 1; + + private int typeBg = 0; + + private Context context; + + private List list; + + private LayoutInflater inflater; + + public PopupMenuAdapter(Context context, List list, int typeBg) { + this.list = list; + inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + this.typeBg = typeBg; + } + + + @Override + public int getCount() { + return list.size(); + } + + @Override + public Object getItem(int position) { + return list.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + ImageView icon = null; + TextView title = null; + if (convertView == null) { + if (typeBg == TYPE_BG_BLACK) { + convertView = inflater.inflate(R.layout.nim_popup_menu_list_black_item, null); + } else { + convertView = inflater.inflate(R.layout.nim_popup_menu_list_item, null); + + } + icon = (ImageView) convertView.findViewById(R.id.popup_menu_icon); + title = (TextView) convertView.findViewById(R.id.popup_menu_title); + ViewHolder cache = new ViewHolder(); + cache.icon = icon; + cache.title = title; + convertView.setTag(cache); + } else { + ViewHolder cache = (ViewHolder) convertView.getTag(); + icon = cache.icon; + title = cache.title; + } + PopupMenuItem item = list.get(position); + if (item.getIcon() != 0) { + icon.setVisibility(View.VISIBLE); + icon.setImageResource(item.getIcon()); + } else { + icon.setVisibility(View.GONE); + } + title.setText(item.getTitle()); + + // 下面代码实现数据绑定 + return convertView; + } + + private final class ViewHolder { + + public ImageView icon; + + public TextView title; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuItem.java new file mode 100644 index 0000000..b3331cd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuItem.java @@ -0,0 +1,94 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.popupmenu; + +import android.content.Context; + +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +/** + * 菜单显示条目 + */ +public class PopupMenuItem { + + private int tag; + + private int icon; + + private String title; + + private Context context; + + private String sessionId; + + private SessionTypeEnum sessionTypeEnum; + + public PopupMenuItem(int tag, int icon, String title) { + this.tag = tag; + this.icon = icon; + this.title = title; + } + + /** + * 只有文字 + * + * @param tag + * @param title + */ + public PopupMenuItem(int tag, String title) { + this(tag, 0, title); + } + + public PopupMenuItem(Context context, int tag, String sessionId, SessionTypeEnum sessionTypeEnum, String title) { + this(tag, title); + this.context = context; + this.sessionId = sessionId; + this.sessionTypeEnum = sessionTypeEnum; + } + + public int getTag() { + return tag; + } + + public void setTag(int tag) { + this.tag = tag; + } + + public int getIcon() { + return icon; + } + + public void setIcon(int icon) { + this.icon = icon; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Context getContext() { + return context; + } + + public void setContext(Context context) { + this.context = context; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public SessionTypeEnum getSessionTypeEnum() { + return sessionTypeEnum; + } + + public void setSessionTypeEnum(SessionTypeEnum sessionTypeEnum) { + this.sessionTypeEnum = sessionTypeEnum; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuListView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuListView.java new file mode 100644 index 0000000..e2d9ca7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/popupmenu/PopupMenuListView.java @@ -0,0 +1,44 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.popupmenu; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +public class PopupMenuListView extends ListView { + + public PopupMenuListView(Context context) { + super(context); + } + + public PopupMenuListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public PopupMenuListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int maxWidth = meathureWidthByChilds() + getPaddingLeft() + getPaddingRight(); + super.onMeasure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.EXACTLY), heightMeasureSpec); + } + + public int meathureWidthByChilds() { + int maxWidth = 0; + View view = null; + for (int i = 0; i < getAdapter().getCount(); i++) { + view = getAdapter().getView(i, view, this); + if (view != null) { + view.setLayoutParams(new ViewGroup.LayoutParams(0, 0)); + view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); + if (view.getMeasuredWidth() > maxWidth) { + maxWidth = view.getMeasuredWidth(); + } + } + } + return maxWidth; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/CustomLoadingLayout.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/CustomLoadingLayout.java new file mode 100644 index 0000000..cf97cf6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/CustomLoadingLayout.java @@ -0,0 +1,109 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.ptr2; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.widget.FrameLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; + + +/** + * Created by sunpingji on 15/9/28. + */ +public class CustomLoadingLayout extends LoadingLayout { + + private FrameLayout mInnerLayout; + private LoadingView loadingView; + + public CustomLoadingLayout(Context context) { + super(context); + LayoutInflater.from(context).inflate(R.layout.nim_pull_to_refresh_header_custom, this); + mInnerLayout = (FrameLayout) findViewById(R.id.fl_inner); + loadingView = (LoadingView) mInnerLayout.findViewById(R.id.custom_loading); + } + + @Override + public void hideAllViews() { + if (VISIBLE == loadingView.getVisibility()) { + loadingView.setVisibility(INVISIBLE); + } + } + + @Override + public void onPull(float scaleOfLayout) { + loadingView.setBaseX(scaleOfLayout); + } + + @Override + protected void pullToRefresh() { + + } + + @Override + public void refreshing() { + loadingView.setNeedAnimation(true); + } + + @Override + protected void releaseToRefresh() { + + } + + @Override + public void reset() { + loadingView.setNeedAnimation(false); + loadingView.reset(); + } + + @Override + protected void showInvisibleViews() { + if (INVISIBLE == loadingView.getVisibility()) { + loadingView.setVisibility(VISIBLE); + } + } + + @Override + public int getContentSize() { + return ScreenUtil.dip2px(30); + } + + + @Override + public void setTextColor(ColorStateList color) { + + } + + @Override + public void setLastUpdatedLabel(CharSequence label) { + + } + + @Override + public void setLoadingDrawable(Drawable drawable) { + + } + + @Override + public void setPullLabel(CharSequence pullLabel) { + + } + + @Override + public void setRefreshingLabel(CharSequence refreshingLabel) { + + } + + @Override + public void setReleaseLabel(CharSequence releaseLabel) { + + } + + @Override + public void setTextTypeface(Typeface tf) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/ILoadingLayout.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/ILoadingLayout.java new file mode 100644 index 0000000..3a794c4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/ILoadingLayout.java @@ -0,0 +1,57 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.ptr2; + +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; + +public interface ILoadingLayout { + + /** + * Set the Last Updated Text. This displayed under the main label when + * Pulling + * + * @param label - Label to set + */ + public void setLastUpdatedLabel(CharSequence label); + + /** + * Set the drawable used in the loading layout. This is the same as calling + * setLoadingDrawable(drawable, Mode.BOTH) + * + * @param drawable - Drawable to display + */ + public void setLoadingDrawable(Drawable drawable); + + /** + * Set Text to show when the Widget is being Pulled + * setPullLabel(releaseLabel, Mode.BOTH) + * + * @param pullLabel - CharSequence to display + */ + public void setPullLabel(CharSequence pullLabel); + + /** + * Set Text to show when the Widget is refreshing + * setRefreshingLabel(releaseLabel, Mode.BOTH) + * + * @param refreshingLabel - CharSequence to display + */ + public void setRefreshingLabel(CharSequence refreshingLabel); + + /** + * Set Text to show when the Widget is being pulled, and will refresh when + * released. This is the same as calling + * setReleaseLabel(releaseLabel, Mode.BOTH) + * + * @param releaseLabel - CharSequence to display + */ + public void setReleaseLabel(CharSequence releaseLabel); + + /** + * Set's the Sets the typeface and style in which the text should be + * displayed. Please see + * {@link android.widget.TextView#setTypeface(Typeface) + * TextView#setTypeface(Typeface)}. + */ + public void setTextTypeface(Typeface tf); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/LoadingLayout.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/LoadingLayout.java new file mode 100644 index 0000000..f038ebf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/LoadingLayout.java @@ -0,0 +1,48 @@ + +package com.fengliyan.tianlesue.im.uikit.common.ui.ptr2; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.ColorStateList; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +@SuppressLint("ViewConstructor") +public abstract class LoadingLayout extends FrameLayout implements ILoadingLayout { + + + public LoadingLayout(Context context) { + super(context); + } + + protected abstract void hideAllViews(); + + protected abstract void onPull(float scaleOfLayout); + + protected abstract void pullToRefresh(); + + protected abstract void refreshing(); + + protected abstract void releaseToRefresh(); + + protected abstract void reset(); + + protected abstract void showInvisibleViews(); + + protected abstract int getContentSize(); + + public final void setWidth(int width) { + ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); + lp.width = width; + requestLayout(); + } + + + public final void setHeight(int height) { + ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); + lp.height = height; + requestLayout(); + } + + public abstract void setTextColor(ColorStateList color); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/LoadingView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/LoadingView.java new file mode 100644 index 0000000..a693657 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/LoadingView.java @@ -0,0 +1,263 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.ptr2; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PointF; +import android.util.AttributeSet; +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.R; + +/** + * Created by sunpingji. + */ +public class LoadingView extends View { + + private static final float DEFAULT_RADIUS = ScreenUtil.dip2px(5); + private static final int DEFAULT_BALL_COLOR = 0xffffffff; + private static final float DEFAULT_SPEED = (float) 0.5; + + private Paint paint = new Paint(); + + private Paint paint2 = new Paint(); + + private PointF leftBall; + private PointF rightBall; + + //两个小球的碰撞参数 + private float handleLenRate = 1f; + + private float radius = DEFAULT_RADIUS; + private float mv = 0.5f; + private float maxTouchDistance = (float) (DEFAULT_RADIUS * 2.5); + + + private int ballLeftColor = DEFAULT_BALL_COLOR; + private int ballRightColor = DEFAULT_BALL_COLOR; + + + //两个小球动画距离 + private float ballMoveDistance = (float) (DEFAULT_RADIUS * 3.5); + + //默认1秒 speed = 1/time;故speed=0.5表示2秒结束动画 + private float animationSpeed = DEFAULT_SPEED; + + private float baseX; + private float baseY; + + private boolean isNeedAnimation; + + public LoadingView(Context context) { + this(context, null); + } + + public LoadingView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs); + } + + public void reset() { + if (leftBall != null && rightBall != null) { + leftBall.x = baseX; + rightBall.x = baseX; + } + } + + public void setPaintMode(int mode) { + paint.setStyle(mode == 0 ? Paint.Style.STROKE : Paint.Style.FILL); + paint2.setStyle(mode == 0 ? Paint.Style.STROKE : Paint.Style.FILL); + invalidate(); + + leftBall.x = rightBall.x; + } + + private void init(AttributeSet attrs) { + + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.LoadingView); + ballLeftColor = a.getColor(R.styleable.LoadingView_left_ball_color, DEFAULT_BALL_COLOR); + ballRightColor = a.getColor(R.styleable.LoadingView_right_ball_color, DEFAULT_BALL_COLOR); + radius = a.getFloat(R.styleable.LoadingView_radius, DEFAULT_RADIUS); + maxTouchDistance = (float) (radius * 2.5); + ballMoveDistance = (float) (radius * 3.5); + animationSpeed = a.getFloat(R.styleable.LoadingView_animation_speed, DEFAULT_SPEED); + isNeedAnimation = a.getBoolean(R.styleable.LoadingView_need_animation, true); + a.recycle(); + paint.setColor(ballLeftColor); + paint.setStyle(Paint.Style.FILL); + paint.setAntiAlias(true); + + paint2.setColor(ballRightColor); + paint2.setStyle(Paint.Style.FILL); + paint2.setAntiAlias(true); + } + + private void initMetaballs() { + baseX = this.getMeasuredWidth() / 2; + baseY = this.getMeasuredHeight() / 2; + leftBall = new PointF(baseX, baseY); + rightBall = new PointF(baseX, baseY); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (changed) { + initMetaballs(); + } + } + + private float[] getVector(float radians, float length) { + float x = (float) (Math.cos(radians) * length); + float y = (float) (Math.sin(radians) * length); + return new float[]{ + x, y + }; + } + + /** + * @param canvas 画布 + * @param v 控制两个圆连接时候长度,间接控制连接线的粗细,该值为1的时候连接线为直线 + * @param handle_len_rate + * @param maxDistance + */ + private void metaball(Canvas canvas, float v, float handle_len_rate, float maxDistance) { + + float d = getDistance(); + + float radius1 = radius; + float radius2 = radius; + float pi2 = (float) (Math.PI / 2); + float u1, u2; + + + if (d > maxDistance) { + canvas.drawCircle(rightBall.x, rightBall.y, radius, paint2); + } else { + canvas.drawCircle(rightBall.x, rightBall.y, radius, paint2); + } + + if (radius1 == 0 || radius2 == 0) { + return; + } + + if (d > maxDistance || d <= Math.abs(radius1 - radius2)) { + return; + } else if (d < radius1 + radius2) { + u1 = (float) Math.acos((radius1 * radius1 + d * d - radius2 * radius2) / + (2 * radius1 * d)); + u2 = (float) Math.acos((radius2 * radius2 + d * d - radius1 * radius1) / + (2 * radius2 * d)); + } else { + u1 = 0; + u2 = 0; + } + float[] centermin = new float[]{rightBall.x - leftBall.x, rightBall.y - leftBall.y}; + + float angle1 = (float) Math.atan2(centermin[1], centermin[0]); + float angle2 = (float) Math.acos((radius1 - radius2) / d); + float angle1a = angle1 + u1 + (angle2 - u1) * v; + float angle1b = angle1 - u1 - (angle2 - u1) * v; + float angle2a = (float) (angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v); + float angle2b = (float) (angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v); + + + float[] p1a1 = getVector(angle1a, radius1); + float[] p1b1 = getVector(angle1b, radius1); + float[] p2a1 = getVector(angle2a, radius2); + float[] p2b1 = getVector(angle2b, radius2); + + float[] p1a = new float[]{p1a1[0] + leftBall.x, p1a1[1] + leftBall.y}; + float[] p1b = new float[]{p1b1[0] + leftBall.x, p1b1[1] + leftBall.y}; + float[] p2a = new float[]{p2a1[0] + rightBall.x, p2a1[1] + rightBall.y}; + float[] p2b = new float[]{p2b1[0] + rightBall.x, p2b1[1] + rightBall.y}; + + + float[] p1_p2 = new float[]{p1a[0] - p2a[0], p1a[1] - p2a[1]}; + + float totalRadius = (radius1 + radius2); + float d2 = Math.min(v * handle_len_rate, getLength(p1_p2) / totalRadius); + d2 *= Math.min(1, d * 2 / (radius1 + radius2)); + + radius1 *= d2; + radius2 *= d2; + + float[] sp1 = getVector(angle1a - pi2, radius1); + float[] sp2 = getVector(angle2a + pi2, radius2); + float[] sp3 = getVector(angle2b - pi2, radius2); + float[] sp4 = getVector(angle1b + pi2, radius1); + + + Path path1 = new Path(); + path1.moveTo(p1a[0], p1a[1]); + path1.cubicTo(p1a[0] + sp1[0], p1a[1] + sp1[1], p2a[0] + sp2[0], p2a[1] + sp2[1], p2a[0], p2a[1]); + path1.lineTo(p2b[0], p2b[1]); + path1.cubicTo(p2b[0] + sp3[0], p2b[1] + sp3[1], p1b[0] + sp4[0], p1b[1] + sp4[1], p1b[0], p1b[1]); + path1.lineTo(p1a[0], p1a[1]); + path1.close(); + canvas.drawPath(path1, paint2); + + } + + + public float getBallMoveDistance() { + return ballMoveDistance; + } + + private float getLength(float[] b) { + return (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]); + } + + private float getDistance() { + float x = leftBall.x - rightBall.x; + float y = leftBall.y - rightBall.y; + float d = x * x + y * y; + return (float) Math.sqrt(d); + } + + public void setBaseX(float scale) { + if (leftBall == null || rightBall == null) { + return; + } + leftBall.x = baseX - scale * ballMoveDistance / 2; + rightBall.x = baseX + scale * ballMoveDistance / 2; + invalidate(); + } + + public void setNeedAnimation(boolean animation) { + isNeedAnimation = animation; + invalidate(); + } + + private void startAnimation() { + if (isNeedAnimation) { + float input = (float) ((System.currentTimeMillis() % 10000 * animationSpeed % 1000) * 1.000 / 1000); + float ratio = (float) ((Math.sin(2 * Math.PI * input)) * ballMoveDistance); + leftBall.x = baseX + ratio; + rightBall.x = baseX - ratio; + float scaleRatio = (float) ((Math.cos(2 * Math.PI * input)) * DEFAULT_RADIUS * 0.2); + radius = (float) (DEFAULT_RADIUS * 0.8 + scaleRatio); + maxTouchDistance = (float) (radius * 2.5); + invalidate(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (leftBall == null || rightBall == null) { + initMetaballs(); + } + canvas.drawCircle(leftBall.x, leftBall.y, radius, paint); + metaball(canvas, mv, handleLenRate, maxTouchDistance); + startAnimation(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/PullToRefreshLayout.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/PullToRefreshLayout.java new file mode 100644 index 0000000..b35a4da --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/PullToRefreshLayout.java @@ -0,0 +1,111 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.ptr2; + +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; + + +/** + * 下拉刷新控件,可以配合 RecyclerView,Scrollview,ListView + * Created by fish on 16/5/17. + */ +public class PullToRefreshLayout extends SuperSwipeRefreshLayout { + + public interface OnRefreshListener { + void onPullDownToRefresh(); + + void onPullUpToRefresh(); + } + + private CustomLoadingLayout loadingLayoutDown; + private CustomLoadingLayout loadingLayoutUp; + private OnRefreshListener listener; + + public void setOnRefreshListener(OnRefreshListener listener) { + this.listener = listener; + } + + + public PullToRefreshLayout(Context context) { + super(context); + initLoadingView(true, true); + } + + public PullToRefreshLayout(Context context, AttributeSet attrs) { + super(context, attrs); + initLoadingView(true, true); + } + + //一般用于进页面第一次刷新 + public void autoRefresh() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + setRefreshing(true); + loadingLayoutDown.refreshing(); + if (listener != null) { + listener.onPullDownToRefresh(); + } + } + }, 100); + } + + public void initLoadingView(boolean pullDown, boolean pullUp) { + if (pullDown) { + loadingLayoutDown = new CustomLoadingLayout(getContext()); + setHeaderView(loadingLayoutDown); + setOnPullRefreshListener(new OnPullRefreshListener() { + + @Override + public void onRefresh() { + loadingLayoutDown.refreshing(); + if (listener != null) { + listener.onPullDownToRefresh(); + } + } + + @Override + public void onPullDistance(int distance) { + if (distance == 0) { + loadingLayoutDown.reset(); + } + loadingLayoutDown.onPull(distance * 1.0f / loadingLayoutDown.getContentSize()); + } + + @Override + public void onPullEnable(boolean enable) { +// textView.setText(enable ? "松开刷新" : "下拉刷新"); + } + }); + } + + if (pullUp) { + loadingLayoutUp = new CustomLoadingLayout(getContext()); + setFooterView(loadingLayoutUp); + setOnPushLoadMoreListener(new OnPushLoadMoreListener() { + @Override + public void onLoadMore() { + loadingLayoutUp.refreshing(); + if (listener != null) { + listener.onPullUpToRefresh(); + } + } + + @Override + public void onPushDistance(int distance) { + if (distance == 0) { + loadingLayoutUp.reset(); + } + loadingLayoutUp.onPull(distance * 1.0f / loadingLayoutUp.getContentSize()); + } + + @Override + public void onPushEnable(boolean enable) { + + } + }); + } + + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/SuperSwipeRefreshLayout.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/SuperSwipeRefreshLayout.java new file mode 100644 index 0000000..047ad27 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/ptr2/SuperSwipeRefreshLayout.java @@ -0,0 +1,1567 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.ptr2; + + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.os.Build; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Display; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.WindowManager; +import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Transformation; +import android.widget.AbsListView; +import android.widget.RelativeLayout; +import android.widget.ScrollView; + +import androidx.core.view.MotionEventCompat; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.LayoutManager; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + + +public class SuperSwipeRefreshLayout extends ViewGroup { + private static final String LOG_TAG = "SuperSwipeRefreshLayout"; + private static final int HEADER_VIEW_HEIGHT = 50;// HeaderView height (dp) + + private static final float DECELERATE_INTERPOLATION_FACTOR = 2f; + private static final int INVALID_POINTER = -1; + private static final float DRAG_RATE = .5f; + + private static final int SCALE_DOWN_DURATION = 150; + private static final int ANIMATE_TO_TRIGGER_DURATION = 200; + private static final int ANIMATE_TO_START_DURATION = 200; + private static final int DEFAULT_CIRCLE_TARGET = 64; + + // SuperSwipeRefreshLayout内的目标View,比如RecyclerView,ListView,ScrollView,GridView + // etc. + private View mTarget; + + private OnPullRefreshListener mListener;// 下拉刷新listener + private OnPushLoadMoreListener mOnPushLoadMoreListener;// 上拉加载更多 + + private boolean mRefreshing = false; + private boolean mLoadMore = false; + private int mTouchSlop; + private float mTotalDragDistance = -1; + private int mMediumAnimationDuration; + private int mCurrentTargetOffsetTop; + private boolean mOriginalOffsetCalculated = false; + + private float mInitialMotionY; + private boolean mIsBeingDragged; + private int mActivePointerId = INVALID_POINTER; + private boolean mScale; + + private boolean mReturningToStart; + private final DecelerateInterpolator mDecelerateInterpolator; + private static final int[] LAYOUT_ATTRS = new int[]{android.R.attr.enabled}; + + private HeadViewContainer mHeadViewContainer; + private RelativeLayout mFooterViewContainer; + private int mHeaderViewIndex = -1; + private int mFooterViewIndex = -1; + + protected int mFrom; + + private float mStartingScale; + + protected int mOriginalOffsetTop; + + private Animation mScaleAnimation; + + private Animation mScaleDownAnimation; + + private Animation mScaleDownToStartAnimation; + + // 最后停顿时的偏移量px,与DEFAULT_CIRCLE_TARGET正比 + private float mSpinnerFinalOffset; + + private boolean mNotify; + + private int mHeaderViewWidth;// headerView的宽度 + + private int mFooterViewWidth; + + private int mHeaderViewHeight; + + private int mFooterViewHeight; + + private boolean mUsingCustomStart; + + private boolean targetScrollWithLayout = true; + + private int pushDistance = 0; + + private CircleProgressView defaultProgressView = null; + + private boolean usingDefaultHeader = true; + + private float density = 1.0f; + + private boolean isProgressEnable = true; + + private boolean pullDownEnable = true; + private boolean pullUpEnable = true; + + + public void setPullDownEnable(boolean pullDownEnable) { + this.pullDownEnable = pullDownEnable; + } + + public void setPullUpEnable(boolean pullUpEnable) { + this.pullUpEnable = pullUpEnable; + } + + + /** + * 下拉时,超过距离之后,弹回来的动画监听器 + */ + private AnimationListener mRefreshListener = new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + isProgressEnable = false; + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + isProgressEnable = true; + if (mRefreshing) { + if (mNotify) { + if (usingDefaultHeader) { + ViewCompat.setAlpha(defaultProgressView, 1.0f); + defaultProgressView.setOnDraw(true); + new Thread(defaultProgressView).start(); + } + if (mListener != null) { + mListener.onRefresh(); + } + } + } else { + mHeadViewContainer.setVisibility(View.GONE); + if (mScale) { + setAnimationProgress(0); + } else { + /* + setTargetOffsetTopAndBottom(mOriginalOffsetTop + - mCurrentTargetOffsetTop, true); + */ + // 回弹动画 + final int from = mTarget.getTop(); + final int to = 0; + ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(250); + animator.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float value = (float) animation.getAnimatedValue(); + float step = (to - from) * value + from; + int top = mTarget.getTop(); + setTargetOffsetTopAndBottom((int) (step - top), true); + } + }); + animator.start(); + } + } + mCurrentTargetOffsetTop = mHeadViewContainer.getTop(); + updateListenerCallBack(); + } + }; + + /** + * 更新回调 + */ + private void updateListenerCallBack() { + int distance = mCurrentTargetOffsetTop + mHeadViewContainer.getHeight(); + if (mListener != null) { + mListener.onPullDistance(distance); + } + if (usingDefaultHeader && isProgressEnable) { + defaultProgressView.setPullDistance(distance); + } + } + + /** + * 添加头布局 + * + * @param child + */ + public void setHeaderView(View child) { + if (child == null) { + return; + } + if (mHeadViewContainer == null) { + return; + } + usingDefaultHeader = false; + mHeadViewContainer.removeAllViews(); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( + mHeaderViewWidth, mHeaderViewHeight); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + mHeadViewContainer.addView(child, layoutParams); + } + + public void setFooterView(View child) { + if (child == null) { + return; + } + if (mFooterViewContainer == null) { + return; + } + mFooterViewContainer.removeAllViews(); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( + mFooterViewWidth, mFooterViewHeight); + mFooterViewContainer.addView(child, layoutParams); + } + + public SuperSwipeRefreshLayout(Context context) { + this(context, null); + } + + @SuppressWarnings("deprecation") + public SuperSwipeRefreshLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + /** + * getScaledTouchSlop是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件。如果小于这个距离就不触发移动控件 + */ + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + + mMediumAnimationDuration = getResources().getInteger( + android.R.integer.config_mediumAnimTime); + + setWillNotDraw(false); + mDecelerateInterpolator = new DecelerateInterpolator( + DECELERATE_INTERPOLATION_FACTOR); + + final TypedArray a = context + .obtainStyledAttributes(attrs, LAYOUT_ATTRS); + setEnabled(a.getBoolean(0, true)); + a.recycle(); + + WindowManager wm = (WindowManager) context + .getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + final DisplayMetrics metrics = getResources().getDisplayMetrics(); + mHeaderViewWidth = (int) display.getWidth(); + mFooterViewWidth = (int) display.getWidth(); + mHeaderViewHeight = (int) (HEADER_VIEW_HEIGHT * metrics.density); + mFooterViewHeight = (int) (HEADER_VIEW_HEIGHT * metrics.density); + defaultProgressView = new CircleProgressView(getContext()); + createHeaderViewContainer(); + createFooterViewContainer(); + ViewCompat.setChildrenDrawingOrderEnabled(this, true); + mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density; + density = metrics.density; + mTotalDragDistance = mSpinnerFinalOffset; + } + + /** + * 孩子节点绘制的顺序 + * + * @param childCount + * @param i + * @return + */ + @Override + protected int getChildDrawingOrder(int childCount, int i) { + // 将新添加的View,放到最后绘制 + if (mHeaderViewIndex < 0 && mFooterViewIndex < 0) { + return i; + } + if (i == childCount - 2) { + return mHeaderViewIndex; + } + if (i == childCount - 1) { + return mFooterViewIndex; + } + int bigIndex = mFooterViewIndex > mHeaderViewIndex ? mFooterViewIndex + : mHeaderViewIndex; + int smallIndex = mFooterViewIndex < mHeaderViewIndex ? mFooterViewIndex + : mHeaderViewIndex; + if (i >= smallIndex && i < bigIndex - 1) { + return i + 1; + } + if (i >= bigIndex || (i == bigIndex - 1)) { + return i + 2; + } + return i; + } + + /** + * 创建头布局的容器 + */ + private void createHeaderViewContainer() { + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( + (int) (mHeaderViewHeight * 0.8), + (int) (mHeaderViewHeight * 0.8)); + layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + mHeadViewContainer = new HeadViewContainer(getContext()); + mHeadViewContainer.setVisibility(View.GONE); + defaultProgressView.setVisibility(View.VISIBLE); + defaultProgressView.setOnDraw(false); + mHeadViewContainer.addView(defaultProgressView, layoutParams); + addView(mHeadViewContainer); + } + + /** + * 添加底部布局 + */ + private void createFooterViewContainer() { + mFooterViewContainer = new RelativeLayout(getContext()); + mFooterViewContainer.setVisibility(View.GONE); + addView(mFooterViewContainer); + } + + /** + * 设置 + * + * @param listener + */ + public void setOnPullRefreshListener(OnPullRefreshListener listener) { + mListener = listener; + } + + public void setHeaderViewBackgroundColor(int color) { + mHeadViewContainer.setBackgroundColor(color); + } + + /** + * 设置上拉加载更多的接口 + * + * @param onPushLoadMoreListener + */ + public void setOnPushLoadMoreListener( + OnPushLoadMoreListener onPushLoadMoreListener) { + this.mOnPushLoadMoreListener = onPushLoadMoreListener; + } + + /** + * Notify the widget that refresh state has changed. Do not call this when + * refresh is triggered by a swipe gesture. + * + * @param refreshing Whether or not the view should show refresh progress. + */ + public void setRefreshing(boolean refreshing) { + if (refreshing && mRefreshing != refreshing) { + // scale and show + mRefreshing = refreshing; + int endTarget = 0; + if (!mUsingCustomStart) { + endTarget = (int) (mSpinnerFinalOffset + mOriginalOffsetTop); + } else { + endTarget = (int) mSpinnerFinalOffset; + } + setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop, + true /* requires update */); + mNotify = false; + startScaleUpAnimation(mRefreshListener); + } else { + setRefreshing(refreshing, false /* notify */); + if (usingDefaultHeader) { + defaultProgressView.setOnDraw(false); + } + } + } + + private void startScaleUpAnimation(AnimationListener listener) { + mHeadViewContainer.setVisibility(View.VISIBLE); + mScaleAnimation = new Animation() { + @Override + public void applyTransformation(float interpolatedTime, + Transformation t) { + setAnimationProgress(interpolatedTime); + } + }; + mScaleAnimation.setDuration(mMediumAnimationDuration); + if (listener != null) { + mHeadViewContainer.setAnimationListener(listener); + } + mHeadViewContainer.clearAnimation(); + mHeadViewContainer.startAnimation(mScaleAnimation); + } + + private void setAnimationProgress(float progress) { + if (!usingDefaultHeader) { + progress = 1; + } + ViewCompat.setScaleX(mHeadViewContainer, progress); + ViewCompat.setScaleY(mHeadViewContainer, progress); + } + + private void setRefreshing(boolean refreshing, final boolean notify) { + if (mRefreshing != refreshing) { + mNotify = notify; + ensureTarget(); + mRefreshing = refreshing; + if (mRefreshing) { + animateOffsetToCorrectPosition(mCurrentTargetOffsetTop, + mRefreshListener); + } else { + startScaleDownAnimation(mRefreshListener); + } + } + } + + private void startScaleDownAnimation(AnimationListener listener) { + mScaleDownAnimation = new Animation() { + @Override + public void applyTransformation(float interpolatedTime, + Transformation t) { + setAnimationProgress(1 - interpolatedTime); + } + }; + mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION); + mHeadViewContainer.setAnimationListener(listener); + mHeadViewContainer.clearAnimation(); + mHeadViewContainer.startAnimation(mScaleDownAnimation); + } + + public boolean isRefreshing() { + return mRefreshing; + } + + /** + * 确保mTarget不为空
+ * mTarget一般是可滑动的ScrollView,ListView,RecyclerView等 + */ + private void ensureTarget() { + if (mTarget == null) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (!child.equals(mHeadViewContainer) + && !child.equals(mFooterViewContainer)) { + mTarget = child; + break; + } + } + } + } + + /** + * Set the distance to trigger a sync in dips + * + * @param distance + */ + public void setDistanceToTriggerSync(int distance) { + mTotalDragDistance = distance; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, + int bottom) { +// LogUtil.fish("SuperSwipeRefreshLayout onLayout"); + final int width = getMeasuredWidth(); + final int height = getMeasuredHeight(); + if (getChildCount() == 0) { + return; + } + if (mTarget == null) { + ensureTarget(); + } + if (mTarget == null) { + return; + } + + layoutHead(width); + layoutTarget(width, height); + + + layoutFooter(width, height); + } + + private void layoutFooter(int width, int height) { + int footViewWidth = mFooterViewContainer.getMeasuredWidth(); + int footViewHeight = mFooterViewContainer.getMeasuredHeight(); + mFooterViewContainer.layout((width / 2 - footViewWidth / 2), height + - pushDistance, (width / 2 + footViewWidth / 2), height + + footViewHeight - pushDistance); + } + + private void layoutTarget(int width, int height) { + int distance = mCurrentTargetOffsetTop + mHeadViewContainer.getHeight(); +// LogUtil.fish("mHeadViewContainer height " + mHeadViewContainer.getHeight()); + if (!targetScrollWithLayout) { + // 判断标志位,如果目标View不跟随手指的滑动而滑动,将下拉偏移量设置为0 + distance = 0; + } + final int childLeft = getPaddingLeft(); + final int childTop = getPaddingTop() + distance - pushDistance;// 根据偏移量distance更新 + final int childWidth = width - getPaddingLeft() - getPaddingRight(); + final int childHeight = height - getPaddingTop() - getPaddingBottom(); + // Log.d(LOG_TAG, "debug:onLayout childHeight = " + childHeight); + mTarget.layout(childLeft, childTop, childLeft + childWidth, childTop + + childHeight);// 更新目标View的位置 + } + + private void layoutHead(int width) { + int headViewWidth = mHeadViewContainer.getMeasuredWidth(); + int headViewHeight = mHeadViewContainer.getMeasuredHeight(); + mHeadViewContainer.layout((width / 2 - headViewWidth / 2), + mCurrentTargetOffsetTop, (width / 2 + headViewWidth / 2), + mCurrentTargetOffsetTop + headViewHeight);// 更新头布局的位置 + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (mTarget == null) { + ensureTarget(); + } + if (mTarget == null) { + return; + } + mTarget.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth() + - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(getMeasuredHeight() + - getPaddingTop() - getPaddingBottom(), + MeasureSpec.EXACTLY)); + mHeadViewContainer.measure(MeasureSpec.makeMeasureSpec( + mHeaderViewWidth, MeasureSpec.EXACTLY), MeasureSpec + .makeMeasureSpec(3 * mHeaderViewHeight, MeasureSpec.EXACTLY)); + mFooterViewContainer.measure(MeasureSpec.makeMeasureSpec( + mFooterViewWidth, MeasureSpec.EXACTLY), MeasureSpec + .makeMeasureSpec(mFooterViewHeight, MeasureSpec.EXACTLY)); + if (!mUsingCustomStart && !mOriginalOffsetCalculated) { + mOriginalOffsetCalculated = true; + mCurrentTargetOffsetTop = mOriginalOffsetTop = -mHeadViewContainer + .getMeasuredHeight(); + updateListenerCallBack(); + } + mHeaderViewIndex = -1; + for (int index = 0; index < getChildCount(); index++) { + if (getChildAt(index) == mHeadViewContainer) { + mHeaderViewIndex = index; + break; + } + } + mFooterViewIndex = -1; + for (int index = 0; index < getChildCount(); index++) { + if (getChildAt(index) == mFooterViewContainer) { + mFooterViewIndex = index; + break; + } + } + } + + /** + * 判断目标View是否滑动到顶部-还能否继续滑动 + * + * @return + */ + public boolean isChildScrollToTop() { + if (Build.VERSION.SDK_INT < 14) { + if (mTarget instanceof AbsListView) { + final AbsListView absListView = (AbsListView) mTarget; + return !(absListView.getChildCount() > 0 && (absListView + .getFirstVisiblePosition() > 0 || absListView + .getChildAt(0).getTop() < absListView.getPaddingTop())); + } else { + return !(mTarget.getScrollY() > 0); + } + } else { + return !ViewCompat.canScrollVertically(mTarget, -1); + } + } + + /** + * 是否滑动到底部 + * + * @return + */ + public boolean isChildScrollToBottom() { + if (isChildScrollToTop()) { + return false; + } + if (mTarget instanceof RecyclerView) { + RecyclerView recyclerView = (RecyclerView) mTarget; + LayoutManager layoutManager = recyclerView.getLayoutManager(); + int count = recyclerView.getAdapter().getItemCount(); + if (layoutManager instanceof LinearLayoutManager && count > 0) { + LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; + if (linearLayoutManager.findLastCompletelyVisibleItemPosition() == count - 1) { + return true; + } + } else if (layoutManager instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager; + int[] lastItems = new int[2]; + staggeredGridLayoutManager + .findLastCompletelyVisibleItemPositions(lastItems); + int lastItem = Math.max(lastItems[0], lastItems[1]); + if (lastItem == count - 1) { + return true; + } + } + return false; + } else if (mTarget instanceof AbsListView) { + final AbsListView absListView = (AbsListView) mTarget; + int count = absListView.getAdapter().getCount(); + int fristPos = absListView.getFirstVisiblePosition(); + if (fristPos == 0 + && absListView.getChildAt(0).getTop() >= absListView + .getPaddingTop()) { + return false; + } + int lastPos = absListView.getLastVisiblePosition(); + if (lastPos > 0 && count > 0 && lastPos == count - 1) { + return true; + } + return false; + } else if (mTarget instanceof ScrollView) { + ScrollView scrollView = (ScrollView) mTarget; + View view = (View) scrollView + .getChildAt(scrollView.getChildCount() - 1); + if (view != null) { + int diff = (view.getBottom() - (scrollView.getHeight() + scrollView + .getScrollY())); + if (diff == 0) { + return true; + } + } + } + return false; + } + + /** + * 主要判断是否应该拦截子View的事件
+ * 如果拦截,则交给自己的OnTouchEvent处理
+ * 否者,交给子View处理
+ */ + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + ensureTarget(); + + final int action = MotionEventCompat.getActionMasked(ev); + + if (mReturningToStart && action == MotionEvent.ACTION_DOWN) { + mReturningToStart = false; + } + if (!isEnabled() || mReturningToStart || mRefreshing || mLoadMore + || (!isChildScrollToTop() && !isChildScrollToBottom())) { + // 如果子View可以滑动,不拦截事件,交给子View处理-下拉刷新 + // 或者子View没有滑动到底部不拦截事件-上拉加载更多 + return false; + } + + // 下拉刷新判断 + switch (action) { + case MotionEvent.ACTION_DOWN: + //手指按下,就会恢复HeaderView的初始位置 + setTargetOffsetTopAndBottom( + mOriginalOffsetTop - mHeadViewContainer.getTop(), true); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + mIsBeingDragged = false; + final float initialMotionY = getMotionEventY(ev, mActivePointerId); + if (initialMotionY == -1) { + return false; + } + mInitialMotionY = initialMotionY;// 记录按下的位置 + + case MotionEvent.ACTION_MOVE: + if (mActivePointerId == INVALID_POINTER) { + Log.e(LOG_TAG, + "Got ACTION_MOVE event but don't have an active pointer id."); + return false; + } + + final float y = getMotionEventY(ev, mActivePointerId); + if (y == -1) { + return false; + } + float yDiff = 0; + if (isChildScrollToBottom() && parentAllowPullUp()) { + yDiff = mInitialMotionY - y;// 计算上拉距离 + if (yDiff > mTouchSlop && !mIsBeingDragged && pullUpEnable) {// 判断是否下拉的距离足够 + mIsBeingDragged = true;// 正在上拉 + requestParentDisallowInterceptTouchEvent(true); + } + } else { + + //这是一个比较蠢的做法,如果scrollerview能滚,就不阻拦 + +// MyScrollView scrollView = (MyScrollView) getParent().getParent().getParent().getParent(); + + +// if(scrollView.getScrollY()>0){ +// +// }else{ +// +// } + + yDiff = y - mInitialMotionY;// 计算下拉距离 + if (yDiff > mTouchSlop && !mIsBeingDragged && pullDownEnable) {// 判断是否下拉的距离足够 + mIsBeingDragged = true;// 正在下拉 + requestParentDisallowInterceptTouchEvent(true); + } + + } + break; + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mIsBeingDragged = false; + mActivePointerId = INVALID_POINTER; + break; + } + +// return false; + return mIsBeingDragged;// 如果正在拖动,则拦截子View的事件 + } + + protected boolean parentAllowPullUp() { + return true; + } + + private float getMotionEventY(MotionEvent ev, int activePointerId) { + final int index = MotionEventCompat.findPointerIndex(ev, + activePointerId); + if (index < 0) { + return -1; + } + return MotionEventCompat.getY(ev, index); + } + +// @Override +// public void requestDisallowInterceptTouchEvent(boolean b) { +// // Nope. +// } + + @Override + public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { + // Nope. + + if (requestDisallowInterceptTouchEvent) { + super.requestDisallowInterceptTouchEvent(disallowIntercept); + } + + } + + boolean requestDisallowInterceptTouchEvent = true; + + public void realRequestDisallowInterceptTouchEvent(boolean b) { + super.requestDisallowInterceptTouchEvent(b); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + final int action = MotionEventCompat.getActionMasked(ev); + + if (mReturningToStart && action == MotionEvent.ACTION_DOWN) { + mReturningToStart = false; + } + if (!isEnabled() || mReturningToStart + || (!isChildScrollToTop() && !isChildScrollToBottom())) { + // 如果子View可以滑动,不拦截事件,交给子View处理 + return false; + } + + if (isChildScrollToBottom()) { + // 上拉加载更多 + return handlerPushTouchEvent(ev, action); + } else { + // 下拉刷新 + return handlerPullTouchEvent(ev, action); + } + } + + private boolean requestParentDisallowInterceptTouchEvent = true; + + //处理下拉刷新 + private boolean handlerPullTouchEvent(MotionEvent ev, int action) { + switch (action) { + case MotionEvent.ACTION_DOWN: + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + mIsBeingDragged = false; + break; + + case MotionEvent.ACTION_MOVE: { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, + mActivePointerId); + if (pointerIndex < 0) { + Log.e(LOG_TAG, + "Got ACTION_MOVE event but have an invalid active pointer id."); + return false; + } + + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE; + if (mIsBeingDragged) { +// if (requestParentDisallowInterceptTouchEvent) { +// requestParentDisallowInterceptTouchEvent(true); +// } + + + float originalDragPercent = overscrollTop / mTotalDragDistance; + if (originalDragPercent < 0) { + return false; + } + float dragPercent = Math.min(1f, Math.abs(originalDragPercent)); + float extraOS = Math.abs(overscrollTop) - mTotalDragDistance; + float slingshotDist = mUsingCustomStart ? mSpinnerFinalOffset + - mOriginalOffsetTop : mSpinnerFinalOffset; + float tensionSlingshotPercent = Math.max(0, + Math.min(extraOS, slingshotDist * 2) / slingshotDist); + float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math + .pow((tensionSlingshotPercent / 4), 2)) * 2f; + float extraMove = (slingshotDist) * tensionPercent * 2; + + int targetY = mOriginalOffsetTop + + (int) ((slingshotDist * dragPercent) + extraMove); + if (mHeadViewContainer.getVisibility() != View.VISIBLE) { + mHeadViewContainer.setVisibility(View.VISIBLE); + } + if (!mScale) { + ViewCompat.setScaleX(mHeadViewContainer, 1f); + ViewCompat.setScaleY(mHeadViewContainer, 1f); + } + if (usingDefaultHeader) { + float alpha = overscrollTop / mTotalDragDistance; + if (alpha >= 1.0f) { + alpha = 1.0f; + } + ViewCompat.setScaleX(defaultProgressView, alpha); + ViewCompat.setScaleY(defaultProgressView, alpha); + ViewCompat.setAlpha(defaultProgressView, alpha); + } + if (overscrollTop < mTotalDragDistance) { + if (mScale) { + setAnimationProgress(overscrollTop / mTotalDragDistance); + } + if (mListener != null) { + mListener.onPullEnable(false); + } + } else { + if (mListener != null) { + mListener.onPullEnable(true); + } + } + setTargetOffsetTopAndBottom(targetY - mCurrentTargetOffsetTop, + true); + } + break; + } + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: { + if (mActivePointerId == INVALID_POINTER) { + if (action == MotionEvent.ACTION_UP) { + Log.e(LOG_TAG, + "Got ACTION_UP event but don't have an active pointer id."); + } + return false; + } + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, + mActivePointerId); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE; + mIsBeingDragged = false; + if (overscrollTop > mTotalDragDistance) { + setRefreshing(true, true /* notify */); + } else { + mRefreshing = false; + AnimationListener listener = null; + if (!mScale) { + listener = new AnimationListener() { + + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + if (!mScale) { + startScaleDownAnimation(null); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + }; + } + animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener); + } + mActivePointerId = INVALID_POINTER; + return false; + } + } + + return true; + } + + private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) { + Log.i(LOG_TAG, "requestParentDisallowInterceptTouchEvent"); + final ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(disallowIntercept); + } + } + + /** + * 处理上拉加载更多的Touch事件 + * + * @param ev + * @param action + * @return + */ + private boolean handlerPushTouchEvent(MotionEvent ev, int action) { + switch (action) { + case MotionEvent.ACTION_DOWN: + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + mIsBeingDragged = false; + Log.d(LOG_TAG, "debug:onTouchEvent ACTION_DOWN"); + break; + case MotionEvent.ACTION_MOVE: { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, + mActivePointerId); + if (pointerIndex < 0) { + Log.e(LOG_TAG, + "Got ACTION_MOVE event but have an invalid active pointer id."); + return false; + } + + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float overscrollBottom = (mInitialMotionY - y) * DRAG_RATE; + if (mIsBeingDragged) { +// if (requestParentDisallowInterceptTouchEvent) { +// requestParentDisallowInterceptTouchEvent(true); +// } + + pushDistance = (int) overscrollBottom; + updateFooterViewPosition(); + if (mOnPushLoadMoreListener != null) { + mOnPushLoadMoreListener + .onPushEnable(pushDistance >= mFooterViewHeight); + } + + + } + break; + } + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: { + if (mActivePointerId == INVALID_POINTER) { + if (action == MotionEvent.ACTION_UP) { + Log.e(LOG_TAG, + "Got ACTION_UP event but don't have an active pointer id."); + } + return false; + } + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, + mActivePointerId); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float overscrollBottom = (mInitialMotionY - y) * DRAG_RATE;// 松手是下拉的距离 + mIsBeingDragged = false; + mActivePointerId = INVALID_POINTER; + if (overscrollBottom < mFooterViewHeight + || mOnPushLoadMoreListener == null) {// 直接取消 + pushDistance = 0; + } else {// 下拉到mFooterViewHeight + pushDistance = mFooterViewHeight; + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + updateFooterViewPosition(); + if (pushDistance == mFooterViewHeight + && mOnPushLoadMoreListener != null) { + mLoadMore = true; + mOnPushLoadMoreListener.onLoadMore(); + } + } else { + animatorFooterToBottom((int) overscrollBottom, pushDistance); + } + return false; + } + } + return true; + } + + /** + * 松手之后,使用动画将Footer从距离start变化到end + * + * @param start + * @param end + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void animatorFooterToBottom(int start, final int end) { + ValueAnimator valueAnimator = ValueAnimator.ofInt(start, end); + valueAnimator.setDuration(150); + valueAnimator.addUpdateListener(new AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + // update + pushDistance = (Integer) valueAnimator.getAnimatedValue(); + updateFooterViewPosition(); + } + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (end > 0 && mOnPushLoadMoreListener != null) { + // start loading more + mLoadMore = true; + mOnPushLoadMoreListener.onLoadMore(); + } else { + resetTargetLayout(); + mLoadMore = false; + } + } + }); + valueAnimator.setInterpolator(mDecelerateInterpolator); + valueAnimator.start(); + } + + /** + * 设置停止加载 + * + * @param loadMore + */ + public void setLoadMore(boolean loadMore) { + if (!loadMore && mLoadMore) {// 停止加载 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + mLoadMore = false; + pushDistance = 0; + updateFooterViewPosition(); + } else { + animatorFooterToBottom(mFooterViewHeight, 0); + } + } + } + + /** + * 停止加载,别用setLoadMore和setRefreshing了,麻烦,过段时间我会只开这个口 + */ + public void stopLoading() { + if (mLoadMore) { + //正在加载更多 + setLoadMore(false); + } else if (mRefreshing) { + //正在刷新 + setRefreshing(false); + } + } + + private void animateOffsetToCorrectPosition(int from, + AnimationListener listener) { + mFrom = from; + mAnimateToCorrectPosition.reset(); + mAnimateToCorrectPosition.setDuration(ANIMATE_TO_TRIGGER_DURATION); + mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator); + if (listener != null) { + mHeadViewContainer.setAnimationListener(listener); + } + mHeadViewContainer.clearAnimation(); + mHeadViewContainer.startAnimation(mAnimateToCorrectPosition); + } + + private void animateOffsetToStartPosition(int from, + AnimationListener listener) { + if (mScale) { + startScaleDownReturnToStartAnimation(from, listener); + } else { + mFrom = from; + mAnimateToStartPosition.reset(); + mAnimateToStartPosition.setDuration(ANIMATE_TO_START_DURATION); + mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator); + if (listener != null) { + mHeadViewContainer.setAnimationListener(listener); + } + mHeadViewContainer.clearAnimation(); + mHeadViewContainer.startAnimation(mAnimateToStartPosition); + } + resetTargetLayoutDelay(ANIMATE_TO_START_DURATION); + } + + /** + * 重置Target位置 + * + * @param delay + */ + public void resetTargetLayoutDelay(int delay) { + new Handler().postDelayed(new Runnable() { + + @Override + public void run() { + resetTargetLayout(); + } + }, delay); + } + + /** + * 重置Target的位置 + */ + public void resetTargetLayout() { + final int width = getMeasuredWidth(); + final int height = getMeasuredHeight(); + final View child = mTarget; + final int childLeft = getPaddingLeft(); + final int childTop = getPaddingTop(); + final int childWidth = child.getWidth() - getPaddingLeft() + - getPaddingRight(); + final int childHeight = child.getHeight() - getPaddingTop() + - getPaddingBottom(); + child.layout(childLeft, childTop, childLeft + childWidth, childTop + + childHeight); + + int headViewWidth = mHeadViewContainer.getMeasuredWidth(); + int headViewHeight = mHeadViewContainer.getMeasuredHeight(); + mHeadViewContainer.layout((width / 2 - headViewWidth / 2), + -headViewHeight, (width / 2 + headViewWidth / 2), 0);// 更新头布局的位置 + int footViewWidth = mFooterViewContainer.getMeasuredWidth(); + int footViewHeight = mFooterViewContainer.getMeasuredHeight(); + mFooterViewContainer.layout((width / 2 - footViewWidth / 2), height, + (width / 2 + footViewWidth / 2), height + footViewHeight); + } + + private final Animation mAnimateToCorrectPosition = new Animation() { + @Override + public void applyTransformation(float interpolatedTime, Transformation t) { + int targetTop = 0; + int endTarget = 0; + if (!mUsingCustomStart) { + endTarget = (int) (mSpinnerFinalOffset - Math + .abs(mOriginalOffsetTop)); + } else { + endTarget = (int) mSpinnerFinalOffset; + } + targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime)); + int offset = targetTop - mHeadViewContainer.getTop(); + setTargetOffsetTopAndBottom(offset, false /* requires update */); + } + + @Override + public void setAnimationListener(AnimationListener listener) { + super.setAnimationListener(listener); + } + }; + + private void moveToStart(float interpolatedTime) { + int targetTop = 0; + targetTop = (mFrom + (int) ((mOriginalOffsetTop - mFrom) * interpolatedTime)); + int offset = targetTop - mHeadViewContainer.getTop(); + setTargetOffsetTopAndBottom(offset, false /* requires update */); + } + + private final Animation mAnimateToStartPosition = new Animation() { + @Override + public void applyTransformation(float interpolatedTime, Transformation t) { + moveToStart(interpolatedTime); + } + }; + + private void startScaleDownReturnToStartAnimation(int from, + AnimationListener listener) { + mFrom = from; + mStartingScale = ViewCompat.getScaleX(mHeadViewContainer); + mScaleDownToStartAnimation = new Animation() { + @Override + public void applyTransformation(float interpolatedTime, + Transformation t) { + float targetScale = (mStartingScale + (-mStartingScale * interpolatedTime)); + setAnimationProgress(targetScale); + moveToStart(interpolatedTime); + } + }; + mScaleDownToStartAnimation.setDuration(SCALE_DOWN_DURATION); + if (listener != null) { + mHeadViewContainer.setAnimationListener(listener); + } + mHeadViewContainer.clearAnimation(); + mHeadViewContainer.startAnimation(mScaleDownToStartAnimation); + } + + private void setTargetOffsetTopAndBottom(int offset, boolean requiresUpdate) { + mHeadViewContainer.bringToFront(); + mHeadViewContainer.offsetTopAndBottom(offset); + mCurrentTargetOffsetTop = mHeadViewContainer.getTop(); + if (requiresUpdate && Build.VERSION.SDK_INT < 11) { + invalidate(); + } + if (targetScrollWithLayout) { + ensureTarget(); + mTarget.offsetTopAndBottom(offset); + } + updateListenerCallBack(); + } + + /** + * 修改底部布局的位置-敏感pushDistance + */ + private void updateFooterViewPosition() { + mFooterViewContainer.setVisibility(View.VISIBLE); + mFooterViewContainer.bringToFront(); + //针对4.4及之前版本的兼容 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + mFooterViewContainer.getParent().requestLayout(); + } + mFooterViewContainer.offsetTopAndBottom(-pushDistance); + updatePushDistanceListener(); + } + + private void updatePushDistanceListener() { + if (mOnPushLoadMoreListener != null) { + mOnPushLoadMoreListener.onPushDistance(pushDistance); + } + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mActivePointerId = MotionEventCompat.getPointerId(ev, + newPointerIndex); + } + } + + /** + * @Description 下拉刷新布局头部的容器 + */ + private class HeadViewContainer extends RelativeLayout { + + private AnimationListener mListener; + + public HeadViewContainer(Context context) { + super(context); + } + + public void setAnimationListener(AnimationListener listener) { + mListener = listener; + } + + @Override + public void onAnimationStart() { + super.onAnimationStart(); + if (mListener != null) { + mListener.onAnimationStart(getAnimation()); + } + } + + @Override + public void onAnimationEnd() { + super.onAnimationEnd(); + if (mListener != null) { + mListener.onAnimationEnd(getAnimation()); + } + } + } + + /** + * 判断子View是否跟随手指的滑动而滑动,默认跟随 + * + * @return + */ + public boolean isTargetScrollWithLayout() { + return targetScrollWithLayout; + } + + /** + * 设置子View是否跟谁手指的滑动而滑动 + * + * @param targetScrollWithLayout + */ + public void setTargetScrollWithLayout(boolean targetScrollWithLayout) { + this.targetScrollWithLayout = targetScrollWithLayout; + } + + /** + * 下拉刷新回调 + */ + public interface OnPullRefreshListener { + public void onRefresh(); + + public void onPullDistance(int distance); + + public void onPullEnable(boolean enable); + } + + /** + * 上拉加载更多 + */ + public interface OnPushLoadMoreListener { + public void onLoadMore(); + + public void onPushDistance(int distance); + + public void onPushEnable(boolean enable); + } + + /** + * Adapter + */ + public class OnPullRefreshListenerAdapter implements OnPullRefreshListener { + + @Override + public void onRefresh() { + + } + + @Override + public void onPullDistance(int distance) { + + } + + @Override + public void onPullEnable(boolean enable) { + + } + + } + + public class OnPushLoadMoreListenerAdapter implements + OnPushLoadMoreListener { + + @Override + public void onLoadMore() { + + } + + @Override + public void onPushDistance(int distance) { + + } + + @Override + public void onPushEnable(boolean enable) { + + } + + } + + /** + * 设置默认下拉刷新进度条的颜色 + * + * @param color + */ + public void setDefaultCircleProgressColor(int color) { + if (usingDefaultHeader) { + defaultProgressView.setProgressColor(color); + } + } + + /** + * 设置圆圈的背景色 + * + * @param color + */ + public void setDefaultCircleBackgroundColor(int color) { + if (usingDefaultHeader) { + defaultProgressView.setCircleBackgroundColor(color); + } + } + + public void setDefaultCircleShadowColor(int color) { + if (usingDefaultHeader) { + defaultProgressView.setShadowColor(color); + } + } + + /** + * 默认的下拉刷新样式 + */ + public class CircleProgressView extends View implements Runnable { + + private static final int PEROID = 16;// 绘制周期 + private Paint progressPaint; + private Paint bgPaint; + private int width;// view的高度 + private int height;// view的宽度 + + private boolean isOnDraw = false; + private boolean isRunning = false; + private int startAngle = 0; + private int speed = 8; + private RectF ovalRect = null; + private RectF bgRect = null; + private int swipeAngle; + private int progressColor = 0xffcccccc; + private int circleBackgroundColor = 0xffffffff; + private int shadowColor = 0xff999999; + + public CircleProgressView(Context context) { + super(context); + } + + public CircleProgressView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CircleProgressView(Context context, AttributeSet attrs, + int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawArc(getBgRect(), 0, 360, false, createBgPaint()); + int index = startAngle / 360; + if (index % 2 == 0) { + swipeAngle = (startAngle % 720) / 2; + } else { + swipeAngle = 360 - (startAngle % 720) / 2; + } + canvas.drawArc(getOvalRect(), startAngle, swipeAngle, false, + createPaint()); + } + + private RectF getBgRect() { + width = getWidth(); + height = getHeight(); + if (bgRect == null) { + int offset = (int) (density * 2); + bgRect = new RectF(offset, offset, width - offset, height + - offset); + } + return bgRect; + } + + private RectF getOvalRect() { + width = getWidth(); + height = getHeight(); + if (ovalRect == null) { + int offset = (int) (density * 8); + ovalRect = new RectF(offset, offset, width - offset, height + - offset); + } + return ovalRect; + } + + public void setProgressColor(int progressColor) { + this.progressColor = progressColor; + } + + public void setCircleBackgroundColor(int circleBackgroundColor) { + this.circleBackgroundColor = circleBackgroundColor; + } + + public void setShadowColor(int shadowColor) { + this.shadowColor = shadowColor; + } + + /** + * 根据画笔的颜色,创建画笔 + * + * @return + */ + private Paint createPaint() { + if (this.progressPaint == null) { + progressPaint = new Paint(); + progressPaint.setStrokeWidth((int) (density * 3)); + progressPaint.setStyle(Paint.Style.STROKE); + progressPaint.setAntiAlias(true); + } + progressPaint.setColor(progressColor); + return progressPaint; + } + + private Paint createBgPaint() { + if (this.bgPaint == null) { + bgPaint = new Paint(); + bgPaint.setColor(circleBackgroundColor); + bgPaint.setStyle(Paint.Style.FILL); + bgPaint.setAntiAlias(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + this.setLayerType(LAYER_TYPE_SOFTWARE, bgPaint); + } + bgPaint.setShadowLayer(4.0f, 0.0f, 2.0f, shadowColor); + } + return bgPaint; + } + + public void setPullDistance(int distance) { + this.startAngle = distance * 2; + postInvalidate(); + } + + @Override + public void run() { + while (isOnDraw) { + isRunning = true; + long startTime = System.currentTimeMillis(); + startAngle += speed; + postInvalidate(); + long time = System.currentTimeMillis() - startTime; + if (time < PEROID) { + try { + Thread.sleep(PEROID - time); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void setOnDraw(boolean isOnDraw) { + this.isOnDraw = isOnDraw; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + public boolean isRunning() { + return isRunning; + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + } + + @Override + protected void onDetachedFromWindow() { + isOnDraw = false; + super.onDetachedFromWindow(); + } + + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseFetchLoadAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseFetchLoadAdapter.java new file mode 100644 index 0000000..2e3374e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseFetchLoadAdapter.java @@ -0,0 +1,993 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +import android.animation.Animator; +import android.content.Context; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; + +import androidx.annotation.IntDef; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.LayoutParams; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.AlphaInAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.BaseAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.ScaleInAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.SlideInBottomAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.SlideInLeftAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.SlideInRightAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore.LoadMoreView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore.SimpleLoadMoreView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.util.RecyclerViewUtil; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + +public abstract class BaseFetchLoadAdapter extends RecyclerView.Adapter implements IRecyclerView { + + private static final String TAG = BaseFetchLoadAdapter.class.getSimpleName(); + + // fetch more + public interface RequestFetchMoreListener { + void onFetchMoreRequested(); + } + + protected RecyclerView mRecyclerView; + + private boolean mFetching = false; + private boolean mFetchMoreEnable = false; + private boolean mNextFetchEnable = false; + private boolean mFirstFetchSuccess = true; + private int mAutoFetchMoreSize = 1; // 距离顶部多少条就开始拉取数据了 + private RequestFetchMoreListener mRequestFetchMoreListener; + private LoadMoreView mFetchMoreView = new SimpleLoadMoreView(); + + //load more + public interface RequestLoadMoreListener { + void onLoadMoreRequested(); + } + + private boolean mLoading = false; + private boolean mNextLoadEnable = false; + private boolean mLoadMoreEnable = false; + private boolean mFirstLoadSuccess = true; + private int mAutoLoadMoreSize = 1; // 距离底部多少条就开始加载数据了 + private RequestLoadMoreListener mRequestLoadMoreListener; + private LoadMoreView mLoadMoreView = new SimpleLoadMoreView(); + + // animation + private boolean mAnimationShowFirstOnly = true; + private boolean mOpenAnimationEnable = false; + private Interpolator mInterpolator = new LinearInterpolator(); + private int mAnimationDuration = 200; + private int mLastPosition = -1; + + // @AnimationType + private BaseAnimation mCustomAnimation; + private BaseAnimation mSelectAnimation = new AlphaInAnimation(); + + // empty + private FrameLayout mEmptyView; + private boolean mIsUseEmpty = true; + + // basic + protected Context mContext; + protected int mLayoutResId; + protected LayoutInflater mLayoutInflater; + protected List mData; + private boolean isScrolling = false; + + /** + * Implement this method and use the helper to adapt the view to the given item. + * + * @param helper A fully initialized helper. + * @param item the item that needs to be displayed. + * @param position the item position + * @param isScrolling RecyclerView is scrolling + */ + protected abstract void convert(K helper, T item, int position, boolean isScrolling); + + + @IntDef({ALPHAIN, SCALEIN, SLIDEIN_BOTTOM, SLIDEIN_LEFT, SLIDEIN_RIGHT}) + @Retention(RetentionPolicy.SOURCE) + public @interface AnimationType { + } + + /** + * Use with {@link #openLoadAnimation} + */ + public static final int ALPHAIN = 0x00000001; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SCALEIN = 0x00000002; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SLIDEIN_BOTTOM = 0x00000003; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SLIDEIN_LEFT = 0x00000004; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SLIDEIN_RIGHT = 0x00000005; + + + /** + * Same as QuickAdapter#QuickAdapter(Context,int) but with + * some initialization data. + * + * @param layoutResId The layout resource id of each item. + * @param data A new list is created out of this one to avoid mutable list + */ + public BaseFetchLoadAdapter(RecyclerView recyclerView, int layoutResId, List data) { + this.mRecyclerView = recyclerView; + this.mData = data == null ? new ArrayList() : data; + if (layoutResId != 0) { + this.mLayoutResId = layoutResId; + } + + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + isScrolling = newState != RecyclerView.SCROLL_STATE_IDLE; + } + }); + + /** + * 关闭默认viewholder item动画 + */ + RecyclerViewUtil.changeItemAnimation(recyclerView, false); + } + + @Override + public int getHeaderLayoutCount() { + return getFetchMoreViewCount(); + } + + /** + * *********************************** fetch more 顶部下拉加载 *********************************** + */ + + public void setOnFetchMoreListener(RequestFetchMoreListener requestFetchMoreListener) { + this.mRequestFetchMoreListener = requestFetchMoreListener; + mNextFetchEnable = true; + mFetchMoreEnable = true; + mFetching = false; + } + + public void setAutoFetchMoreSize(int autoFetchMoreSize) { + if (autoFetchMoreSize > 1) { + mAutoFetchMoreSize = autoFetchMoreSize; + } + } + + public void setFetchMoreView(LoadMoreView fetchMoreView) { + this.mFetchMoreView = fetchMoreView; // 自定义View + } + + private int getFetchMoreViewCount() { + if (mRequestFetchMoreListener == null || !mFetchMoreEnable) { + return 0; + } + if (!mNextFetchEnable && mFetchMoreView.isLoadEndMoreGone()) { + return 0; + } + + return 1; + } + + /** + * 列表滑动时自动拉取数据 + * + * @param position + */ + private void autoRequestFetchMoreData(int position) { + if (getFetchMoreViewCount() == 0) { + return; + } + + if (position > mAutoFetchMoreSize - 1) { + return; + } + + if (mFetchMoreView.getLoadMoreStatus() != LoadMoreView.STATUS_DEFAULT) { + return; + } + + if (mData.size() == 0 && mFirstFetchSuccess) { + return; // 都还没有数据,不自动触发加载,等外部塞入数据后再加载 + } + + Log.d(TAG, "auto fetch, pos=" + position); + + mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_LOADING); + if (!mFetching) { + mFetching = true; + mRequestFetchMoreListener.onFetchMoreRequested(); + } + } + + /** + * fetch complete + */ + public void fetchMoreComplete(final List newData) { + addFrontData(newData); // notifyItemRangeInserted从顶部向下加入View,顶部View并没有改变 + + if (getFetchMoreViewCount() == 0) { + return; + } + + fetchMoreComplete(newData.size()); + } + + public void fetchMoreComplete(int newDataSize) { + if (getFetchMoreViewCount() == 0) { + return; + } + + mFetching = false; + mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemChanged(0); + + // 定位到insert新消息前的top消息位置。必须移动,否则还在顶部,会继续fetch!!! + if (mRecyclerView != null) { + RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager(); + // 只有LinearLayoutManager才有查找第一个和最后一个可见view位置的方法 + if (layoutManager instanceof LinearLayoutManager) { + LinearLayoutManager linearManager = (LinearLayoutManager) layoutManager; + //获取第一个可见view的位置 + int firstItemPosition = linearManager.findFirstVisibleItemPosition(); + if (firstItemPosition == 0) { + // 最顶部可见的View已经是FetchMoreView了,那么add数据&局部刷新后,要进行定位到上次的最顶部消息。 + mRecyclerView.scrollToPosition(newDataSize + getFetchMoreViewCount()); + } + } else { + mRecyclerView.scrollToPosition(newDataSize); + } + } + } + + /** + * fetch end, no more data + * + * @param data last load data to add + * @param gone if true gone the fetch more view + */ + public void fetchMoreEnd(List data, boolean gone) { + addFrontData(data); + + if (getFetchMoreViewCount() == 0) { + return; + } + mFetching = false; + mNextFetchEnable = false; + mFetchMoreView.setLoadMoreEndGone(gone); + if (gone) { + notifyItemRemoved(0); + } else { + mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_END); + notifyItemChanged(0); + } + } + + /** + * fetch failed + */ + public void fetchMoreFailed() { + if (getFetchMoreViewCount() == 0) { + return; + } + mFetching = false; + if (mData.size() == 0) { + mFirstFetchSuccess = false; // 首次加载失败 + } + mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_FAIL); + + notifyItemChanged(0); + } + + /** + * *********************************** load more 底部上拉加载 *********************************** + */ + + public void setLoadMoreView(LoadMoreView loadingView) { + this.mLoadMoreView = loadingView; // 自定义View + } + + public void setOnLoadMoreListener(RequestLoadMoreListener requestLoadMoreListener) { + this.mRequestLoadMoreListener = requestLoadMoreListener; + mNextLoadEnable = true; + mLoadMoreEnable = true; + mLoading = false; + } + + public void setAutoLoadMoreSize(int autoLoadMoreSize) { + if (autoLoadMoreSize > 1) { + mAutoLoadMoreSize = autoLoadMoreSize; + } + } + + private int getLoadMoreViewCount() { + if (mRequestLoadMoreListener == null || !mLoadMoreEnable) { + return 0; + } + if (!mNextLoadEnable && mLoadMoreView.isLoadEndMoreGone()) { + return 0; + } + if (mData.size() == 0) { + return 0; + } + return 1; + } + + /** + * 列表滑动时自动加载数据 + * + * @param position + */ + private void autoRequestLoadMoreData(int position) { + if (getLoadMoreViewCount() == 0) { + return; + } + + if (position < getItemCount() - mAutoLoadMoreSize) { + return; + } + + if (mLoadMoreView.getLoadMoreStatus() != LoadMoreView.STATUS_DEFAULT) { + return; + } + + if (mData.size() == 0 && mFirstLoadSuccess) { + return; // 都还没有数据,不自动触发加载,等外部塞入数据后再加载 + } + + Log.d(TAG, "auto load, pos=" + position); + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_LOADING); + if (!mLoading) { + mLoading = true; + mRequestLoadMoreListener.onLoadMoreRequested(); + } + } + + /** + * load complete + */ + public void loadMoreComplete(final List newData) { + appendData(newData); + + loadMoreComplete(); + } + + public void loadMoreComplete() { + if (getLoadMoreViewCount() == 0) { + return; + } + mLoading = false; + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemChanged(getFetchMoreViewCount() + mData.size()); + } + + /** + * load end, no more data + * + * @param data last data to append + * @param gone if true gone the load more view + */ + public void loadMoreEnd(List data, boolean gone) { + appendData(data); + + if (getLoadMoreViewCount() == 0) { + return; + } + mLoading = false; + mNextLoadEnable = false; + mLoadMoreView.setLoadMoreEndGone(gone); + if (gone) { + notifyItemRemoved(getFetchMoreViewCount() + mData.size()); + } else { + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_END); + notifyItemChanged(getFetchMoreViewCount() + mData.size()); + } + } + + /** + * load failed + */ + public void loadMoreFail() { + if (getLoadMoreViewCount() == 0) { + return; + } + mLoading = false; + if (mData.size() == 0) { + mFirstLoadSuccess = false; // 首次加载失败 + } + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_FAIL); + notifyItemChanged(getFetchMoreViewCount() + mData.size()); + } + + + /** + * Set the enabled state of load more. + * + * @param enable True if load more is enabled, false otherwise. + */ + public void setEnableLoadMore(boolean enable) { + int oldLoadMoreCount = getLoadMoreViewCount(); + mLoadMoreEnable = enable; + int newLoadMoreCount = getLoadMoreViewCount(); + + if (oldLoadMoreCount == 1) { + if (newLoadMoreCount == 0) { + notifyItemRemoved(getFetchMoreViewCount() + mData.size()); + } + } else { + if (newLoadMoreCount == 1) { + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemInserted(getFetchMoreViewCount() + mData.size()); + } + } + } + + /** + * Returns the enabled status for load more. + * + * @return True if load more is enabled, false otherwise. + */ + public boolean isLoadMoreEnable() { + return mLoadMoreEnable; + } + + /** + * *********************************** 数据源管理 *********************************** + */ + + /** + * setting up a new instance to data; + * + * @param data + */ + public void setNewData(List data) { + this.mData = data == null ? new ArrayList() : data; + if (mRequestLoadMoreListener != null) { + mNextLoadEnable = true; + mLoadMoreEnable = true; + mLoading = false; + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + } + if (mRequestFetchMoreListener != null) { + mNextFetchEnable = true; + mFetchMoreEnable = true; + mFetching = false; + mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + } + + mLastPosition = -1; + notifyDataSetChanged(); + } + + /** + * clear data before reload + */ + public void clearData() { + this.mData.clear(); + if (mRequestLoadMoreListener != null) { + mNextLoadEnable = true; + mLoading = false; + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + } + if (mRequestFetchMoreListener != null) { + mNextFetchEnable = true; + mFetching = false; + mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + } + + mLastPosition = -1; + notifyDataSetChanged(); + } + + /** + * insert a item associated with the specified position of adapter + * + * @param position + * @param item + */ + public void add(int position, T item) { + mData.add(position, item); + notifyItemInserted(position + getFetchMoreViewCount()); + } + + /** + * add new data in to certain location + * + * @param position + */ + public void addData(int position, List data) { + if (0 <= position && position < mData.size()) { + mData.addAll(position, data); + notifyItemRangeInserted(getFetchMoreViewCount() + position, data.size()); + } else { + throw new ArrayIndexOutOfBoundsException("inserted position most greater than 0 and less than data size"); + } + } + + /** + * remove the item associated with the specified position of adapter + * + * @param position + */ + public void remove(int position) { + final T item = mData.get(position); + mData.remove(position); + notifyItemRemoved(position + getHeaderLayoutCount()); + onRemove(item); + } + + protected void onRemove(T item) { + + } + + /** + * add new data to head location + */ + public void addFrontData(List data) { + if (data == null || data.isEmpty()) { + return; + } + + mData.addAll(0, data); + notifyItemRangeInserted(getFetchMoreViewCount(), data.size()); // add到FetchMoreView之下,保持FetchMoreView在顶部 + } + + /** + * additional data; + * + * @param newData + */ + public void appendData(List newData) { + if (newData == null || newData.isEmpty()) { + return; + } + + this.mData.addAll(newData); + notifyItemRangeInserted(mData.size() - newData.size() + getFetchMoreViewCount(), newData.size()); + } + + public void appendData(T newData) { + List data = new ArrayList<>(1); + data.add(newData); + appendData(data); + } + + /** + * Get the data of list + * + * @return + */ + public List getData() { + return mData; + } + + /** + * Get the data item associated with the specified position in the data set. + * + * @param position Position of the item whose data we want within the adapter's + * data set. + * @return The data at the specified position. + */ + public T getItem(int position) { + return mData.get(position); + } + + public int getDataSize() { + return mData == null ? 0 : mData.size(); + } + + public int getBottomDataPosition() { + return getHeaderLayoutCount() + mData.size() - 1; + } + + public void notifyDataItemChanged(int dataIndex) { + notifyItemChanged(getHeaderLayoutCount() + dataIndex); + } + + /** + * *********************************** ViewHolder/ViewType *********************************** + */ + + @Override + public int getItemCount() { + int count; + if (getEmptyViewCount() == 1) { + count = 1; + } else { + count = getFetchMoreViewCount() + mData.size() + getLoadMoreViewCount(); + } + return count; + } + + @Override + public int getItemViewType(int position) { + if (getEmptyViewCount() == 1) { + return EMPTY_VIEW; + } + + // fetch + autoRequestFetchMoreData(position); + // load + autoRequestLoadMoreData(position); + int fetchMoreCount = getFetchMoreViewCount(); + if (position < fetchMoreCount) { + Log.d(TAG, "FETCH pos=" + position); + return FETCHING_VIEW; + } else { + int adjPosition = position - fetchMoreCount; + int adapterCount = mData.size(); + if (adjPosition < adapterCount) { + Log.d(TAG, "DATA pos=" + position); + return getDefItemViewType(adjPosition); + } else { + Log.d(TAG, "LOAD pos=" + position); + return LOADING_VIEW; + } + } + } + + /** + * To bind different types of holder and solve different the bind events + * + * @param holder + * @param positions + * @see #getDefItemViewType(int) + */ + @Override + public void onBindViewHolder(K holder, int positions) { + int viewType = holder.getItemViewType(); + + switch (viewType) { + case LOADING_VIEW: + mLoadMoreView.convert(holder); + break; + case FETCHING_VIEW: + mFetchMoreView.convert(holder); + break; + case EMPTY_VIEW: + break; + default: + convert(holder, mData.get(holder.getLayoutPosition() - getFetchMoreViewCount()), positions, isScrolling); + break; + } + } + + protected K onCreateDefViewHolder(ViewGroup parent, int viewType) { + return createBaseViewHolder(parent, mLayoutResId); + } + + protected K createBaseViewHolder(ViewGroup parent, int layoutResId) { + return createBaseViewHolder(getItemView(layoutResId, parent)); + } + + /** + * @param layoutResId ID for an XML layout resource to load + * @param parent Optional view to be the parent of the generated hierarchy or else simply an object that + * provides a set of LayoutParams values for root of the returned + * hierarchy + * @return view will be return + */ + protected View getItemView(int layoutResId, ViewGroup parent) { + return mLayoutInflater.inflate(layoutResId, parent, false); + } + + /** + * if you want to use subclass of BaseViewHolder in the adapter, + * you must override the method to create new ViewHolder. + * + * @param view view + * @return new ViewHolder + */ + protected K createBaseViewHolder(View view) { + return (K) new BaseViewHolder(view); + } + + protected int getDefItemViewType(int position) { + return super.getItemViewType(position); + } + + @Override + public K onCreateViewHolder(ViewGroup parent, int viewType) { + K baseViewHolder; + this.mContext = parent.getContext(); + this.mLayoutInflater = LayoutInflater.from(mContext); + switch (viewType) { + case FETCHING_VIEW: + baseViewHolder = getFetchingView(parent); + break; + case LOADING_VIEW: + baseViewHolder = getLoadingView(parent); + break; + case EMPTY_VIEW: + baseViewHolder = createBaseViewHolder(mEmptyView); + break; + default: + baseViewHolder = onCreateDefViewHolder(parent, viewType); + } + return baseViewHolder; + + } + + private K getLoadingView(ViewGroup parent) { + View view = getItemView(mLoadMoreView.getLayoutId(), parent); + K holder = createBaseViewHolder(view); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLoadMoreView.getLoadMoreStatus() == LoadMoreView.STATUS_FAIL) { + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemChanged(getFetchMoreViewCount() + mData.size()); + } + } + }); + return holder; + } + + private K getFetchingView(ViewGroup parent) { + View view = getItemView(mFetchMoreView.getLayoutId(), parent); + K holder = createBaseViewHolder(view); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mFetchMoreView.getLoadMoreStatus() == LoadMoreView.STATUS_FAIL) { + mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemChanged(0); + } + } + }); + return holder; + } + + /** + * Called when a view created by this adapter has been attached to a window. + * simple to solve item will layout using all + * {@link #setFullSpan(RecyclerView.ViewHolder)} + * + * @param holder + */ + @Override + public void onViewAttachedToWindow(K holder) { + super.onViewAttachedToWindow(holder); + int type = holder.getItemViewType(); + if (type == EMPTY_VIEW || type == LOADING_VIEW || type == FETCHING_VIEW) { + setFullSpan(holder); + } else { + addAnimation(holder); + } + } + + /** + * When set to true, the item will layout using all span area. That means, if orientation + * is vertical, the view will have full width; if orientation is horizontal, the view will + * have full height. + * if the hold view use StaggeredGridLayoutManager they should using all span area + * + * @param holder True if this item should traverse all spans. + */ + protected void setFullSpan(RecyclerView.ViewHolder holder) { + if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) { + StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); + params.setFullSpan(true); + } + } + + @Override + public void onAttachedToRecyclerView(final RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + if (manager instanceof GridLayoutManager) { + final GridLayoutManager gridManager = ((GridLayoutManager) manager); + gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + int type = getItemViewType(position); + if (mSpanSizeLookup == null) { + return (type == EMPTY_VIEW || type == LOADING_VIEW || type == FETCHING_VIEW) ? gridManager.getSpanCount() : 1; + } else { + return (type == EMPTY_VIEW || type == LOADING_VIEW || type == FETCHING_VIEW) ? gridManager + .getSpanCount() : mSpanSizeLookup.getSpanSize(gridManager, position - getFetchMoreViewCount()); + } + } + }); + } + } + + private SpanSizeLookup mSpanSizeLookup; + + public interface SpanSizeLookup { + int getSpanSize(GridLayoutManager gridLayoutManager, int position); + } + + /** + * *********************************** EmptyView *********************************** + */ + + /** + * if mEmptyView will be return 1 or not will be return 0 + * + * @return + */ + public int getEmptyViewCount() { + if (mEmptyView == null || mEmptyView.getChildCount() == 0) { + return 0; + } + if (!mIsUseEmpty) { + return 0; + } + if (mData.size() != 0) { + return 0; + } + return 1; + } + + public void setEmptyView(View emptyView) { + boolean insert = false; + if (mEmptyView == null) { + mEmptyView = new FrameLayout(emptyView.getContext()); + mEmptyView.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); + insert = true; + } + mEmptyView.removeAllViews(); + mEmptyView.addView(emptyView); + mIsUseEmpty = true; + if (insert) { + if (getEmptyViewCount() == 1) { + notifyItemInserted(0); + } + } + } + + /** + * Set whether to use empty view + * + * @param isUseEmpty + */ + public void isUseEmpty(boolean isUseEmpty) { + mIsUseEmpty = isUseEmpty; + } + + /** + * When the current adapter is empty, the BaseQuickAdapter can display a special view + * called the empty view. The empty view is used to provide feedback to the user + * that no data is available in this AdapterView. + * + * @return The view to show if the adapter is empty. + */ + public View getEmptyView() { + return mEmptyView; + } + + /** + * *********************************** 动画 *********************************** + */ + + /** + * Set the view animation type. + * + * @param animationType One of {@link #ALPHAIN}, {@link #SCALEIN}, {@link #SLIDEIN_BOTTOM}, {@link #SLIDEIN_LEFT}, {@link #SLIDEIN_RIGHT}. + */ + public void openLoadAnimation(@AnimationType int animationType) { + this.mOpenAnimationEnable = true; + mCustomAnimation = null; + switch (animationType) { + case ALPHAIN: + mSelectAnimation = new AlphaInAnimation(); + break; + case SCALEIN: + mSelectAnimation = new ScaleInAnimation(); + break; + case SLIDEIN_BOTTOM: + mSelectAnimation = new SlideInBottomAnimation(); + break; + case SLIDEIN_LEFT: + mSelectAnimation = new SlideInLeftAnimation(); + break; + case SLIDEIN_RIGHT: + mSelectAnimation = new SlideInRightAnimation(); + break; + default: + break; + } + } + + /** + * Set Custom ObjectAnimator + * + * @param animation ObjectAnimator + */ + public void openLoadAnimation(BaseAnimation animation) { + this.mOpenAnimationEnable = true; + this.mCustomAnimation = animation; + } + + /** + * To open the animation when loading + */ + public void openLoadAnimation() { + this.mOpenAnimationEnable = true; + } + + /** + * To close the animation when loading + */ + public void closeLoadAnimation() { + this.mOpenAnimationEnable = false; + this.mSelectAnimation = null; + this.mCustomAnimation = null; + this.mAnimationDuration = 0; + } + + /** + * {@link #addAnimation(RecyclerView.ViewHolder)} + * + * @param firstOnly true just show anim when first loading false show anim when load the data every time + */ + public void setAnimationShowFirstOnly(boolean firstOnly) { + this.mAnimationShowFirstOnly = firstOnly; + } + + /** + * Sets the duration of the animation. + * + * @param duration The length of the animation, in milliseconds. + */ + public void setAnimationDuration(int duration) { + mAnimationDuration = duration; + } + + /** + * add animation when you want to show time + * + * @param holder + */ + private void addAnimation(RecyclerView.ViewHolder holder) { + if (mOpenAnimationEnable) { + if (!mAnimationShowFirstOnly || holder.getLayoutPosition() > mLastPosition) { + BaseAnimation animation; + if (mCustomAnimation != null) { + animation = mCustomAnimation; + } else { + animation = mSelectAnimation; + } + for (Animator anim : animation.getAnimators(holder.itemView)) { + startAnim(anim, holder.getLayoutPosition()); + } + mLastPosition = holder.getLayoutPosition(); + } + } + } + + /** + * set anim to start when loading + * + * @param anim + * @param index + */ + protected void startAnim(Animator anim, int index) { + anim.setDuration(mAnimationDuration).start(); + anim.setInterpolator(mInterpolator); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseItemDraggableAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseItemDraggableAdapter.java new file mode 100644 index 0000000..1711d74 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseItemDraggableAdapter.java @@ -0,0 +1,255 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter; + +import android.graphics.Canvas; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.core.view.MotionEventCompat; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.callback.ItemDragAndSwipeCallback; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener.OnItemDragListener; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener.OnItemSwipeListener; +import com.netease.nim.uikit.R; + +import java.util.Collections; +import java.util.List; + +public abstract class BaseItemDraggableAdapter extends BaseQuickAdapter { + + private static final int NO_TOGGLE_VIEW = 0; + protected int mToggleViewId = NO_TOGGLE_VIEW; + protected ItemTouchHelper mItemTouchHelper; + protected boolean itemDragEnabled = false; + protected boolean itemSwipeEnabled = false; + protected OnItemDragListener mOnItemDragListener; + protected OnItemSwipeListener mOnItemSwipeListener; + protected boolean mDragOnLongPress = true; + + protected View.OnTouchListener mOnToggleViewTouchListener; + protected View.OnLongClickListener mOnToggleViewLongClickListener; + + private static final String ERROR_NOT_SAME_ITEMTOUCHHELPER = "Item drag and item swipe should pass the same ItemTouchHelper"; + + + public BaseItemDraggableAdapter(RecyclerView recyclerView, List data) { + super(recyclerView, data); + } + + public BaseItemDraggableAdapter(RecyclerView recyclerView, int layoutResId, List data) { + super(recyclerView, layoutResId, data); + } + + /** + * To bind different types of holder and solve different the bind events + * + * @param holder + * @param positions + * @see #getDefItemViewType(int) + */ + @Override + public void onBindViewHolder(K holder, int positions) { + super.onBindViewHolder(holder, positions); + int viewType = holder.getItemViewType(); + + if (mItemTouchHelper != null && itemDragEnabled && viewType != LOADING_VIEW && viewType != HEADER_VIEW + && viewType != EMPTY_VIEW && viewType != FOOTER_VIEW) { + if (mToggleViewId != NO_TOGGLE_VIEW) { + View toggleView = ((BaseViewHolder) holder).getView(mToggleViewId); + if (toggleView != null) { + toggleView.setTag(R.id.BaseQuickAdapter_viewholder_support, holder); + if (mDragOnLongPress) { + toggleView.setOnLongClickListener(mOnToggleViewLongClickListener); + } else { + toggleView.setOnTouchListener(mOnToggleViewTouchListener); + } + } + } else { + holder.itemView.setTag(R.id.BaseQuickAdapter_viewholder_support, holder); + holder.itemView.setOnLongClickListener(mOnToggleViewLongClickListener); + } + } + } + + + /** + * Set the toggle view's id which will trigger drag event. + * If the toggle view id is not set, drag event will be triggered when the item is long pressed. + * + * @param toggleViewId the toggle view's id + */ + public void setToggleViewId(int toggleViewId) { + mToggleViewId = toggleViewId; + } + + /** + * Set the drag event should be trigger on long press. + * Work when the toggleViewId has been set. + * + * @param longPress by default is true. + */ + public void setToggleDragOnLongPress(boolean longPress) { + mDragOnLongPress = longPress; + if (mDragOnLongPress) { + mOnToggleViewTouchListener = null; + mOnToggleViewLongClickListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (mItemTouchHelper != null && itemDragEnabled) { + mItemTouchHelper.startDrag((RecyclerView.ViewHolder) v.getTag(R.id.BaseQuickAdapter_viewholder_support)); + } + return true; + } + }; + } else { + mOnToggleViewTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN + && !mDragOnLongPress) { + if (mItemTouchHelper != null && itemDragEnabled) { + mItemTouchHelper.startDrag((RecyclerView.ViewHolder) v.getTag(R.id.BaseQuickAdapter_viewholder_support)); + } + return true; + } else { + return false; + } + } + }; + mOnToggleViewLongClickListener = null; + } + } + + /** + * Enable drag items. + * Use itemView as the toggleView when long pressed. + * + * @param itemTouchHelper {@link ItemTouchHelper} + */ + public void enableDragItem(@NonNull ItemTouchHelper itemTouchHelper) { + enableDragItem(itemTouchHelper, NO_TOGGLE_VIEW, true); + } + + /** + * Enable drag items. Use the specified view as toggle. + * + * @param itemTouchHelper {@link ItemTouchHelper} + * @param toggleViewId The toggle view's id. + * @param dragOnLongPress If true the drag event will be trigger on long press, otherwise on touch down. + */ + public void enableDragItem(@NonNull ItemTouchHelper itemTouchHelper, int toggleViewId, boolean dragOnLongPress) { + itemDragEnabled = true; + mItemTouchHelper = itemTouchHelper; + setToggleViewId(toggleViewId); + setToggleDragOnLongPress(dragOnLongPress); + } + + /** + * Disable drag items. + */ + public void disableDragItem() { + itemDragEnabled = false; + mItemTouchHelper = null; + } + + public boolean isItemDraggable() { + return itemDragEnabled; + } + + /** + *

Enable swipe items.

+ * You should attach {@link ItemTouchHelper} which construct with {@link ItemDragAndSwipeCallback} to the Recycler when you enable + * this. + */ + public void enableSwipeItem() { + itemSwipeEnabled = true; + } + + public void disableSwipeItem() { + itemSwipeEnabled = false; + } + + public boolean isItemSwipeEnable() { + return itemSwipeEnabled; + } + + /** + * @param onItemDragListener Register a callback to be invoked when drag event happen. + */ + public void setOnItemDragListener(OnItemDragListener onItemDragListener) { + mOnItemDragListener = onItemDragListener; + } + + public int getViewHolderPosition(RecyclerView.ViewHolder viewHolder) { + return viewHolder.getAdapterPosition() - getHeaderLayoutCount(); + } + + public void onItemDragStart(RecyclerView.ViewHolder viewHolder) { + if (mOnItemDragListener != null && itemDragEnabled) { + mOnItemDragListener.onItemDragStart(viewHolder, getViewHolderPosition(viewHolder)); + } + } + + public void onItemDragMoving(RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { + int from = getViewHolderPosition(source); + int to = getViewHolderPosition(target); + + if (from < to) { + for (int i = from; i < to; i++) { + Collections.swap(mData, i, i + 1); + } + } else { + for (int i = from; i > to; i--) { + Collections.swap(mData, i, i - 1); + } + } + notifyItemMoved(source.getAdapterPosition(), target.getAdapterPosition()); + + if (mOnItemDragListener != null && itemDragEnabled) { + mOnItemDragListener.onItemDragMoving(source, from, target, to); + } + } + + public void onItemDragEnd(RecyclerView.ViewHolder viewHolder) { + if (mOnItemDragListener != null && itemDragEnabled) { + mOnItemDragListener.onItemDragEnd(viewHolder, getViewHolderPosition(viewHolder)); + } + } + + public void setOnItemSwipeListener(OnItemSwipeListener listener) { + mOnItemSwipeListener = listener; + } + + public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder) { + if (mOnItemSwipeListener != null && itemSwipeEnabled) { + mOnItemSwipeListener.onItemSwipeStart(viewHolder, getViewHolderPosition(viewHolder)); + } + } + + public void onItemSwipeClear(RecyclerView.ViewHolder viewHolder) { + if (mOnItemSwipeListener != null && itemSwipeEnabled) { + mOnItemSwipeListener.clearView(viewHolder, getViewHolderPosition(viewHolder)); + } + } + + public void onItemSwiped(RecyclerView.ViewHolder viewHolder) { + if (mOnItemSwipeListener != null && itemSwipeEnabled) { + mOnItemSwipeListener.onItemSwiped(viewHolder, getViewHolderPosition(viewHolder)); + } + + int pos = getViewHolderPosition(viewHolder); + + mData.remove(pos); + notifyItemRemoved(viewHolder.getAdapterPosition()); + } + + public void onItemSwiping(Canvas canvas, RecyclerView.ViewHolder viewHolder, float dX, float dY, boolean isCurrentlyActive) { + if (mOnItemSwipeListener != null && itemSwipeEnabled) { + mOnItemSwipeListener.onItemSwipeMoving(canvas, viewHolder, dX, dY, isCurrentlyActive); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseMultiItemFetchLoadAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseMultiItemFetchLoadAdapter.java new file mode 100644 index 0000000..e5d4303 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseMultiItemFetchLoadAdapter.java @@ -0,0 +1,137 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter; + +import android.util.SparseArray; +import android.view.ViewGroup; + +import androidx.annotation.LayoutRes; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class BaseMultiItemFetchLoadAdapter extends BaseFetchLoadAdapter { + + /** + * viewType->layoutResId + */ + private SparseArray layouts; + + /** + * viewType->view holder class + */ + private SparseArray> holderClasses; + + /** + * viewType->view holder instance + */ + private Map> multiTypeViewHolders; + + /** + * get view type from data item + * + * @param item + * @return + */ + protected abstract int getViewType(T item); + + /** + * get view holder unique key from data item + * + * @param item + * @return + */ + protected abstract String getItemKey(T item); + + public BaseMultiItemFetchLoadAdapter(RecyclerView recyclerView, List data) { + super(recyclerView, 0, data); + } + + /** + * add viewType->layoutResId, viewType->ViewHolder.class + * + * @param type view type + * @param layoutResId + * @param viewHolderClass + */ + protected void addItemType(int type, @LayoutRes int layoutResId, Class viewHolderClass) { + // layouts + if (layouts == null) { + layouts = new SparseArray<>(); + } + layouts.put(type, layoutResId); + + // view holder class + if (holderClasses == null) { + holderClasses = new SparseArray<>(); + } + holderClasses.put(type, viewHolderClass); + + // view holder + if (multiTypeViewHolders == null) { + multiTypeViewHolders = new HashMap<>(); + } + multiTypeViewHolders.put(type, new HashMap()); + } + + @Override + protected int getDefItemViewType(int position) { + return getViewType(mData.get(position)); + } + + @Override + protected K onCreateDefViewHolder(ViewGroup parent, int viewType) { + return createBaseViewHolder(parent, getLayoutId(viewType)); + } + + @Override + protected void convert(final K baseHolder, final T item, final int position, boolean isScrolling) { + final String key = getItemKey(item); + final int viewType = baseHolder.getItemViewType(); + + RecyclerViewHolder h = multiTypeViewHolders.get(viewType).get(key); + if (h == null) { + // build + try { + Class cls = holderClasses.get(viewType); + Constructor c = cls.getDeclaredConstructors()[0]; // 第一个显式的构造函数 + c.setAccessible(true); + h = (RecyclerViewHolder) c.newInstance(new Object[]{this}); + multiTypeViewHolders.get(viewType).put(key, h); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // convert + if (h != null) { + h.convert(baseHolder, item, position, isScrolling); + } + } + + @Override + protected void onRemove(final T item) { + super.onRemove(item); + + // 移除holder + multiTypeViewHolders.get(getViewType(item)).remove(getItemKey(item)); + } + + private int getLayoutId(int viewType) { + return layouts.get(viewType); + } + + protected RecyclerViewHolder getViewHolder(int viewType, String viewHolderKey) { + if (multiTypeViewHolders.containsKey(viewType)) { + return multiTypeViewHolders.get(viewType).get(viewHolderKey); + } + + return null; + } +} + + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseMultiItemQuickAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseMultiItemQuickAdapter.java new file mode 100644 index 0000000..dedf0e9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseMultiItemQuickAdapter.java @@ -0,0 +1,137 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter; + +import android.util.SparseArray; +import android.view.ViewGroup; + +import androidx.annotation.LayoutRes; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class BaseMultiItemQuickAdapter extends BaseQuickAdapter { + + /** + * viewType->layoutResId + */ + private SparseArray layouts; + + /** + * viewType->view holder class + */ + private SparseArray> holderClasses; + + /** + * viewType->view holder instance + */ + private Map> multiTypeViewHolders; + + /** + * get view type from data item + * + * @param item + * @return + */ + protected abstract int getViewType(T item); + + /** + * get view holder unique key from data item + * + * @param item + * @return + */ + protected abstract String getItemKey(T item); + + public BaseMultiItemQuickAdapter(RecyclerView recyclerView, List data) { + super(recyclerView, data); + } + + /** + * add viewType->layoutResId, viewType->ViewHolder.class + * + * @param type view type + * @param layoutResId + * @param viewHolderClass + */ + protected void addItemType(int type, @LayoutRes int layoutResId, Class viewHolderClass) { + // layouts + if (layouts == null) { + layouts = new SparseArray<>(); + } + layouts.put(type, layoutResId); + + // view holder class + if (holderClasses == null) { + holderClasses = new SparseArray<>(); + } + holderClasses.put(type, viewHolderClass); + + // view holder + if (multiTypeViewHolders == null) { + multiTypeViewHolders = new HashMap<>(); + } + multiTypeViewHolders.put(type, new HashMap()); + } + + @Override + protected int getDefItemViewType(int position) { + return getViewType(mData.get(position)); + } + + @Override + protected K onCreateDefViewHolder(ViewGroup parent, int viewType) { + return createBaseViewHolder(parent, getLayoutId(viewType)); + } + + @Override + protected void convert(final K baseHolder, final T item, final int position, boolean isScrolling) { + /** + * 注意:baseHolder对应的是某一行的View的缓存,与item不一定是一一对应的。即同一个item,在不同的行,回调的baseHolder不一样。 + * 例如:第一行:s1-> baseHolder01 第二行 s2->baseHolder02。 + * 把s2置顶,则第一行:s2->baseHolder01,第二行:s1->baseHolder02。 + * + * 而我们的设计:item与RecyclerViewHolder是一一对应的。因此每次convert都需要拿当前回调的baseHolder进行convert, + * RecyclerViewHolder可以从baseHolder中取出该行View所有的子View进行数据绑定(相当于需要经历inflate->refresh的过程)。 + */ + final String key = getItemKey(item); + final int viewType = baseHolder.getItemViewType(); + + RecyclerViewHolder h = multiTypeViewHolders.get(viewType).get(key); + if (h == null) { + // build + try { + Class cls = holderClasses.get(viewType); + Constructor c = cls.getDeclaredConstructors()[0]; // 第一个显式的构造函数 + c.setAccessible(true); + h = (RecyclerViewHolder) c.newInstance(new Object[]{this}); + multiTypeViewHolders.get(viewType).put(key, h); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // convert + if (h != null) { + h.convert(baseHolder, item, position, isScrolling); + } + } + + @Override + protected void onRemove(final T item) { + super.onRemove(item); + + // 移除holder + multiTypeViewHolders.get(getViewType(item)).remove(getItemKey(item)); + } + + private int getLayoutId(int viewType) { + return layouts.get(viewType); + } +} + + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseQuickAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseQuickAdapter.java new file mode 100644 index 0000000..4d1456e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseQuickAdapter.java @@ -0,0 +1,1381 @@ +/** + * Copyright 2013 Joan Zapata + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +import android.animation.Animator; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import androidx.annotation.IntDef; +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.LayoutParams; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.AlphaInAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.BaseAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.ScaleInAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.SlideInBottomAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.SlideInLeftAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation.SlideInRightAnimation; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.entity.IExpandable; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore.LoadMoreView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore.SimpleLoadMoreView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.util.RecyclerViewUtil; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + +public abstract class BaseQuickAdapter extends RecyclerView.Adapter implements IRecyclerView { + + private boolean isScrolling = false; + + //load more + private boolean mNextLoadEnable = false; + private boolean mLoadMoreEnable = false; + private RequestLoadMoreListener mRequestLoadMoreListener; + private boolean mLoading = false; + private LoadMoreView mLoadMoreView = new SimpleLoadMoreView(); + + private boolean mFirstOnlyEnable = true; + private boolean mOpenAnimationEnable = false; + private Interpolator mInterpolator = new LinearInterpolator(); + private int mDuration = 300; + private int mLastPosition = -1; + //@AnimationType + private BaseAnimation mCustomAnimation; + private BaseAnimation mSelectAnimation = new AlphaInAnimation(); + //header footer + private LinearLayout mHeaderLayout; + private LinearLayout mFooterLayout; + //empty + private FrameLayout mEmptyView; + private boolean mIsUseEmpty = true; + private boolean mHeadAndEmptyEnable; + private boolean mFootAndEmptyEnable; + + protected static final String TAG = BaseQuickAdapter.class.getSimpleName(); + protected Context mContext; + protected int mLayoutResId; + protected LayoutInflater mLayoutInflater; + protected List mData; + + @IntDef({ALPHAIN, SCALEIN, SLIDEIN_BOTTOM, SLIDEIN_LEFT, SLIDEIN_RIGHT}) + @Retention(RetentionPolicy.SOURCE) + public @interface AnimationType { + } + + /** + * Use with {@link #openLoadAnimation} + */ + public static final int ALPHAIN = 0x00000001; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SCALEIN = 0x00000002; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SLIDEIN_BOTTOM = 0x00000003; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SLIDEIN_LEFT = 0x00000004; + /** + * Use with {@link #openLoadAnimation} + */ + public static final int SLIDEIN_RIGHT = 0x00000005; + + public void setOnLoadMoreListener(RequestLoadMoreListener requestLoadMoreListener) { + this.mRequestLoadMoreListener = requestLoadMoreListener; + mNextLoadEnable = true; + mLoadMoreEnable = true; + mLoading = false; + } + + /** + * Set custom load more + * + * @param loadingView + */ + public void setLoadMoreView(LoadMoreView loadingView) { + this.mLoadMoreView = loadingView; + } + + /** + * Load more view count + * + * @return 0 or 1 + */ + private int getLoadMoreViewCount() { + if (mRequestLoadMoreListener == null || !mLoadMoreEnable) { + return 0; + } + if (!mNextLoadEnable && mLoadMoreView.isLoadEndMoreGone()) { + return 0; + } + if (mData.size() == 0) { + return 0; + } + return 1; + } + + /** + * @return Whether the Adapter is actively showing load + * progress. + */ + public boolean isLoading() { + return mLoading; + } + + + /** + * Refresh end, no more data + */ + public void loadMoreEnd() { + loadMoreEnd(false); + } + + /** + * Refresh end, no more data + * + * @param gone if true gone the load more view + */ + public void loadMoreEnd(boolean gone) { + if (getLoadMoreViewCount() == 0) { + return; + } + mLoading = false; + mNextLoadEnable = false; + mLoadMoreView.setLoadMoreEndGone(gone); + if (gone) { + notifyItemRemoved(getHeaderLayoutCount() + mData.size() + getFooterLayoutCount()); + } else { + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_END); + notifyItemChanged(getHeaderLayoutCount() + mData.size() + getFooterLayoutCount()); + } + } + + /** + * Refresh complete + */ + public void loadMoreComplete() { + if (getLoadMoreViewCount() == 0) { + return; + } + mLoading = false; + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemChanged(getHeaderLayoutCount() + mData.size() + getFooterLayoutCount()); + } + + /** + * Refresh failed + */ + public void loadMoreFail() { + if (getLoadMoreViewCount() == 0) { + return; + } + mLoading = false; + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_FAIL); + notifyItemChanged(getHeaderLayoutCount() + mData.size() + getFooterLayoutCount()); + } + + /** + * Set the enabled state of load more. + * + * @param enable True if load more is enabled, false otherwise. + */ + public void setEnableLoadMore(boolean enable) { + int oldLoadMoreCount = getLoadMoreViewCount(); + mLoadMoreEnable = enable; + int newLoadMoreCount = getLoadMoreViewCount(); + + if (oldLoadMoreCount == 1) { + if (newLoadMoreCount == 0) { + notifyItemRemoved(getHeaderLayoutCount() + mData.size() + getFooterLayoutCount()); + } + } else { + if (newLoadMoreCount == 1) { + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemInserted(getHeaderLayoutCount() + mData.size() + getFooterLayoutCount()); + } + } + } + + /** + * Returns the enabled status for load more. + * + * @return True if load more is enabled, false otherwise. + */ + public boolean isLoadMoreEnable() { + return mLoadMoreEnable; + } + + /** + * Sets the duration of the animation. + * + * @param duration The length of the animation, in milliseconds. + */ + public void setDuration(int duration) { + mDuration = duration; + } + + + /** + * Same as QuickAdapter#QuickAdapter(Context,int) but with + * some initialization data. + * + * @param recyclerView RecyclerView which use this adapter + * @param layoutResId The layout resource id of each item. + * @param data A new list is created out of this one to avoid mutable list + */ + public BaseQuickAdapter(RecyclerView recyclerView, int layoutResId, List data) { + this.mData = data == null ? new ArrayList() : data; + if (layoutResId != 0) { + this.mLayoutResId = layoutResId; + } + + /** + * 在适配器中声明一个全局的boolean变量用来保存此刻是否在滚动,然后通过给RecyclerView设置滚动监听,然后在滚动监听器的onScrollStateChanged()方法中给boolean值赋值,看是否在滚动。 + * 在使用这个适配器的时候,可以根据滚动状态的不同来判断:比如正在滚动的时候就只显示内存缓存的图片,如果内存缓存中没有就显示一张默认图片;而如果没有在滚动就采用正常的图片加载方案去加载网络或者缓存中的图片。 + */ + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + isScrolling = newState != RecyclerView.SCROLL_STATE_IDLE; + } + }); + + /** + * 关闭默认viewholder item动画 + */ + RecyclerViewUtil.changeItemAnimation(recyclerView, false); + } + + public BaseQuickAdapter(RecyclerView recyclerView, List data) { + this(recyclerView, 0, data); + } + + /** + * remove the item associated with the specified position of adapter + * + * @param position + */ + public void remove(int position) { + final T item = mData.get(position); + mData.remove(position); + notifyItemRemoved(position + getHeaderLayoutCount()); + onRemove(item); + } + + protected void onRemove(T item) { + + } + + /** + * insert a item associated with the specified position of adapter + * + * @param position + * @param item + */ + public void add(int position, T item) { + mData.add(position, item); + notifyItemInserted(position + getHeaderLayoutCount()); + } + + /** + * setting up a new instance to data; + * + * @param data + */ + public void setNewData(List data) { + this.mData = data == null ? new ArrayList() : data; + if (mRequestLoadMoreListener != null) { + mNextLoadEnable = true; + mLoadMoreEnable = true; + mLoading = false; + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + } + mLastPosition = -1; + notifyDataSetChanged(); + } + + /** + * clear data before reload + */ + public void clearData() { + this.mData.clear(); + if (mRequestLoadMoreListener != null) { + mNextLoadEnable = true; + mLoading = false; + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + } + mLastPosition = -1; + notifyDataSetChanged(); + } + + /** + * add one new data in to certain location + * + * @param position + */ + public void addData(int position, T data) { + if (0 <= position && position < mData.size()) { + mData.add(position, data); + notifyItemInserted(position + getHeaderLayoutCount()); + } else { + throw new ArrayIndexOutOfBoundsException("inserted position most greater than 0 and less than data size"); + } + } + + /** + * add one new data + */ + public void addData(T data) { + mData.add(data); + notifyItemInserted(mData.size() + getHeaderLayoutCount()); + } + + /** + * add new data in to certain location + * + * @param position + */ + public void addData(int position, List data) { + if (0 <= position && position < mData.size()) { + mData.addAll(position, data); + notifyItemRangeInserted(position + getHeaderLayoutCount(), data.size()); + } else { + throw new ArrayIndexOutOfBoundsException("inserted position most greater than 0 and less than data size"); + } + } + + /** + * additional data; + * + * @param newData + */ + public void addData(List newData) { + this.mData.addAll(newData); + notifyItemRangeInserted(mData.size() - newData.size() + getHeaderLayoutCount(), newData.size()); + } + + /** + * Get the data of list + * + * @return + */ + public List getData() { + return mData; + } + + /** + * Get the data item associated with the specified position in the data set. + * + * @param position Position of the item whose data we want within the adapter's + * data set. + * @return The data at the specified position. + */ + public T getItem(int position) { + return mData.get(position); + } + + /** + * if setHeadView will be return 1 if not will be return 0. + * notice: Deprecated! Use {@link ViewGroup#getChildCount()} of {@link #getHeaderLayout()} to replace. + * + * @return + */ + @Deprecated + public int getHeaderViewsCount() { + return getHeaderLayoutCount(); + } + + /** + * if mFooterLayout will be return 1 or not will be return 0. + * notice: Deprecated! Use {@link ViewGroup#getChildCount()} of {@link #getFooterLayout()} to replace. + * + * @return + */ + @Deprecated + public int getFooterViewsCount() { + return getFooterLayoutCount(); + } + + /** + * if addHeaderView will be return 1, if not will be return 0 + */ + public int getHeaderLayoutCount() { + if (mHeaderLayout == null || mHeaderLayout.getChildCount() == 0) { + return 0; + } + return 1; + } + + /** + * if addFooterView will be return 1, if not will be return 0 + */ + public int getFooterLayoutCount() { + if (mFooterLayout == null || mFooterLayout.getChildCount() == 0) { + return 0; + } + return 1; + } + + /** + * if mEmptyView will be return 1 or not will be return 0 + * + * @return + */ + public int getEmptyViewCount() { + if (mEmptyView == null || mEmptyView.getChildCount() == 0) { + return 0; + } + if (!mIsUseEmpty) { + return 0; + } + if (mData.size() != 0) { + return 0; + } + return 1; + } + + @Override + public int getItemCount() { + int count; + if (getEmptyViewCount() == 1) { + count = 1; + if (mHeadAndEmptyEnable && getHeaderLayoutCount() != 0) { + count++; + } + if (mFootAndEmptyEnable && getFooterLayoutCount() != 0) { + count++; + } + } else { + count = getHeaderLayoutCount() + mData.size() + getFooterLayoutCount() + getLoadMoreViewCount(); + } + return count; + } + + @Override + public int getItemViewType(int position) { + if (getEmptyViewCount() == 1) { + boolean header = mHeadAndEmptyEnable && getHeaderLayoutCount() != 0; + switch (position) { + case 0: + if (header) { + return HEADER_VIEW; + } else { + return EMPTY_VIEW; + } + case 1: + if (header) { + return EMPTY_VIEW; + } else { + return FOOTER_VIEW; + } + case 2: + return FOOTER_VIEW; + default: + return EMPTY_VIEW; + } + } + autoLoadMore(position); + int numHeaders = getHeaderLayoutCount(); + if (position < numHeaders) { + return HEADER_VIEW; + } else { + int adjPosition = position - numHeaders; + int adapterCount = mData.size(); + if (adjPosition < adapterCount) { + return getDefItemViewType(adjPosition); + } else { + adjPosition = adjPosition - adapterCount; + int numFooters = getFooterLayoutCount(); + if (adjPosition < numFooters) { + return FOOTER_VIEW; + } else { + return LOADING_VIEW; + } + } + } + } + + protected int getDefItemViewType(int position) { + return super.getItemViewType(position); + } + + @Override + public K onCreateViewHolder(ViewGroup parent, int viewType) { + K baseViewHolder = null; + this.mContext = parent.getContext(); + this.mLayoutInflater = LayoutInflater.from(mContext); + switch (viewType) { + case LOADING_VIEW: + baseViewHolder = getLoadingView(parent); + break; + case HEADER_VIEW: + baseViewHolder = createBaseViewHolder(mHeaderLayout); + break; + case EMPTY_VIEW: + baseViewHolder = createBaseViewHolder(mEmptyView); + break; + case FOOTER_VIEW: + baseViewHolder = createBaseViewHolder(mFooterLayout); + break; + default: + baseViewHolder = onCreateDefViewHolder(parent, viewType); + } + return baseViewHolder; + + } + + + private K getLoadingView(ViewGroup parent) { + View view = getItemView(mLoadMoreView.getLayoutId(), parent); + K holder = createBaseViewHolder(view); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLoadMoreView.getLoadMoreStatus() == LoadMoreView.STATUS_FAIL) { + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT); + notifyItemChanged(getHeaderLayoutCount() + mData.size() + getFooterLayoutCount()); + } + } + }); + return holder; + } + + /** + * Called when a view created by this adapter has been attached to a window. + * simple to solve item will layout using all + * {@link #setFullSpan(RecyclerView.ViewHolder)} + * + * @param holder + */ + @Override + public void onViewAttachedToWindow(K holder) { + super.onViewAttachedToWindow(holder); + int type = holder.getItemViewType(); + if (type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type == LOADING_VIEW) { + setFullSpan(holder); + } else { + addAnimation(holder); + } + } + + /** + * When set to true, the item will layout using all span area. That means, if orientation + * is vertical, the view will have full width; if orientation is horizontal, the view will + * have full height. + * if the hold view use StaggeredGridLayoutManager they should using all span area + * + * @param holder True if this item should traverse all spans. + */ + protected void setFullSpan(RecyclerView.ViewHolder holder) { + if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) { + StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); + params.setFullSpan(true); + } + } + + @Override + public void onAttachedToRecyclerView(final RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + if (manager instanceof GridLayoutManager) { + final GridLayoutManager gridManager = ((GridLayoutManager) manager); + gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + int type = getItemViewType(position); + if (mSpanSizeLookup == null) + return (type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type == LOADING_VIEW) ? gridManager.getSpanCount() : 1; + else + return (type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type == LOADING_VIEW) ? gridManager.getSpanCount() : mSpanSizeLookup.getSpanSize(gridManager, position - getHeaderLayoutCount()); + } + }); + } + } + + private boolean flag = true; + private SpanSizeLookup mSpanSizeLookup; + + public interface SpanSizeLookup { + int getSpanSize(GridLayoutManager gridLayoutManager, int position); + } + + /** + * @param spanSizeLookup instance to be used to query number of spans occupied by each item + */ + public void setSpanSizeLookup(SpanSizeLookup spanSizeLookup) { + this.mSpanSizeLookup = spanSizeLookup; + } + + /** + * To bind different types of holder and solve different the bind events + * + * @param holder + * @param positions + * @see #getDefItemViewType(int) + */ + @Override + public void onBindViewHolder(K holder, int positions) { + final int viewType = holder.getItemViewType(); + final int position = holder.getLayoutPosition() - getHeaderLayoutCount(); + + switch (viewType) { + case LOADING_VIEW: + mLoadMoreView.convert(holder); + break; + case HEADER_VIEW: + break; + case EMPTY_VIEW: + break; + case FOOTER_VIEW: + break; + default: + convert(holder, mData.get(position), position, isScrolling); + break; + } + } + + protected K onCreateDefViewHolder(ViewGroup parent, int viewType) { + return createBaseViewHolder(parent, mLayoutResId); + } + + protected K createBaseViewHolder(ViewGroup parent, int layoutResId) { + return createBaseViewHolder(getItemView(layoutResId, parent)); + } + + /** + * if you want to use subclass of BaseViewHolder in the adapter, + * you must override the method to create new ViewHolder. + * + * @param view view + * @return new ViewHolder + */ + protected K createBaseViewHolder(View view) { + return (K) new BaseViewHolder(view); + } + + /** + * Return root layout of header + */ + public LinearLayout getHeaderLayout() { + return mHeaderLayout; + } + + /** + * Return root layout of footer + */ + public LinearLayout getFooterLayout() { + return mFooterLayout; + } + + /** + * Append header to the rear of the mHeaderLayout. + * + * @param header + */ + public void addHeaderView(View header) { + addHeaderView(header, -1); + } + + /** + * Add header view to mHeaderLayout and set header view position in mHeaderLayout. + * When index = -1 or index >= child count in mHeaderLayout, + * the effect of this method is the same as that of {@link #addHeaderView(View)}. + * + * @param header + * @param index the position in mHeaderLayout of this header. + * When index = -1 or index >= child count in mHeaderLayout, + * the effect of this method is the same as that of {@link #addHeaderView(View)}. + */ + public void addHeaderView(View header, int index) { + addHeaderView(header, index, LinearLayout.VERTICAL); + } + + /** + * @param header + * @param index + * @param orientation + */ + public void addHeaderView(View header, int index, int orientation) { + if (mHeaderLayout == null) { + mHeaderLayout = new LinearLayout(header.getContext()); + if (orientation == LinearLayout.VERTICAL) { + mHeaderLayout.setOrientation(LinearLayout.VERTICAL); + mHeaderLayout.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); + } else { + mHeaderLayout.setOrientation(LinearLayout.HORIZONTAL); + mHeaderLayout.setLayoutParams(new LayoutParams(WRAP_CONTENT, MATCH_PARENT)); + } + } + index = index >= mHeaderLayout.getChildCount() ? -1 : index; + mHeaderLayout.addView(header, index); + if (mHeaderLayout.getChildCount() == 1) { + int position = getHeaderViewPosition(); + if (position != -1) { + notifyItemInserted(position); + } + } + } + + /** + * Append footer to the rear of the mFooterLayout. + * + * @param footer + */ + public void addFooterView(View footer) { + addFooterView(footer, -1); + } + + /** + * Add footer view to mFooterLayout and set footer view position in mFooterLayout. + * When index = -1 or index >= child count in mFooterLayout, + * the effect of this method is the same as that of {@link #addFooterView(View)}. + * + * @param footer + * @param index the position in mFooterLayout of this footer. + * When index = -1 or index >= child count in mFooterLayout, + * the effect of this method is the same as that of {@link #addFooterView(View)}. + */ + public void addFooterView(View footer, int index) { + if (mFooterLayout == null) { + mFooterLayout = new LinearLayout(footer.getContext()); + mFooterLayout.setOrientation(LinearLayout.VERTICAL); + mFooterLayout.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); + } + index = index >= mFooterLayout.getChildCount() ? -1 : index; + mFooterLayout.addView(footer, index); + if (mFooterLayout.getChildCount() == 1) { + int position = getFooterViewPosition(); + if (position != -1) { + notifyItemInserted(position); + } + } + } + + /** + * remove header view from mHeaderLayout. + * When the child count of mHeaderLayout is 0, mHeaderLayout will be set to null. + * + * @param header + */ + public void removeHeaderView(View header) { + if (getHeaderLayoutCount() == 0) return; + + mHeaderLayout.removeView(header); + if (mHeaderLayout.getChildCount() == 0) { + int position = getHeaderViewPosition(); + if (position != -1) { + notifyItemRemoved(position); + } + } + } + + /** + * remove footer view from mFooterLayout, + * When the child count of mFooterLayout is 0, mFooterLayout will be set to null. + * + * @param footer + */ + public void removeFooterView(View footer) { + if (getFooterLayoutCount() == 0) return; + + mFooterLayout.removeView(footer); + if (mFooterLayout.getChildCount() == 0) { + int position = getFooterViewPosition(); + if (position != -1) { + notifyItemRemoved(position); + } + } + } + + /** + * remove all header view from mHeaderLayout and set null to mHeaderLayout + */ + public void removeAllHeaderView() { + if (getHeaderLayoutCount() == 0) return; + + mHeaderLayout.removeAllViews(); + int position = getHeaderViewPosition(); + if (position != -1) { + notifyItemRemoved(position); + } + } + + /** + * remove all footer view from mFooterLayout and set null to mFooterLayout + */ + public void removeAllFooterView() { + if (getFooterLayoutCount() == 0) return; + + mFooterLayout.removeAllViews(); + int position = getFooterViewPosition(); + if (position != -1) { + notifyItemRemoved(position); + } + } + + private int getHeaderViewPosition() { + //Return to header view notify position + if (getEmptyViewCount() == 1) { + if (mHeadAndEmptyEnable) { + return 0; + } + } else { + return 0; + } + return -1; + } + + private int getFooterViewPosition() { + //Return to footer view notify position + if (getEmptyViewCount() == 1) { + int position = 1; + if (mHeadAndEmptyEnable && getHeaderLayoutCount() != 0) { + position++; + } + if (mFootAndEmptyEnable) { + return position; + } + } else { + return getHeaderLayoutCount() + mData.size(); + } + return -1; + } + + public void setEmptyView(View emptyView) { + boolean insert = false; + if (mEmptyView == null) { + mEmptyView = new FrameLayout(emptyView.getContext()); + mEmptyView.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); + insert = true; + } + mEmptyView.removeAllViews(); + mEmptyView.addView(emptyView); + mIsUseEmpty = true; + if (insert) { + if (getEmptyViewCount() == 1) { + int position = 0; + if (mHeadAndEmptyEnable && getHeaderLayoutCount() != 0) { + position++; + } + notifyItemInserted(position); + } + } + } + + /** + * Call before {@link RecyclerView#setAdapter(RecyclerView.Adapter)} + * + * @param isHeadAndEmpty false will not show headView if the data is empty true will show emptyView and headView + */ + public void setHeaderAndEmpty(boolean isHeadAndEmpty) { + setHeaderFooterEmpty(isHeadAndEmpty, false); + } + + /** + * set emptyView show if adapter is empty and want to show headview and footview + * Call before {@link RecyclerView#setAdapter(RecyclerView.Adapter)} + * + * @param isHeadAndEmpty + * @param isFootAndEmpty + */ + public void setHeaderFooterEmpty(boolean isHeadAndEmpty, boolean isFootAndEmpty) { + mHeadAndEmptyEnable = isHeadAndEmpty; + mFootAndEmptyEnable = isFootAndEmpty; + } + + /** + * Set whether to use empty view + * + * @param isUseEmpty + */ + public void isUseEmpty(boolean isUseEmpty) { + mIsUseEmpty = isUseEmpty; + } + + /** + * When the current adapter is empty, the BaseQuickAdapter can display a special view + * called the empty view. The empty view is used to provide feedback to the user + * that no data is available in this AdapterView. + * + * @return The view to show if the adapter is empty. + */ + public View getEmptyView() { + return mEmptyView; + } + + private int mAutoLoadMoreSize = 1; + + public void setAutoLoadMoreSize(int autoLoadMoreSize) { + if (autoLoadMoreSize > 1) { + mAutoLoadMoreSize = autoLoadMoreSize; + } + } + + private void autoLoadMore(int position) { + if (getLoadMoreViewCount() == 0) { + return; + } + if (position < getItemCount() - mAutoLoadMoreSize) { + return; + } + if (mLoadMoreView.getLoadMoreStatus() != LoadMoreView.STATUS_DEFAULT) { + return; + } + mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_LOADING); + if (!mLoading) { + mLoading = true; + mRequestLoadMoreListener.onLoadMoreRequested(); + } + } + + + /** + * add animation when you want to show time + * + * @param holder + */ + private void addAnimation(RecyclerView.ViewHolder holder) { + if (mOpenAnimationEnable) { + if (!mFirstOnlyEnable || holder.getLayoutPosition() > mLastPosition) { + BaseAnimation animation = null; + if (mCustomAnimation != null) { + animation = mCustomAnimation; + } else { + animation = mSelectAnimation; + } + for (Animator anim : animation.getAnimators(holder.itemView)) { + startAnim(anim, holder.getLayoutPosition()); + } + mLastPosition = holder.getLayoutPosition(); + } + } + } + + /** + * set anim to start when loading + * + * @param anim + * @param index + */ + protected void startAnim(Animator anim, int index) { + anim.setDuration(mDuration).start(); + anim.setInterpolator(mInterpolator); + } + + /** + * @param layoutResId ID for an XML layout resource to load + * @param parent Optional view to be the parent of the generated hierarchy or else simply an object that + * provides a set of LayoutParams values for root of the returned + * hierarchy + * @return view will be return + */ + protected View getItemView(int layoutResId, ViewGroup parent) { + return mLayoutInflater.inflate(layoutResId, parent, false); + } + + + public interface RequestLoadMoreListener { + + void onLoadMoreRequested(); + + } + + + /** + * Set the view animation type. + * + * @param animationType One of {@link #ALPHAIN}, {@link #SCALEIN}, {@link #SLIDEIN_BOTTOM}, {@link #SLIDEIN_LEFT}, {@link #SLIDEIN_RIGHT}. + */ + public void openLoadAnimation(@AnimationType int animationType) { + this.mOpenAnimationEnable = true; + mCustomAnimation = null; + switch (animationType) { + case ALPHAIN: + mSelectAnimation = new AlphaInAnimation(); + break; + case SCALEIN: + mSelectAnimation = new ScaleInAnimation(); + break; + case SLIDEIN_BOTTOM: + mSelectAnimation = new SlideInBottomAnimation(); + break; + case SLIDEIN_LEFT: + mSelectAnimation = new SlideInLeftAnimation(); + break; + case SLIDEIN_RIGHT: + mSelectAnimation = new SlideInRightAnimation(); + break; + default: + break; + } + } + + /** + * Set Custom ObjectAnimator + * + * @param animation ObjectAnimator + */ + public void openLoadAnimation(BaseAnimation animation) { + this.mOpenAnimationEnable = true; + this.mCustomAnimation = animation; + } + + /** + * To open the animation when loading + */ + public void openLoadAnimation() { + this.mOpenAnimationEnable = true; + } + + /** + * To close the animation when loading + */ + public void closeLoadAnimation() { + this.mOpenAnimationEnable = false; + this.mSelectAnimation = null; + this.mCustomAnimation = null; + this.mDuration = 0; + } + + /** + * {@link #addAnimation(RecyclerView.ViewHolder)} + * + * @param firstOnly true just show anim when first loading false show anim when load the data every time + */ + public void isFirstOnly(boolean firstOnly) { + this.mFirstOnlyEnable = firstOnly; + } + + /** + * Implement this method and use the helper to adapt the view to the given item. + * + * @param helper A fully initialized helper. + * @param item the item that needs to be displayed. + * @param position the item position + * @param isScrolling RecyclerView is scrolling + */ + protected abstract void convert(K helper, T item, int position, boolean isScrolling); + + /** + * Get the row id associated with the specified position in the list. + * + * @param position The position of the item within the adapter's data set whose row id we want. + * @return The id of the item at the specified position. + */ + @Override + public long getItemId(int position) { + return position; + } + + private int recursiveExpand(int position, @NonNull List list) { + int count = 0; + int pos = position + list.size() - 1; + for (int i = list.size() - 1; i >= 0; i--, pos--) { + if (list.get(i) instanceof IExpandable) { + IExpandable item = (IExpandable) list.get(i); + if (item.isExpanded() && hasSubItems(item)) { + List subList = item.getSubItems(); + mData.addAll(pos + 1, subList); + int subItemCount = recursiveExpand(pos + 1, subList); + count += subItemCount; + } + } + } + return count; + + } + + /** + * Expand an expandable item + * + * @param position position of the item + * @param animate expand items with animation + * @param shouldNotify notify the RecyclerView to rebind items, false if you want to do it yourself. + * @return the number of items that have been added. + */ + public int expand(@IntRange(from = 0) int position, boolean animate, boolean shouldNotify) { + position -= getHeaderLayoutCount(); + + IExpandable expandable = getExpandableItem(position); + if (expandable == null) { + return 0; + } + if (!hasSubItems(expandable)) { + expandable.setExpanded(false); + return 0; + } + int subItemCount = 0; + if (!expandable.isExpanded()) { + List list = expandable.getSubItems(); + mData.addAll(position + 1, list); + subItemCount += recursiveExpand(position + 1, list); + + expandable.setExpanded(true); + subItemCount += list.size(); + } + int parentPos = position + getHeaderLayoutCount(); + if (shouldNotify) { + if (animate) { + notifyItemChanged(parentPos); + notifyItemRangeInserted(parentPos + 1, subItemCount); + } else { + notifyDataSetChanged(); + } + } + return subItemCount; + } + + /** + * Expand an expandable item + * + * @param position position of the item, which includes the header layout count. + * @param animate expand items with animation + * @return the number of items that have been added. + */ + public int expand(@IntRange(from = 0) int position, boolean animate) { + return expand(position, animate, true); + } + + /** + * Expand an expandable item with animation. + * + * @param position position of the item, which includes the header layout count. + * @return the number of items that have been added. + */ + public int expand(@IntRange(from = 0) int position) { + return expand(position, true, true); + } + + public int expandAll(int position, boolean animate, boolean notify) { + position -= getHeaderLayoutCount(); + + T endItem = null; + if (position + 1 < this.mData.size()) { + endItem = getItem(position + 1); + } + + IExpandable expandable = getExpandableItem(position); + if (!hasSubItems(expandable)) { + return 0; + } + + int count = expand(position + getHeaderLayoutCount(), false, false); + for (int i = position + 1; i < this.mData.size(); i++) { + T item = getItem(i); + + if (item == endItem) { + break; + } + if (isExpandable(item)) { + count += expand(i + getHeaderLayoutCount(), false, false); + } + } + + if (notify) { + if (animate) { + notifyItemRangeInserted(position + getHeaderLayoutCount() + 1, count); + } else { + notifyDataSetChanged(); + } + } + return count; + } + + /** + * expand the item and all its subItems + * + * @param position position of the item, which includes the header layout count. + * @param init whether you are initializing the recyclerView or not. + * if true, it won't notify recyclerView to redraw UI. + * @return the number of items that have been added to the adapter. + */ + public int expandAll(int position, boolean init) { + return expandAll(position, true, !init); + } + + private int recursiveCollapse(@IntRange(from = 0) int position) { + T item = getItem(position); + if (!isExpandable(item)) { + return 0; + } + IExpandable expandable = (IExpandable) item; + int subItemCount = 0; + if (expandable.isExpanded()) { + List subItems = expandable.getSubItems(); + for (int i = subItems.size() - 1; i >= 0; i--) { + T subItem = subItems.get(i); + int pos = getItemPosition(subItem); + if (pos < 0) { + continue; + } + if (subItem instanceof IExpandable) { + subItemCount += recursiveCollapse(pos); + } + mData.remove(pos); + subItemCount++; + } + } + return subItemCount; + } + + /** + * Collapse an expandable item that has been expanded.. + * + * @param position the position of the item, which includes the header layout count. + * @param animate collapse with animation or not. + * @param notify notify the recyclerView refresh UI or not. + * @return the number of subItems collapsed. + */ + public int collapse(@IntRange(from = 0) int position, boolean animate, boolean notify) { + position -= getHeaderLayoutCount(); + + IExpandable expandable = getExpandableItem(position); + if (expandable == null) { + return 0; + } + int subItemCount = recursiveCollapse(position); + expandable.setExpanded(false); + int parentPos = position + getHeaderLayoutCount(); + if (notify) { + if (animate) { + notifyItemChanged(parentPos); + notifyItemRangeRemoved(parentPos + 1, subItemCount); + } else { + notifyDataSetChanged(); + } + } + return subItemCount; + } + + /** + * Collapse an expandable item that has been expanded.. + * + * @param position the position of the item, which includes the header layout count. + * @return the number of subItems collapsed. + */ + public int collapse(@IntRange(from = 0) int position) { + return collapse(position, true, true); + } + + /** + * Collapse an expandable item that has been expanded.. + * + * @param position the position of the item, which includes the header layout count. + * @return the number of subItems collapsed. + */ + public int collapse(@IntRange(from = 0) int position, boolean animate) { + return collapse(position, animate, true); + } + + private int getItemPosition(T item) { + return item != null && mData != null && !mData.isEmpty() ? mData.indexOf(item) : -1; + } + + private boolean hasSubItems(IExpandable item) { + List list = item.getSubItems(); + return list != null && list.size() > 0; + } + + private boolean isExpandable(T item) { + return item != null && item instanceof IExpandable; + } + + private IExpandable getExpandableItem(int position) { + T item = getItem(position); + if (isExpandable(item)) { + return (IExpandable) item; + } else { + return null; + } + } + + /** + * Get the parent item position of the IExpandable item + * + * @return return the closest parent item position of the IExpandable. + * if the IExpandable item's level is 0, return itself position. + * if the item's level is negative which mean do not implement this, return a negative + * if the item is not exist in the data list, return a negative. + */ + public int getParentPosition(@NonNull T item) { + int position = getItemPosition(item); + if (position == -1) { + return -1; + } + + // if the item is IExpandable, return a closest IExpandable item position whose level smaller than this. + // if it is not, return the closest IExpandable item position whose level is not negative + int level; + if (item instanceof IExpandable) { + level = ((IExpandable) item).getLevel(); + } else { + level = Integer.MAX_VALUE; + } + if (level == 0) { + return position; + } else if (level == -1) { + return -1; + } + + for (int i = position; i >= 0; i--) { + T temp = mData.get(i); + if (temp instanceof IExpandable) { + IExpandable expandable = (IExpandable) temp; + if (expandable.getLevel() >= 0 && expandable.getLevel() < level) { + return i; + } + } + } + return -1; + } + + public boolean isFirstDataItem(int dataItemPosition) { + return dataItemPosition == 0; + } + + public boolean isLastDataItem(int dataItemPosition) { + return dataItemPosition == mData.size() - 1; + } + + public int getViewHolderPosition(int dataItemPosition) { + return getHeaderLayoutCount() + dataItemPosition; + } + + public int getBottomDataPosition() { + return getHeaderLayoutCount() + mData.size() - 1; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseSectionQuickAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseSectionQuickAdapter.java new file mode 100644 index 0000000..286e67a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/BaseSectionQuickAdapter.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter; + +import androidx.recyclerview.widget.RecyclerView; +import android.view.ViewGroup; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.entity.SectionEntity; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; + +import java.util.List; + +public abstract class BaseSectionQuickAdapter extends BaseQuickAdapter { + + + protected int mSectionHeadResId; + protected static final int SECTION_HEADER_VIEW = 0x00000444; + + /** + * Same as QuickAdapter#QuickAdapter(Context,int) but with + * some initialization data. + * + * @param sectionHeadResId The section head layout id for each item + * @param layoutResId The layout resource id of each item. + * @param data A new list is created out of this one to avoid mutable list + */ + public BaseSectionQuickAdapter(RecyclerView recyclerView, int layoutResId, int sectionHeadResId, List data) { + super(recyclerView, layoutResId, data); + this.mSectionHeadResId = sectionHeadResId; + } + + @Override + protected int getDefItemViewType(int position) { + return mData.get(position).isHeader ? SECTION_HEADER_VIEW : 0; + } + + @Override + protected K onCreateDefViewHolder(ViewGroup parent, int viewType) { + if (viewType == SECTION_HEADER_VIEW) + return createBaseViewHolder(getItemView(mSectionHeadResId, parent)); + + return super.onCreateDefViewHolder(parent, viewType); + } + + @Override + public void onBindViewHolder(K holder, int positions) { + switch (holder.getItemViewType()) { + case SECTION_HEADER_VIEW: + setFullSpan(holder); + convertHead(holder, mData.get(holder.getLayoutPosition() - getHeaderLayoutCount())); + break; + default: + super.onBindViewHolder(holder, positions); + break; + } + } + + protected abstract void convertHead(BaseViewHolder helper, T item); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/IRecyclerView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/IRecyclerView.java new file mode 100644 index 0000000..7018098 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/adapter/IRecyclerView.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter; + +/** + * Created by huangjun on 2016/12/8. + */ + +public interface IRecyclerView { + /** + * special view type + */ + int FETCHING_VIEW = 0x00001000; + int HEADER_VIEW = 0x00001001; + int LOADING_VIEW = 0x00001002; + int FOOTER_VIEW = 0x00001003; + int EMPTY_VIEW = 0x00001004; + + /** + * 获取Header item的数量(包含FetchItem) + */ + int getHeaderLayoutCount(); + + /** + * 获取Item视图类型 + * + * @param position Item位置 + * @return + */ + int getItemViewType(int position); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/AlphaInAnimation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/AlphaInAnimation.java new file mode 100644 index 0000000..914c9e5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/AlphaInAnimation.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.view.View; + +public class AlphaInAnimation implements BaseAnimation { + + private static final float DEFAULT_ALPHA_FROM = 0f; + private final float mFrom; + + public AlphaInAnimation() { + this(DEFAULT_ALPHA_FROM); + } + + public AlphaInAnimation(float from) { + mFrom = from; + } + + @Override + public Animator[] getAnimators(View view) { + return new Animator[]{ObjectAnimator.ofFloat(view, "alpha", mFrom, 1f)}; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/BaseAnimation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/BaseAnimation.java new file mode 100644 index 0000000..cd51181 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/BaseAnimation.java @@ -0,0 +1,10 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation; + +import android.animation.Animator; +import android.view.View; + +public interface BaseAnimation { + + Animator[] getAnimators(View view); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/ScaleInAnimation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/ScaleInAnimation.java new file mode 100644 index 0000000..cdd387d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/ScaleInAnimation.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.view.View; + +public class ScaleInAnimation implements BaseAnimation { + + private static final float DEFAULT_SCALE_FROM = .5f; + private final float mFrom; + + public ScaleInAnimation() { + this(DEFAULT_SCALE_FROM); + } + + public ScaleInAnimation(float from) { + mFrom = from; + } + + @Override + public Animator[] getAnimators(View view) { + ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", mFrom, 1f); + ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", mFrom, 1f); + return new ObjectAnimator[]{scaleX, scaleY}; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInBottomAnimation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInBottomAnimation.java new file mode 100644 index 0000000..4d75807 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInBottomAnimation.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.view.View; + +public class SlideInBottomAnimation implements BaseAnimation { + + @Override + public Animator[] getAnimators(View view) { + return new Animator[]{ + ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0) + }; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInLeftAnimation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInLeftAnimation.java new file mode 100644 index 0000000..e16d8e0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInLeftAnimation.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.view.View; + +public class SlideInLeftAnimation implements BaseAnimation { + + @Override + public Animator[] getAnimators(View view) { + return new Animator[]{ + ObjectAnimator.ofFloat(view, "translationX", -view.getRootView().getWidth(), 0) + }; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInRightAnimation.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInRightAnimation.java new file mode 100644 index 0000000..ade32a7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/animation/SlideInRightAnimation.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.animation; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.view.View; + +public class SlideInRightAnimation implements BaseAnimation { + + @Override + public Animator[] getAnimators(View view) { + return new Animator[]{ + ObjectAnimator.ofFloat(view, "translationX", view.getRootView().getWidth(), 0) + }; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/callback/ItemDragAndSwipeCallback.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/callback/ItemDragAndSwipeCallback.java new file mode 100644 index 0000000..4ebbbbd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/callback/ItemDragAndSwipeCallback.java @@ -0,0 +1,195 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.callback; + +import android.graphics.Canvas; +import android.view.View; + +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseItemDraggableAdapter; +import com.netease.nim.uikit.R; + +public class ItemDragAndSwipeCallback extends ItemTouchHelper.Callback { + +// private static final String TAG = ItemDragAndSwipeCallback.class.getSimpleName(); + + BaseItemDraggableAdapter mAdapter; + + float mMoveThreshold = 0.1f; + float mSwipeThreshold = 0.7f; + + int mDragMoveFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; + int mSwipeMoveFlags = ItemTouchHelper.END; + + public ItemDragAndSwipeCallback(BaseItemDraggableAdapter adapter) { + mAdapter = adapter; + } + + @Override + public boolean isLongPressDragEnabled() { + return false; + } + + @Override + public boolean isItemViewSwipeEnabled() { + return mAdapter.isItemSwipeEnable(); + } + + @Override + public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { + if (actionState == ItemTouchHelper.ACTION_STATE_DRAG + && !isViewCreateByAdapter(viewHolder)) { + mAdapter.onItemDragStart(viewHolder); + viewHolder.itemView.setTag(R.id.BaseQuickAdapter_dragging_support, true); + } else if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE + && !isViewCreateByAdapter(viewHolder)) { + mAdapter.onItemSwipeStart(viewHolder); + viewHolder.itemView.setTag(R.id.BaseQuickAdapter_swiping_support, true); + } + super.onSelectedChanged(viewHolder, actionState); + } + + @Override + public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + super.clearView(recyclerView, viewHolder); + if (isViewCreateByAdapter(viewHolder)) { + return; + } + + if (viewHolder.itemView.getTag(R.id.BaseQuickAdapter_dragging_support) != null + && (Boolean) viewHolder.itemView.getTag(R.id.BaseQuickAdapter_dragging_support)) { + mAdapter.onItemDragEnd(viewHolder); + viewHolder.itemView.setTag(R.id.BaseQuickAdapter_dragging_support, false); + } + if (viewHolder.itemView.getTag(R.id.BaseQuickAdapter_swiping_support) != null + && (Boolean) viewHolder.itemView.getTag(R.id.BaseQuickAdapter_swiping_support)) { + mAdapter.onItemSwipeClear(viewHolder); + viewHolder.itemView.setTag(R.id.BaseQuickAdapter_swiping_support, false); + } + } + + @Override + public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + if (isViewCreateByAdapter(viewHolder)) { + return makeMovementFlags(0, 0); + } + + return makeMovementFlags(mDragMoveFlags, mSwipeMoveFlags); + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { + if (source.getItemViewType() != target.getItemViewType()) { + return false; + } else { + return true; + } + } + + @Override + public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder source, int fromPos, RecyclerView.ViewHolder target, int toPos, int x, int y) { + mAdapter.onItemDragMoving(source, target); + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + if (!isViewCreateByAdapter(viewHolder)) { + mAdapter.onItemSwiped(viewHolder); + } + } + + @Override + public float getMoveThreshold(RecyclerView.ViewHolder viewHolder) { + return mMoveThreshold; + } + + @Override + public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) { + return mSwipeThreshold; + } + + /** + * Set the fraction that the user should move the View to be considered as swiped. + * The fraction is calculated with respect to RecyclerView's bounds. + *

+ * Default value is .5f, which means, to swipe a View, user must move the View at least + * half of RecyclerView's width or height, depending on the swipe direction. + * + * @param swipeThreshold A float value that denotes the fraction of the View size. Default value + * is .8f . + */ + public void setSwipeThreshold(float swipeThreshold) { + mSwipeThreshold = swipeThreshold; + } + + + /** + * Set the fraction that the user should move the View to be considered as it is + * dragged. After a view is moved this amount, ItemTouchHelper starts checking for Views + * below it for a possible drop. + * + * @param moveThreshold A float value that denotes the fraction of the View size. Default value is + * .1f . + */ + public void setMoveThreshold(float moveThreshold) { + mMoveThreshold = moveThreshold; + } + + /** + *

Set the drag movement direction.

+ *

The value should be ItemTouchHelper.UP, ItemTouchHelper.DOWN, ItemTouchHelper.LEFT, ItemTouchHelper.RIGHT or their combination.

+ * You can combine them like ItemTouchHelper.UP | ItemTouchHelper.DOWN, it means that the item could only move up and down when dragged. + * + * @param dragMoveFlags the drag movement direction. Default value is ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT. + */ + public void setDragMoveFlags(int dragMoveFlags) { + mDragMoveFlags = dragMoveFlags; + } + + /** + *

Set the swipe movement direction.

+ *

The value should be ItemTouchHelper.START, ItemTouchHelper.END or their combination.

+ * You can combine them like ItemTouchHelper.START | ItemTouchHelper.END, it means that the item could swipe to both left or right. + * + * @param swipeMoveFlags the swipe movement direction. Default value is ItemTouchHelper.END. + */ + public void setSwipeMoveFlags(int swipeMoveFlags) { + mSwipeMoveFlags = swipeMoveFlags; + } + + @Override + public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + + if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE + && !isViewCreateByAdapter(viewHolder)) { + View itemView = viewHolder.itemView; + + c.save(); + if (dX > 0) { + c.clipRect(itemView.getLeft(), itemView.getTop(), + itemView.getLeft() + dX, itemView.getBottom()); + c.translate(itemView.getLeft(), itemView.getTop()); + } else { + c.clipRect(itemView.getRight() + dX, itemView.getTop(), + itemView.getRight(), itemView.getBottom()); + c.translate(itemView.getRight() + dX, itemView.getTop()); + } + + mAdapter.onItemSwiping(c, viewHolder, dX, dY, isCurrentlyActive); + c.restore(); + + } + } + + private boolean isViewCreateByAdapter(RecyclerView.ViewHolder viewHolder) { + int type = viewHolder.getItemViewType(); + if (type == mAdapter.HEADER_VIEW || type == mAdapter.LOADING_VIEW + || type == mAdapter.FOOTER_VIEW || type == mAdapter.EMPTY_VIEW) { + return true; + } + return false; + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/decoration/DividerItemDecoration.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/decoration/DividerItemDecoration.java new file mode 100644 index 0000000..473ddc6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/decoration/DividerItemDecoration.java @@ -0,0 +1,108 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.decoration; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * Created by hzchenkang on 2016/12/2. + */ + +public class DividerItemDecoration extends RecyclerView.ItemDecoration { + private static final int[] ATTRS = new int[]{ + android.R.attr.listDivider + }; + + public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; + + public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; + + private Drawable mDivider; + + private int mOrientation; + + public DividerItemDecoration(Context context, int orientation) { + final TypedArray a = context.obtainStyledAttributes(ATTRS); + mDivider = a.getDrawable(0); + a.recycle(); + setOrientation(orientation); + } + + public void setOrientation(int orientation) { + if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { + throw new IllegalArgumentException("invalid orientation"); + } + mOrientation = orientation; + } + + @Override + public void onDraw(Canvas c, RecyclerView parent) { + + if (mOrientation == VERTICAL_LIST) { + drawVertical(c, parent); + } else { + drawHorizontal(c, parent); + } + } + + protected boolean needDrawDecoration(RecyclerView parent, int position) { + return true; + } + + public void drawVertical(Canvas c, RecyclerView parent) { + final int left = parent.getPaddingLeft(); + final int right = parent.getWidth() - parent.getPaddingRight(); + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + if (!needDrawDecoration(parent, i)) { + continue; + } + final View child = parent.getChildAt(i); + RecyclerView v = new RecyclerView(parent.getContext()); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child + .getLayoutParams(); + final int top = child.getBottom() + params.bottomMargin; + final int bottom = top + mDivider.getIntrinsicHeight(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + public void drawHorizontal(Canvas c, RecyclerView parent) { + final int top = parent.getPaddingTop(); + final int bottom = parent.getHeight() - parent.getPaddingBottom(); + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + if (!needDrawDecoration(parent, i)) { + continue; + } + final View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child + .getLayoutParams(); + final int left = child.getRight() + params.rightMargin; + final int right = left + mDivider.getIntrinsicHeight(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + @Override + public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { + if (!needDrawDecoration(parent, itemPosition)) { + return; + } + if (mOrientation == VERTICAL_LIST) { + outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); + } else { + outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/decoration/SpacingDecoration.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/decoration/SpacingDecoration.java new file mode 100644 index 0000000..82db3f5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/decoration/SpacingDecoration.java @@ -0,0 +1,73 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.decoration; + +import android.graphics.Rect; +import android.view.View; + +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +/** + * Created by huangjun on 2016/12/9. + */ +public class SpacingDecoration extends RecyclerView.ItemDecoration { + private int mHorizontalSpacing = 0; + private int mVerticalSpacing = 0; + private boolean mIncludeEdge = false; + + public SpacingDecoration(int hSpacing, int vSpacing, boolean includeEdge) { + mHorizontalSpacing = hSpacing; + mVerticalSpacing = vSpacing; + mIncludeEdge = includeEdge; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + // Only handle the vertical situation + int position = parent.getChildAdapterPosition(view); + if (parent.getLayoutManager() instanceof GridLayoutManager) { + GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager(); + int spanCount = layoutManager.getSpanCount(); + int column = position % spanCount; + getGridItemOffsets(outRect, position, column, spanCount); + } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) parent.getLayoutManager(); + int spanCount = layoutManager.getSpanCount(); + StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); + int column = lp.getSpanIndex(); + getGridItemOffsets(outRect, position, column, spanCount); + } else if (parent.getLayoutManager() instanceof LinearLayoutManager) { + outRect.left = mHorizontalSpacing; + outRect.right = mHorizontalSpacing; + if (mIncludeEdge) { + if (position == 0) { + outRect.top = mVerticalSpacing; + } + outRect.bottom = mVerticalSpacing; + } else { + if (position > 0) { + outRect.top = mVerticalSpacing; + } + } + } + } + + private void getGridItemOffsets(Rect outRect, int position, int column, int spanCount) { + if (mIncludeEdge) { + outRect.left = mHorizontalSpacing * (spanCount - column) / spanCount; + outRect.right = mHorizontalSpacing * (column + 1) / spanCount; + if (position < spanCount) { + outRect.top = mVerticalSpacing; + } + outRect.bottom = mVerticalSpacing; + } else { + outRect.left = mHorizontalSpacing * column / spanCount; + outRect.right = mHorizontalSpacing * (spanCount - 1 - column) / spanCount; + if (position >= spanCount) { + outRect.top = mVerticalSpacing; + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/AbstractExpandableItem.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/AbstractExpandableItem.java new file mode 100644 index 0000000..4700818 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/AbstractExpandableItem.java @@ -0,0 +1,79 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.entity; + +import java.util.ArrayList; +import java.util.List; + +/** + *

A helper to implement expandable item.

+ *

if you don't want to extent a class, you can also implement the interface IExpandable

+ */ +public abstract class AbstractExpandableItem implements IExpandable { + protected boolean mExpandable = false; + protected List mSubItems; + + @Override + public boolean isExpanded() { + return mExpandable; + } + + @Override + public void setExpanded(boolean expanded) { + mExpandable = expanded; + } + + @Override + public List getSubItems() { + return mSubItems; + } + + public boolean hasSubItem() { + return mSubItems != null && mSubItems.size() > 0; + } + + public void setSubItems(List list) { + mSubItems = list; + } + + public T getSubItem(int position) { + if (hasSubItem() && position < mSubItems.size()) { + return mSubItems.get(position); + } else { + return null; + } + } + + public int getSubItemPosition(T subItem) { + return mSubItems != null ? mSubItems.indexOf(subItem) : -1; + } + + public void addSubItem(T subItem) { + if (mSubItems == null) { + mSubItems = new ArrayList<>(); + } + mSubItems.add(subItem); + } + + public void addSubItem(int position, T subItem) { + if (mSubItems != null && position >= 0 && position < mSubItems.size()) { + mSubItems.add(position, subItem); + } else { + addSubItem(subItem); + } + } + + public boolean contains(T subItem) { + return mSubItems != null && mSubItems.contains(subItem); + } + + public boolean removeSubItem(T subItem) { + return mSubItems != null && mSubItems.remove(subItem); + } + + public boolean removeSubItem(int position) { + if (mSubItems != null && position >= 0 && position < mSubItems.size()) { + mSubItems.remove(position); + return true; + } + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/IExpandable.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/IExpandable.java new file mode 100644 index 0000000..c0d4ea7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/IExpandable.java @@ -0,0 +1,20 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.entity; + +import java.util.List; + +/** + * implement the interface if the item is expandable + */ +public interface IExpandable { + boolean isExpanded(); + + void setExpanded(boolean expanded); + + List getSubItems(); + + /** + * Get the level of this item. The level start from 0. + * If you don't care about the level, just return a negative. + */ + int getLevel(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/MultiItemEntity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/MultiItemEntity.java new file mode 100644 index 0000000..35c7cee --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/MultiItemEntity.java @@ -0,0 +1,7 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.entity; + +public interface MultiItemEntity { + + int getItemType(); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/SectionEntity.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/SectionEntity.java new file mode 100644 index 0000000..4d234d9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/entity/SectionEntity.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.entity; + +public abstract class SectionEntity { + public boolean isHeader; + public T t; + public String header; + + public SectionEntity(boolean isHeader, String header) { + this.isHeader = isHeader; + this.header = header; + this.t = null; + } + + public SectionEntity(T t) { + this.isHeader = false; + this.header = null; + this.t = t; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/holder/BaseViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/holder/BaseViewHolder.java new file mode 100644 index 0000000..4e1bd27 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/holder/BaseViewHolder.java @@ -0,0 +1,515 @@ +/** + * Copyright 2013 Joan Zapata + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.util.Linkify; +import android.util.SparseArray; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.widget.Adapter; +import android.widget.AdapterView; +import android.widget.CheckedTextView; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.RatingBar; +import android.widget.TextView; + +import androidx.annotation.DrawableRes; +import androidx.annotation.StringRes; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.HashSet; +import java.util.LinkedHashSet; + +public class BaseViewHolder extends RecyclerView.ViewHolder { + + /** + * Views indexed with their IDs + */ + private final SparseArray views; + + private final LinkedHashSet childClickViewIds; + private final LinkedHashSet itemChildLongClickViewIds; + + + public View convertView; + + /** + * Package private field to retain the associated user object and detect a change + */ + Object associatedObject; + + + public BaseViewHolder(View view) { + super(view); + this.views = new SparseArray(); + this.childClickViewIds = new LinkedHashSet<>(); + this.itemChildLongClickViewIds = new LinkedHashSet<>(); + convertView = view; + + } + + public HashSet getItemChildLongClickViewIds() { + return itemChildLongClickViewIds; + } + + public HashSet getChildClickViewIds() { + return childClickViewIds; + } + + public View getConvertView() { + return convertView; + } + + /** + * Will set the text of a TextView. + * + * @param viewId The view id. + * @param value The text to put in the text view. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setText(int viewId, CharSequence value) { + TextView view = getView(viewId); + view.setText(value); + return this; + } + + public BaseViewHolder setText(int viewId, @StringRes int strId) { + TextView view = getView(viewId); + view.setText(strId); + return this; + } + + /** + * Will set the image of an ImageView from a resource id. + * + * @param viewId The view id. + * @param imageResId The image resource id. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setImageResource(int viewId, @DrawableRes int imageResId) { + ImageView view = getView(viewId); + view.setImageResource(imageResId); + return this; + } + + /** + * Will set background color of a view. + * + * @param viewId The view id. + * @param color A color, not a resource id. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setBackgroundColor(int viewId, int color) { + View view = getView(viewId); + view.setBackgroundColor(color); + return this; + } + + /** + * Will set background of a view. + * + * @param viewId The view id. + * @param backgroundRes A resource to use as a background. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setBackgroundRes(int viewId, @DrawableRes int backgroundRes) { + View view = getView(viewId); + view.setBackgroundResource(backgroundRes); + return this; + } + + /** + * Will set text color of a TextView. + * + * @param viewId The view id. + * @param textColor The text color (not a resource id). + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setTextColor(int viewId, int textColor) { + TextView view = getView(viewId); + view.setTextColor(textColor); + return this; + } + + + /** + * Will set the image of an ImageView from a drawable. + * + * @param viewId The view id. + * @param drawable The image drawable. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setImageDrawable(int viewId, Drawable drawable) { + ImageView view = getView(viewId); + view.setImageDrawable(drawable); + return this; + } + + /** + * Add an action to set the image of an image view. Can be called multiple times. + */ + public BaseViewHolder setImageBitmap(int viewId, Bitmap bitmap) { + ImageView view = getView(viewId); + view.setImageBitmap(bitmap); + return this; + } + + /** + * Add an action to set the alpha of a view. Can be called multiple times. + * Alpha between 0-1. + */ + public BaseViewHolder setAlpha(int viewId, float value) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + getView(viewId).setAlpha(value); + } else { + // Pre-honeycomb hack to set Alpha value + AlphaAnimation alpha = new AlphaAnimation(value, value); + alpha.setDuration(0); + alpha.setFillAfter(true); + getView(viewId).startAnimation(alpha); + } + return this; + } + + /** + * Set a view visibility to VISIBLE (true) or GONE (false). + * + * @param viewId The view id. + * @param visible True for VISIBLE, false for GONE. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setVisible(int viewId, boolean visible) { + View view = getView(viewId); + view.setVisibility(visible ? View.VISIBLE : View.GONE); + return this; + } + + /** + * Add links into a TextView. + * + * @param viewId The id of the TextView to linkify. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder linkify(int viewId) { + TextView view = getView(viewId); + Linkify.addLinks(view, Linkify.ALL); + return this; + } + + /** + * Apply the typeface to the given viewId, and enable subpixel rendering. + */ + public BaseViewHolder setTypeface(int viewId, Typeface typeface) { + TextView view = getView(viewId); + view.setTypeface(typeface); + view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); + return this; + } + + /** + * Apply the typeface to all the given viewIds, and enable subpixel rendering. + */ + public BaseViewHolder setTypeface(Typeface typeface, int... viewIds) { + for (int viewId : viewIds) { + TextView view = getView(viewId); + view.setTypeface(typeface); + view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); + } + return this; + } + + /** + * Sets the progress of a ProgressBar. + * + * @param viewId The view id. + * @param progress The progress. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setProgress(int viewId, int progress) { + ProgressBar view = getView(viewId); + view.setProgress(progress); + return this; + } + + /** + * Sets the progress and max of a ProgressBar. + * + * @param viewId The view id. + * @param progress The progress. + * @param max The max value of a ProgressBar. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setProgress(int viewId, int progress, int max) { + ProgressBar view = getView(viewId); + view.setMax(max); + view.setProgress(progress); + return this; + } + + /** + * Sets the range of a ProgressBar to 0...max. + * + * @param viewId The view id. + * @param max The max value of a ProgressBar. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setMax(int viewId, int max) { + ProgressBar view = getView(viewId); + view.setMax(max); + return this; + } + + /** + * Sets the rating (the number of stars filled) of a RatingBar. + * + * @param viewId The view id. + * @param rating The rating. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setRating(int viewId, float rating) { + RatingBar view = getView(viewId); + view.setRating(rating); + return this; + } + + /** + * Sets the rating (the number of stars filled) and max of a RatingBar. + * + * @param viewId The view id. + * @param rating The rating. + * @param max The range of the RatingBar to 0...max. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setRating(int viewId, float rating, int max) { + RatingBar view = getView(viewId); + view.setMax(max); + view.setRating(rating); + return this; + } + + /** + * Sets the on click listener of the view. + * + * @param viewId The view id. + * @param listener The on click listener; + * @return The BaseViewHolder for chaining. + */ + @Deprecated + public BaseViewHolder setOnClickListener(int viewId, View.OnClickListener listener) { + View view = getView(viewId); + view.setOnClickListener(listener); + return this; + } + + /** + * add childView id + * + * @param viewId add the child view id can support childview click + * @return + */ + public BaseViewHolder addOnClickListener(int viewId) { + childClickViewIds.add(viewId); + return this; + } + + /** + * add long click view id + * + * @param viewId + * @return + */ + public BaseViewHolder addOnLongClickListener(int viewId) { + itemChildLongClickViewIds.add(viewId); + return this; + } + + + /** + * Sets the on touch listener of the view. + * + * @param viewId The view id. + * @param listener The on touch listener; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnTouchListener(int viewId, View.OnTouchListener listener) { + View view = getView(viewId); + view.setOnTouchListener(listener); + return this; + } + + /** + * Sets the on long click listener of the view. + * + * @param viewId The view id. + * @param listener The on long click listener; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) { + View view = getView(viewId); + view.setOnLongClickListener(listener); + return this; + } + + /** + * Sets the listview or gridview's item click listener of the view + * + * @param viewId The view id. + * @param listener The item on click listener; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnItemClickListener(int viewId, AdapterView.OnItemClickListener listener) { + AdapterView view = getView(viewId); + view.setOnItemClickListener(listener); + return this; + } + + /** + * Sets the listview or gridview's item long click listener of the view + * + * @param viewId The view id. + * @param listener The item long click listener; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnItemLongClickListener(int viewId, AdapterView.OnItemLongClickListener listener) { + AdapterView view = getView(viewId); + view.setOnItemLongClickListener(listener); + return this; + } + + /** + * Sets the listview or gridview's item selected click listener of the view + * + * @param viewId The view id. + * @param listener The item selected click listener; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnItemSelectedClickListener(int viewId, AdapterView.OnItemSelectedListener listener) { + AdapterView view = getView(viewId); + view.setOnItemSelectedListener(listener); + return this; + } + + /** + * Sets the on checked change listener of the view. + * + * @param viewId The view id. + * @param listener The checked change listener of compound button. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnCheckedChangeListener(int viewId, CompoundButton.OnCheckedChangeListener listener) { + CompoundButton view = getView(viewId); + view.setOnCheckedChangeListener(listener); + return this; + } + + /** + * Sets the tag of the view. + * + * @param viewId The view id. + * @param tag The tag; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setTag(int viewId, Object tag) { + View view = getView(viewId); + view.setTag(tag); + return this; + } + + /** + * Sets the tag of the view. + * + * @param viewId The view id. + * @param key The key of tag; + * @param tag The tag; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setTag(int viewId, int key, Object tag) { + View view = getView(viewId); + view.setTag(key, tag); + return this; + } + + /** + * Sets the checked status of a checkable. + * + * @param viewId The view id. + * @param checked The checked status; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setChecked(int viewId, boolean checked) { + View view = getView(viewId); + // View unable cast to Checkable + if (view instanceof CompoundButton) { + ((CompoundButton) view).setChecked(checked); + } else if (view instanceof CheckedTextView) { + ((CheckedTextView) view).setChecked(checked); + } + return this; + } + + /** + * Sets the adapter of a adapter view. + * + * @param viewId The view id. + * @param adapter The adapter; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setAdapter(int viewId, Adapter adapter) { + AdapterView view = getView(viewId); + view.setAdapter(adapter); + return this; + } + + @SuppressWarnings("unchecked") + public T getView(int viewId) { + View view = views.get(viewId); + if (view == null) { + view = convertView.findViewById(viewId); + views.put(viewId, view); + } + return (T) view; + } + + /** + * Retrieves the last converted object on this view. + */ + public Object getAssociatedObject() { + return associatedObject; + } + + /** + * Should be called during convert + */ + public void setAssociatedObject(Object associatedObject) { + this.associatedObject = associatedObject; + } + + public Context getContext() { + if (convertView == null) { + return null; + } + + return convertView.getContext(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/holder/RecyclerViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/holder/RecyclerViewHolder.java new file mode 100644 index 0000000..d3dfb41 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/holder/RecyclerViewHolder.java @@ -0,0 +1,21 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder; + +import androidx.recyclerview.widget.RecyclerView; + +/** + * Created by huangjun on 2016/12/11. + */ + +public abstract class RecyclerViewHolder { + final private T adapter; + + public RecyclerViewHolder(T adapter) { + this.adapter = adapter; + } + + public T getAdapter() { + return adapter; + } + + public abstract void convert(V holder, K data, int position, boolean isScrolling); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemChildClickListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemChildClickListener.java new file mode 100644 index 0000000..3a677cb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemChildClickListener.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener; + +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.IRecyclerView; + +/** + * A convenience class to extend when you only want to OnItemChildClickListener for a subset + * of all the SimpleClickListener. This implements all methods in the + * {@link SimpleClickListener} + **/ + +public abstract class OnItemChildClickListener extends SimpleClickListener { + + @Override + public void onItemClick(T adapter, View view, int position) { + + } + + @Override + public void onItemLongClick(T adapter, View view, int position) { + + } + + @Override + public void onItemChildLongClick(T adapter, View view, int position) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemChildLongClickListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemChildLongClickListener.java new file mode 100644 index 0000000..9f8adbd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemChildLongClickListener.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener; + +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.IRecyclerView; + +/** + * A convenience class to extend when you only want to OnItemChildLongClickListener for a subset + * of all the SimpleClickListener. This implements all methods in the + * {@link SimpleClickListener} + **/ +public abstract class OnItemChildLongClickListener extends SimpleClickListener { + + @Override + public void onItemClick(T adapter, View view, int position) { + + } + + @Override + public void onItemLongClick(T adapter, View view, int position) { + + } + + @Override + public void onItemChildClick(T adapter, View view, int position) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemClickListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemClickListener.java new file mode 100644 index 0000000..81b6544 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemClickListener.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener; + +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.IRecyclerView; + + +/** + * A convenience class to extend when you only want to OnItemClickListener for a subset + * of all the SimpleClickListener. This implements all methods in the + * {@link SimpleClickListener} + */ +public abstract class OnItemClickListener extends SimpleClickListener { + + @Override + public void onItemLongClick(T adapter, View view, int position) { + + } + + @Override + public void onItemChildClick(T adapter, View view, int position) { + + } + + @Override + public void onItemChildLongClick(T adapter, View view, int position) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemDragListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemDragListener.java new file mode 100644 index 0000000..920c685 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemDragListener.java @@ -0,0 +1,12 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener; + +import androidx.recyclerview.widget.RecyclerView; + +public interface OnItemDragListener { + void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos); + + void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to); + + void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemLongClickListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemLongClickListener.java new file mode 100644 index 0000000..6fb4bb8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemLongClickListener.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener; + +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.IRecyclerView; + +public abstract class OnItemLongClickListener extends SimpleClickListener { + + @Override + public void onItemClick(T adapter, View view, int position) { + + } + + @Override + public void onItemChildClick(T adapter, View view, int position) { + + } + + @Override + public void onItemChildLongClick(T adapter, View view, int position) { + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemSwipeListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemSwipeListener.java new file mode 100644 index 0000000..72c0a9e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/OnItemSwipeListener.java @@ -0,0 +1,39 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener; + +import android.graphics.Canvas; +import androidx.recyclerview.widget.RecyclerView; + +public interface OnItemSwipeListener { + + /** + * Called when the swipe action start. + */ + void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos); + + /** + * Called when the swipe action is over. + * If you change the view on the start, you should reset is here, no matter the item has swiped or not. + * + * @param pos If the view is swiped, pos will be negative. + */ + void clearView(RecyclerView.ViewHolder viewHolder, int pos); + + /** + * Called when item is swiped, the view is going to be removed from the adapter. + */ + void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos); + + /** + * Draw on the empty edge when swipe moving + * + * @param canvas the empty edge's canvas + * @param viewHolder The ViewHolder which is being interacted by the User or it was + * interacted and simply animating to its original position + * @param dX The amount of horizontal displacement caused by user's action + * @param dY The amount of vertical displacement caused by user's action + * @param isCurrentlyActive True if this view is currently being controlled by the user or + * false it is simply animating back to its original state. + */ + void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float dX, float dY, boolean isCurrentlyActive); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/SimpleClickListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/SimpleClickListener.java new file mode 100644 index 0000000..3086a4f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/listener/SimpleClickListener.java @@ -0,0 +1,308 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.listener; + +import android.os.Build; +import androidx.core.view.GestureDetectorCompat; +import androidx.recyclerview.widget.RecyclerView; +import android.view.GestureDetector; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.IRecyclerView; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; + +import java.util.Iterator; +import java.util.Set; + +/** + * This can be useful for applications that wish to implement various forms of click and longclick and childView click + * manipulation of item views within the RecyclerView. SimpleClickListener may intercept + * a touch interaction already in progress even if the SimpleClickListener is already handling that + * gesture stream itself for the purposes of scrolling. + * + * @see RecyclerView.OnItemTouchListener + */ +public abstract class SimpleClickListener implements RecyclerView.OnItemTouchListener { + private GestureDetectorCompat mGestureDetector; + private RecyclerView recyclerView; + private Set childClickViewIds; + private Set longClickViewIds; + protected T baseAdapter; + public static String TAG = "SimpleClickListener"; + private boolean mIsPrepressed = false; + private boolean mIsShowPress = false; + private View mPressedView = null; + private boolean shouldDetectGesture = true; + private int longClickDelta = 200; + + @Override + public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { + if (!shouldDetectGesture()) { + return false; // 拦截手势检测 + } + + // 手势检测 + if (recyclerView == null) { + this.recyclerView = rv; + this.baseAdapter = (T) recyclerView.getAdapter(); + mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(), new ItemTouchHelperGestureListener(recyclerView)); + } + if (!mGestureDetector.onTouchEvent(e) && e.getActionMasked() == MotionEvent.ACTION_UP && mIsShowPress) { + if (mPressedView != null) { + BaseViewHolder vh = (BaseViewHolder) recyclerView.getChildViewHolder(mPressedView); + if (vh == null || vh.getItemViewType() != IRecyclerView.LOADING_VIEW || vh.getItemViewType() != IRecyclerView.FETCHING_VIEW) { + mPressedView.setPressed(false); + } + mPressedView = null; + } + mIsShowPress = false; + mIsPrepressed = false; + } + + return false; + } + + @Override + public void onTouchEvent(RecyclerView rv, MotionEvent e) { + if (!shouldDetectGesture()) { + return; + } + + mGestureDetector.onTouchEvent(e); + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + } + + private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener { + + private RecyclerView recyclerView; + + public ItemTouchHelperGestureListener(RecyclerView recyclerView) { + this.recyclerView = recyclerView; + } + + @Override + public boolean onDown(MotionEvent e) { + if (!shouldDetectGesture()) { + return false; + } + + mIsPrepressed = true; + mPressedView = recyclerView.findChildViewUnder(e.getX(), e.getY()); + + super.onDown(e); + return false; + } + + @Override + public void onShowPress(MotionEvent e) { + if (!shouldDetectGesture()) { + return; + } + + if (mIsPrepressed && mPressedView != null) { +// mPressedView.setPressed(true); + mIsShowPress = true; + } + super.onShowPress(e); + } + + @Override + public boolean onSingleTapUp(MotionEvent e) { + if (!shouldDetectGesture()) { + return false; + } + + if (mIsPrepressed && mPressedView != null) { + final View pressedView = mPressedView; + BaseViewHolder vh = (BaseViewHolder) recyclerView.getChildViewHolder(pressedView); + + if (isHeaderOrFooterPosition(vh.getLayoutPosition())) { + return false; + } + childClickViewIds = vh.getChildClickViewIds(); + + if (childClickViewIds != null && childClickViewIds.size() > 0) { + for (Iterator it = childClickViewIds.iterator(); it.hasNext(); ) { + View childView = pressedView.findViewById((Integer) it.next()); + if (inRangeOfView(childView, e) && childView.isEnabled()) { + setPressViewHotSpot(e, childView); + childView.setPressed(true); + onItemChildClick(baseAdapter, childView, vh.getLayoutPosition() - baseAdapter.getHeaderLayoutCount()); + resetPressedView(childView); + return true; + } else { + childView.setPressed(false); + } + } + setPressViewHotSpot(e, pressedView); + mPressedView.setPressed(true); + for (Iterator it = childClickViewIds.iterator(); it.hasNext(); ) { + View childView = pressedView.findViewById((Integer) it.next()); + childView.setPressed(false); + } + onItemClick(baseAdapter, pressedView, vh.getLayoutPosition() - baseAdapter.getHeaderLayoutCount()); + } else { + setPressViewHotSpot(e, pressedView); + mPressedView.setPressed(true); + for (Iterator it = childClickViewIds.iterator(); it.hasNext(); ) { + View childView = pressedView.findViewById((Integer) it.next()); + childView.setPressed(false); + } + onItemClick(baseAdapter, pressedView, vh.getLayoutPosition() - baseAdapter.getHeaderLayoutCount()); + } + resetPressedView(pressedView); + + } + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + if (!shouldDetectGesture()) { + return; + } + + boolean isChildLongClick = false; + if (mIsPrepressed && mPressedView != null) { + mPressedView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + BaseViewHolder vh = (BaseViewHolder) recyclerView.getChildViewHolder(mPressedView); + if (!isHeaderOrFooterPosition(vh.getLayoutPosition())) { + longClickViewIds = vh.getItemChildLongClickViewIds(); + if (longClickViewIds != null && longClickViewIds.size() > 0) { + for (Iterator it = longClickViewIds.iterator(); it.hasNext(); ) { + View childView = mPressedView.findViewById((Integer) it.next()); + if (inRangeOfView(childView, e) && childView.isEnabled()) { + setPressViewHotSpot(e, childView); + onItemChildLongClick(baseAdapter, childView, vh.getLayoutPosition() - baseAdapter.getHeaderLayoutCount()); + childView.setPressed(true); + mIsShowPress = true; + isChildLongClick = true; + break; + } + } + } + if (!isChildLongClick) { + onItemLongClick(baseAdapter, mPressedView, vh.getLayoutPosition() - baseAdapter.getHeaderLayoutCount()); + setPressViewHotSpot(e, mPressedView); + mPressedView.setPressed(true); + for (Iterator it = longClickViewIds.iterator(); it.hasNext(); ) { + View childView = mPressedView.findViewById((Integer) it.next()); + childView.setPressed(false); + } + mIsShowPress = true; + } + } + } + } + + private final void resetPressedView(final View pressedView) { + if (pressedView != null) { + pressedView.postDelayed(new Runnable() { + @Override + public void run() { + if (pressedView != null) { + pressedView.setPressed(false); + } + } + }, longClickDelta); + } + + mIsPrepressed = false; + mPressedView = null; + } + } + + private void setPressViewHotSpot(final MotionEvent e, final View mPressedView) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + /** + * when click Outside the region ,mPressedView is null + */ + if (mPressedView != null && mPressedView.getBackground() != null) { + mPressedView.getBackground().setHotspot(e.getRawX(), e.getY() - mPressedView.getY()); + } + } + } + + /** + * Callback method to be invoked when an item in this AdapterView has + * been clicked. + * + * @param view The view within the AdapterView that was clicked (this + * will be a view provided by the adapter) + * @param position The position of the view in the adapter. + */ + public abstract void onItemClick(T adapter, View view, int position); + + /** + * callback method to be invoked when an item in this view has been + * click and held + * + * @param view The view whihin the AbsListView that was clicked + * @param position The position of the view int the adapter + * @return true if the callback consumed the long click ,false otherwise + */ + public abstract void onItemLongClick(T adapter, View view, int position); + + public abstract void onItemChildClick(T adapter, View view, int position); + + public abstract void onItemChildLongClick(T adapter, View view, int position); + + public boolean inRangeOfView(View view, MotionEvent ev) { + int[] location = new int[2]; + if (view.getVisibility() != View.VISIBLE) { + return false; + } + view.getLocationOnScreen(location); + int x = location[0]; + int y = location[1]; + if (ev.getRawX() < x + || ev.getRawX() > (x + view.getWidth()) + || ev.getRawY() < y + || ev.getRawY() > (y + view.getHeight())) { + return false; + } + return true; + } + + private boolean isHeaderOrFooterPosition(int position) { + /** + * have a headview and EMPTY_VIEW FOOTER_VIEW LOADING_VIEW + */ + if (baseAdapter == null) { + if (recyclerView != null) { + baseAdapter = (T) recyclerView.getAdapter(); + } else { + return false; + } + } + int type = baseAdapter.getItemViewType(position); + return (type == IRecyclerView.EMPTY_VIEW || type == IRecyclerView.HEADER_VIEW || type == IRecyclerView.FOOTER_VIEW + || type == IRecyclerView.LOADING_VIEW || type == IRecyclerView.FETCHING_VIEW); + } + + public void setShouldDetectGesture(boolean shouldDetectGesture) { + this.shouldDetectGesture = shouldDetectGesture; + } + + private boolean shouldDetectGesture() { + if (!shouldDetectGesture) { + mIsPrepressed = false; + mPressedView = null; + } + + return shouldDetectGesture; + } + + public void setLongClickDelta(int longClickDelta) { + if (longClickDelta <= 0 || longClickDelta > 2000) { + longClickDelta = 200; + } + + this.longClickDelta = longClickDelta; + } +} + + diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/LoadMoreView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/LoadMoreView.java new file mode 100644 index 0000000..a48d407 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/LoadMoreView.java @@ -0,0 +1,120 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore; + + +import androidx.annotation.IdRes; +import androidx.annotation.LayoutRes; + +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; + +public abstract class LoadMoreView { + + public static final int STATUS_DEFAULT = 1; + public static final int STATUS_LOADING = 2; + public static final int STATUS_FAIL = 3; + public static final int STATUS_END = 4; + + private int mLoadMoreStatus = STATUS_DEFAULT; + private boolean mLoadMoreEndGone = false; + + public void setLoadMoreStatus(int loadMoreStatus) { + this.mLoadMoreStatus = loadMoreStatus; + } + + public int getLoadMoreStatus() { + return mLoadMoreStatus; + } + + public void convert(BaseViewHolder holder) { + switch (mLoadMoreStatus) { + case STATUS_LOADING: + visibleLoading(holder, true); + visibleLoadFail(holder, false); + visibleLoadEnd(holder, false); + break; + case STATUS_FAIL: + visibleLoading(holder, false); + visibleLoadFail(holder, true); + visibleLoadEnd(holder, false); + break; + case STATUS_END: + visibleLoading(holder, false); + visibleLoadFail(holder, false); + visibleLoadEnd(holder, true); + break; + } + } + + private void visibleLoading(BaseViewHolder holder, boolean visible) { + holder.setVisible(getLoadingViewId(), visible); + } + + private void visibleLoadFail(BaseViewHolder holder, boolean visible) { + holder.setVisible(getLoadFailViewId(), visible); + } + + private void visibleLoadEnd(BaseViewHolder holder, boolean visible) { + final int loadEndViewId = getLoadEndViewId(); + if (loadEndViewId != 0) { + holder.setVisible(loadEndViewId, visible); + } + } + + public final void setLoadMoreEndGone(boolean loadMoreEndGone) { + this.mLoadMoreEndGone = loadMoreEndGone; + } + + public final boolean isLoadEndMoreGone() { + if (getLoadEndViewId() == 0) { + return true; + } + return mLoadMoreEndGone; + } + + /** + * No more data is hidden + * + * @return true for no more data hidden load more + * @deprecated Use {@link BaseQuickAdapter#loadMoreEnd(boolean)} instead. + */ + @Deprecated + public boolean isLoadEndGone() { + return mLoadMoreEndGone; + } + + /** + * load more layout + * + * @return + */ + public abstract + @LayoutRes + int getLayoutId(); + + /** + * loading view + * + * @return + */ + protected abstract + @IdRes + int getLoadingViewId(); + + /** + * load fail view + * + * @return + */ + protected abstract + @IdRes + int getLoadFailViewId(); + + /** + * load end view, you can return 0 + * + * @return + */ + protected abstract + @IdRes + int getLoadEndViewId(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/MsgListFetchLoadMoreView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/MsgListFetchLoadMoreView.java new file mode 100644 index 0000000..3e84536 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/MsgListFetchLoadMoreView.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore; + +import com.netease.nim.uikit.R; + +public final class MsgListFetchLoadMoreView extends LoadMoreView { + + @Override + public int getLayoutId() { + return R.layout.nim_msg_list_fetch_load_more; + } + + @Override + protected int getLoadingViewId() { + return R.id.load_more_loading_view; + } + + @Override + protected int getLoadFailViewId() { + return R.id.load_more_load_fail_view; + } + + @Override + protected int getLoadEndViewId() { + return R.id.load_more_load_end_view; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/SimpleLoadMoreView.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/SimpleLoadMoreView.java new file mode 100644 index 0000000..0e28861 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/loadmore/SimpleLoadMoreView.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.loadmore; + +import com.netease.nim.uikit.R; + +public final class SimpleLoadMoreView extends LoadMoreView { + + @Override + public int getLayoutId() { + return R.layout.nim_simple_load_more; + } + + @Override + protected int getLoadingViewId() { + return R.id.load_more_loading_view; + } + + @Override + protected int getLoadFailViewId() { + return R.id.load_more_load_fail_view; + } + + @Override + protected int getLoadEndViewId() { + return R.id.load_more_load_end_view; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/util/RecyclerViewUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/util/RecyclerViewUtil.java new file mode 100644 index 0000000..a6a9a5b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/recyclerview/util/RecyclerViewUtil.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.util; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; + +/** + * Created by hzxuwen on 2017/1/13. + */ + +public class RecyclerViewUtil { + + public static void changeItemAnimation(RecyclerView recyclerView, boolean isOpen) { + // 关闭viewholder动画效果。解决viewholder闪烁问题 + RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); + if (animator instanceof SimpleItemAnimator) { + ((SimpleItemAnimator) animator).setSupportsChangeAnimations(isOpen); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/widget/ClearableEditTextWithIcon.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/widget/ClearableEditTextWithIcon.java new file mode 100644 index 0000000..0a57241 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/widget/ClearableEditTextWithIcon.java @@ -0,0 +1,119 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; + +import androidx.appcompat.widget.AppCompatEditText; + +import com.netease.nim.uikit.R; + + +/** + * 带有图标和删除符号的可编辑输入框,用户可以自定义传入的显示图标 + * + * @author + */ +public class ClearableEditTextWithIcon extends AppCompatEditText implements OnTouchListener, TextWatcher { + + // 删除符号 + Drawable deleteImage = getResources().getDrawable(R.drawable.nim_icon_edit_delete); + + Drawable icon; + + public ClearableEditTextWithIcon(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(); + } + + public ClearableEditTextWithIcon(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public ClearableEditTextWithIcon(Context context) { + super(context); + init(); + } + + private void init() { + ClearableEditTextWithIcon.this.setOnTouchListener(this); + ClearableEditTextWithIcon.this.addTextChangedListener(this); + deleteImage.setBounds(0, 0, deleteImage.getIntrinsicWidth(), deleteImage.getIntrinsicHeight()); + manageClearButton(); + } + + /** + * 传入显示的图标资源id + * + * @param id + */ + public void setIconResource(int id) { + icon = getResources().getDrawable(id); + icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); + manageClearButton(); + } + + /** + * 传入删除图标资源id + * + * @param id + */ + public void setDeleteImage(int id) { + deleteImage = getResources().getDrawable(id); + deleteImage.setBounds(0, 0, deleteImage.getIntrinsicWidth(), deleteImage.getIntrinsicHeight()); + manageClearButton(); + } + + void manageClearButton() { + if (this.getText().toString().equals("")) + removeClearButton(); + else + addClearButton(); + } + + void removeClearButton() { + this.setCompoundDrawables(this.icon, this.getCompoundDrawables()[1], null, this.getCompoundDrawables()[3]); + } + + void addClearButton() { + this.setCompoundDrawables(this.icon, this.getCompoundDrawables()[1], deleteImage, + this.getCompoundDrawables()[3]); + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + ClearableEditTextWithIcon et = ClearableEditTextWithIcon.this; + + if (et.getCompoundDrawables()[2] == null) + return false; + if (event.getAction() != MotionEvent.ACTION_UP) + return false; + if (event.getX() > et.getWidth() - et.getPaddingRight() - deleteImage.getIntrinsicWidth()) { + et.setText(""); + ClearableEditTextWithIcon.this.removeClearButton(); + } + return false; + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + ClearableEditTextWithIcon.this.manageClearButton(); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/widget/SwitchButton.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/widget/SwitchButton.java new file mode 100644 index 0000000..815591f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/ui/widget/SwitchButton.java @@ -0,0 +1,210 @@ +package com.fengliyan.tianlesue.im.uikit.common.ui.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; + +import com.netease.nim.uikit.R; + + +/** + * 仿iphone 开关按钮 + * + * @author sunyoujun + */ +public class SwitchButton extends View implements OnTouchListener { + + private boolean isChoose = false;// 记录当前按钮是否打开,true为打开,flase为关闭 + + private boolean isChecked; + + private boolean onSlip = false;// 记录用户是否在滑动的变量 + + private float down_x, now_x;// 按下时的x,当前的x + + private Rect btn_off, btn_on;// 打开和关闭状态下,游标的Rect . + + private boolean isChangeOn = false; + + private boolean isInterceptOn = false; + + private OnChangedListener onChangedListener; + + private Bitmap bg_on, bg_off, slip_btn; + + public SwitchButton(Context context) { + super(context); + init(); + } + + public SwitchButton(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public SwitchButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(); + } + + private void init() {// 初始化 + bg_on = BitmapFactory.decodeResource(getResources(), R.drawable.nim_slide_toggle_on); + bg_off = BitmapFactory.decodeResource(getResources(), R.drawable.nim_slide_toggle_off); + slip_btn = BitmapFactory.decodeResource(getResources(), R.drawable.nim_slide_toggle); + btn_off = new Rect(0, 0, slip_btn.getWidth(), slip_btn.getHeight()); + btn_on = new Rect(bg_off.getWidth() - slip_btn.getWidth(), 0, bg_off.getWidth(), slip_btn.getHeight()); + setOnTouchListener(this);// 设置监听器,也可以直接复写OnTouchEvent + } + + @SuppressLint("DrawAllocation") + @Override + protected void onDraw(Canvas canvas) {// 绘图函数 + + super.onDraw(canvas); + + Matrix matrix = new Matrix(); + Paint paint = new Paint(); + float x; + // 滑动到前半段与后半段的背景不同,在此做判断 + if (now_x < (bg_on.getWidth() / 2)) { + x = now_x - slip_btn.getWidth() / 2; + canvas.drawBitmap(bg_off, matrix, paint);// 画出关闭时的背景 + } else { + x = bg_on.getWidth() - slip_btn.getWidth() / 2; + canvas.drawBitmap(bg_on, matrix, paint);// 画出打开时的背景 + } + // 是否是在滑动状态 + if (onSlip) { + if (now_x >= bg_on.getWidth()) {// 是否划出指定范围,不能让游标跑到外头,必须做这个判断 + x = bg_on.getWidth() - slip_btn.getWidth() / 2;// 减去游标1/2的长度... + } else if (now_x < 0) { + x = 0; + } else { + x = now_x - slip_btn.getWidth() / 2; + } + } else {// 非滑动状态 + if (isChoose) {// 根据现在的开关状态设置画游标的位置 + x = btn_on.left; + canvas.drawBitmap(bg_on, matrix, paint);// 初始状态为true时应该画出打开状态图片 + } else { + x = btn_off.left; + } + } + if (isChecked) { + canvas.drawBitmap(bg_on, matrix, paint); + x = btn_on.left; + isChecked = !isChecked; + } + + // 对游标位置进行异常判断... + if (x < 0) { + x = 0; + } else if (x > bg_on.getWidth() - slip_btn.getWidth()) { + x = bg_on.getWidth() - slip_btn.getWidth(); + } + canvas.drawBitmap(slip_btn, x, 0, paint);// 画出游标. + } + + public boolean onTouch(View v, MotionEvent event) { + boolean old = isChoose; + switch (event.getAction()) { + case MotionEvent.ACTION_MOVE:// 滑动 + now_x = event.getX(); + break; + case MotionEvent.ACTION_DOWN:// 按下 + if (event.getX() > bg_on.getWidth() || event.getY() > bg_on.getHeight()) { + return false; + } + onSlip = true; + down_x = event.getX(); + now_x = down_x; + break; + case MotionEvent.ACTION_CANCEL: // 移到控件外部 + onSlip = false; + boolean choose = isChoose; + if (now_x >= (bg_on.getWidth() / 2)) { + now_x = bg_on.getWidth() - slip_btn.getWidth() / 2; + isChoose = true; + } else { + now_x = now_x - slip_btn.getWidth() / 2; + isChoose = false; + } + if (isChangeOn && (choose != isChoose)) { // 如果设置了监听器,就调用其方法.. + onChangedListener.OnChanged(this, isChoose); + } + break; + case MotionEvent.ACTION_UP:// 松开 + onSlip = false; + boolean lastChoose = isChoose; + if (event.getX() >= (bg_on.getWidth() / 2)) { + now_x = bg_on.getWidth() - slip_btn.getWidth() / 2; + isChoose = true; + } else { + now_x = now_x - slip_btn.getWidth() / 2; + isChoose = false; + } + if (lastChoose == isChoose) {// 相等表示点击状态未切换,之后切换状态 + if (event.getX() >= (bg_on.getWidth() / 2)) { + now_x = 0; + isChoose = false; + } else { + now_x = bg_on.getWidth() - slip_btn.getWidth() / 2; + isChoose = true; + } + } + // 如果设置了监听器,就调用其方法.. + if (isChangeOn) { + onChangedListener.OnChanged(this, isChoose); + } + break; + default: + } + if (!old && isInterceptOn) { + isChoose = false; + } else { + invalidate();// 重画控件 + } + return true; + } + + public void setOnChangedListener(OnChangedListener listener) {// 设置监听器,当状态修改的时候 + isChangeOn = true; + onChangedListener = listener; + } + + public interface OnChangedListener { + + abstract void OnChanged(View v, boolean checkState); + } + + public void setCheck(boolean isChecked) { + this.isChecked = isChecked; + isChoose = isChecked; + if (isChecked == false) { + now_x = 0; + } + invalidate(); + } + + public boolean isChoose() { + return this.isChoose; + } + + public boolean getCheck() { + return this.isChecked; + } + + public void setInterceptState(boolean isIntercept) {// 设置监听器,是否在重画钱拦截事件,状态由false变true时 拦截事件 + isInterceptOn = isIntercept; + // onInterceptListener = listener; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/C.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/C.java new file mode 100644 index 0000000..5e3b125 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/C.java @@ -0,0 +1,65 @@ +package com.fengliyan.tianlesue.im.uikit.common.util; + +public class C { + // 视频允许大小 + public static final long MAX_LOCAL_VIDEO_FILE_SIZE = 100 * 1024 * 1024; + + + // 关于文件后缀的常量 + public static final class FileSuffix { + public static final String JPG = ".jpg"; + + public static final String PNG = ".png"; + + public static final String M4A = ".m4a"; + + public static final String THREE_3GPP = ".3gp"; + + public static final String BMP = ".bmp"; + + public static final String MP4 = ".mp4"; + + public static final String AMR_NB = ".amr"; + + public static final String APK = ".apk"; + + public static final String AAC = ".aac"; + } + + // 关于mimetype的常量 + public static final class MimeType { + public static final String MIME_JPEG = "image/jpeg"; + + public static final String MIME_PNG = "image/png"; + + public static final String MIME_BMP = "image/x-MS-bmp"; + + public static final String MIME_GIF = "image/gif"; + + public static final String MIME_AUDIO_3GPP = "audio/3gpp"; + + public static final String MIME_AUDIO_MP4 = "audio/mp4"; + + public static final String MIME_AUDIO_M4A = "audio/m4a"; + + public static final String MIME_AUDIO_AMR_NB = "audio/amr"; + + public static final String MIME_AUDIO_AAC = "audio/aac"; + + public static final String MIME_TXT = "txt/txt";// 用 于PC长消息 + + public static final String MIME_WAPPUSH_SMS = "message/sms"; + + public static final String MIME_WAPPUSH_TEXT = "txt/wappush"; // 文字wappush + + public static final String MIME_MUSIC_LOVE = "music/love"; // 爱音乐 + + public static final String MIME_MUSIC_XIA = "music/xia"; // 虾米音乐 + + public static final String MIME_VIDEO_3GPP = "video/3gpp"; + + public static final String MIME_VIDEO_ALL = "video/*"; + + public static final String MIME_LOCATION_GOOGLE = "location/google"; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/file/AttachmentStore.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/file/AttachmentStore.java new file mode 100644 index 0000000..dd2e60e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/file/AttachmentStore.java @@ -0,0 +1,346 @@ + +package com.fengliyan.tianlesue.im.uikit.common.util.file; + +import android.graphics.Bitmap; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +/** + * 用于把附件保存到文件系统中 + */ +public class AttachmentStore { + public static long copy(String srcPath, String dstPath) { + if (TextUtils.isEmpty(srcPath) || TextUtils.isEmpty(dstPath)) { + return -1; + } + + File source = new File(srcPath); + if (!source.exists()) { + return -1; + } + + if (srcPath.equals(dstPath)) { + return source.length(); + } + + FileChannel fcin = null; + FileChannel fcout = null; + try { + fcin = new FileInputStream(source).getChannel(); + fcout = new FileOutputStream(create(dstPath)).getChannel(); + ByteBuffer tmpBuffer = ByteBuffer.allocateDirect(4096); + while (fcin.read(tmpBuffer) != -1) { + tmpBuffer.flip(); + fcout.write(tmpBuffer); + tmpBuffer.clear(); + } + return source.length(); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (fcin != null) { + fcin.close(); + } + if (fcout != null) { + fcout.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return -1; + } + + public static long getFileLength(String srcPath) { + if (TextUtils.isEmpty(srcPath)) { + return -1; + } + + File srcFile = new File(srcPath); + if (!srcFile.exists()) { + return -1; + } + + return srcFile.length(); + } + + public static long save(String path, String content) { + return save(content.getBytes(), path); + } + + /** + * 把数据保存到文件系统中,并且返回其大小 + * + * @param data + * @param filePath + * @return 如果保存失败, 则返回-1 + */ + public static long save(byte[] data, String filePath) { + if (TextUtils.isEmpty(filePath)) { + return -1; + } + + File f = new File(filePath); + if (f.getParentFile() == null) { + return -1; + } + + if (!f.getParentFile().exists()) {// 如果不存在上级文件夹 + f.getParentFile().mkdirs(); + } + try { + f.createNewFile(); + FileOutputStream fout = new FileOutputStream(f); + fout.write(data); + fout.close(); + } catch (IOException e) { + e.printStackTrace(); + return -1; + } + return f.length(); + } + + public static boolean move(String srcFilePath, String dstFilePath) { + if (TextUtils.isEmpty(srcFilePath) || TextUtils.isEmpty(dstFilePath)) { + return false; + } + + File srcFile = new File(srcFilePath); + if (!srcFile.exists() || !srcFile.isFile()) { + return false; + } + + File dstFile = new File(dstFilePath); + if (dstFile.getParentFile() == null) { + return false; + } + + if (!dstFile.getParentFile().exists()) {// 如果不存在上级文件夹 + dstFile.getParentFile().mkdirs(); + } + + return srcFile.renameTo(dstFile); + } + + public static File create(String filePath) { + if (TextUtils.isEmpty(filePath)) { + return null; + } + + File f = new File(filePath); + if (!f.getParentFile().exists()) {// 如果不存在上级文件夹 + f.getParentFile().mkdirs(); + } + try { + f.createNewFile(); + return f; + } catch (IOException e) { + if (f != null && f.exists()) { + f.delete(); + } + return null; + } + } + + /** + * @param is + * @param filePath + * @return 保存失败,返回-1 + */ + public static long save(InputStream is, String filePath) { + File f = new File(filePath); + if (!f.getParentFile().exists()) {// 如果不存在上级文件夹 + f.getParentFile().mkdirs(); + } + FileOutputStream fos = null; + try { + f.createNewFile(); + fos = new FileOutputStream(f); + int read = 0; + byte[] bytes = new byte[8091]; + while ((read = is.read(bytes)) != -1) { + fos.write(bytes, 0, read); + } + return f.length(); + } catch (IOException e) { + if (f != null && f.exists()) { + f.delete(); + } + LogUtil.e("file", "save is to " + filePath + " failed: " + e.getMessage()); + return -1; + } finally { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + if (fos != null) { + fos.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 把文件从文件系统中读取出来 + * + * @param path + * @return 如果无法读取, 则返回null + */ + public static byte[] load(String path) { + try { + File f = new File(path); + int unread = (int) f.length(); + int read = 0; + byte[] buf = new byte[unread]; // 读取文件长度 + FileInputStream fin = new FileInputStream(f); + do { + int count = fin.read(buf, read, unread); + read += count; + unread -= count; + } while (unread != 0); + fin.close(); + return buf; + } catch (FileNotFoundException e) { + return null; + } catch (IOException e) { + return null; + } + } + + public static String loadAsString(String path) { + if (isFileExist(path)) { + byte[] content = load(path); + return new String(content); + } else { + return null; + } + } + + /** + * 删除指定路径文件 + * + * @param path + */ + public static boolean delete(String path) { + if (TextUtils.isEmpty(path)) { + return false; + } + File f = new File(path); + if (f.exists()) { + f = renameOnDelete(f); + return f.delete(); + } else { + return false; + } + } + + public static void deleteOnExit(String path) { + if (TextUtils.isEmpty(path)) { + return; + } + File f = new File(path); + if (f.exists()) { + f.deleteOnExit(); + } + } + + public static boolean deleteDir(String path) { + return deleteDir(path, true); + } + + private static boolean deleteDir(String path, boolean rename) { + boolean success = true; + File file = new File(path); + if (file.exists()) { + if (rename) { + file = renameOnDelete(file); + } + + File[] list = file.listFiles(); + if (list != null) { + int len = list.length; + for (int i = 0; i < len; ++i) { + if (list[i].isDirectory()) { + deleteDir(list[i].getPath(), false); + } else { + boolean ret = list[i].delete(); + if (!ret) { + success = false; + } + } + } + } + } else { + success = false; + } + if (success) { + file.delete(); + } + return success; + } + + // rename before delete to avoid lingering filesystem lock of android + private static File renameOnDelete(File file) { + String tmpPath = file.getParent() + "/" + System.currentTimeMillis() + "_tmp"; + File tmpFile = new File(tmpPath); + if (file.renameTo(tmpFile)) { + return tmpFile; + } else { + return file; + } + } + + public static boolean isFileExist(String path) { + if (!TextUtils.isEmpty(path) && new File(path).exists()) { + return true; + } else { + return false; + } + } + + public static boolean saveBitmap(Bitmap bitmap, String path, boolean recycle) { + if (bitmap == null || TextUtils.isEmpty(path)) { + return false; + } + + BufferedOutputStream bos = null; + try { + FileOutputStream fos = new FileOutputStream(path); + bos = new BufferedOutputStream(fos); + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); + return true; + + } catch (FileNotFoundException e) { + return false; + } finally { + if (bos != null) { + try { + bos.close(); + } catch (IOException e) { + } + } + if (recycle) { + bitmap.recycle(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/file/FileUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/file/FileUtil.java new file mode 100644 index 0000000..d978edc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/file/FileUtil.java @@ -0,0 +1,129 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.file; + +import android.text.TextUtils; +import android.util.Log; +import android.webkit.MimeTypeMap; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.R; + +import java.util.Locale; + +public class FileUtil { + private static final String TAG = "FileUtil"; + + public static boolean hasExtentsion(String filename) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length() - 1))) { + return true; + } else { + return false; + } + } + + // 获取文件扩展名 + public static String getExtensionName(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length() - 1))) { + return filename.substring(dot + 1); + } + } + return ""; + } + + // 获取文件名 + public static String getFileNameFromPath(String filepath) { + if ((filepath != null) && (filepath.length() > 0)) { + int sep = filepath.lastIndexOf('/'); + if ((sep > -1) && (sep < filepath.length() - 1)) { + return filepath.substring(sep + 1); + } + } + return filepath; + } + + // 获取不带扩展名的文件名 + public static String getFileNameNoEx(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length()))) { + return filename.substring(0, dot); + } + } + return filename; + } + + public static String getMimeType(String filePath) { + if (TextUtils.isEmpty(filePath)) { + return ""; + } + String type = null; + String extension = getExtensionName(filePath.toLowerCase()); + if (!TextUtils.isEmpty(extension)) { + MimeTypeMap mime = MimeTypeMap.getSingleton(); + type = mime.getMimeTypeFromExtension(extension); + } + Log.i(TAG, "url:" + filePath + " " + "type:" + type); + + // FIXME + if (StringUtil.isEmpty(type) && filePath.endsWith("aac")) { + type = "audio/aac"; + } + + return type; + } + + public enum SizeUnit { + Byte, + KB, + MB, + GB, + TB, + Auto, + } + + public static String formatFileSize(long size) { + return formatFileSize(size, SizeUnit.Auto); + } + + public static String formatFileSize(long size, SizeUnit unit) { + if (size < 0) { + return NimUIKit.getContext().getString(R.string.unknow_size); + } + + final double KB = 1024; + final double MB = KB * 1024; + final double GB = MB * 1024; + final double TB = GB * 1024; + if (unit == SizeUnit.Auto) { + if (size < KB) { + unit = SizeUnit.Byte; + } else if (size < MB) { + unit = SizeUnit.KB; + } else if (size < GB) { + unit = SizeUnit.MB; + } else if (size < TB) { + unit = SizeUnit.GB; + } else { + unit = SizeUnit.TB; + } + } + + switch (unit) { + case Byte: + return size + "B"; + case KB: + return String.format(Locale.US, "%.2fKB", size / KB); + case MB: + return String.format(Locale.US, "%.2fMB", size / MB); + case GB: + return String.format(Locale.US, "%.2fGB", size / GB); + case TB: + return String.format(Locale.US, "%.2fPB", size / TB); + default: + return size + "B"; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/LogUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/LogUtil.java new file mode 100644 index 0000000..c82e5e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/LogUtil.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log; + + +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.LogBase; +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.wrapper.NimLog; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.ExternalStorage; + +public class LogUtil extends NimLog { + + private static final String LOG_FILE_NAME_PREFIX = "demo"; + + public static void init(String logDir, int level) { + final LogBase.LogInterceptor interceptor = new LogBase.LogInterceptor() { + @Override + public boolean checkValidBeforeWrite() { + return ExternalStorage.getInstance().checkStorageValid(); + } + }; + + NimLog.initDateNLog(null, logDir, LOG_FILE_NAME_PREFIX, level, 0, 0, true, interceptor); + } + + public static void ui(String msg) { + if (getLog() != null) { + getLog().i("ui", buildMessage(msg)); + } + } + + public static void res(String msg) { + if (getLog() != null) { + getLog().i("res", buildMessage(msg)); + } + } + + public static void audio(String msg) { + if (getLog() != null) { + getLog().i("AudioRecorder", buildMessage(msg)); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/LogBase.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/LogBase.java new file mode 100644 index 0000000..ba666e5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/LogBase.java @@ -0,0 +1,224 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log.sdk; + +import android.text.TextUtils; +import android.util.Log; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.util.FileUtils; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +/** + * 日志基类 + * 保证open/write/close/flush都在同个线程操作 + *

+ * Created by huangjun on 2017/3/7. + */ + +public abstract class LogBase { + + public interface LogInterceptor { + /** + * 子类实现写日志前处理逻辑,例如本地存储读写权限检查,只有返回 true 才会执行写操作 + * + * @return 是否允许执行写操作 + */ + boolean checkValidBeforeWrite(); + } + + static final int K = 1024; + static final int M = 1024 * K; + private static final int DEFAULT_MAX_LENGTH = 8 * M; // 每次初始化的时候检查,大于该值时缩减log文件 + private static final int DEFAULT_BASE_LENGTH = 4 * M; // 如果大于MAX_LENGTH,缩减到该值 + private static final boolean RUN_ON_SINGLE_THREAD = true; // 默认在独立线程上排队写日志,测试性能可以改成在主线程上执行 + + int maxLength; + int baseLength; + + String logPath; + private int level = Log.DEBUG; + private LogInterceptor interceptor; + + private final Executor logger = Executors.newSingleThreadExecutor(); + + /** + * 动态设置日志级别 + * + * @param level 日志级别 + */ + public void setLevel(int level) { + this.level = level; + } + + /** + * 日志初始化 + * + * @param logDir 日志文件所在的目录 + * @param logName 日志文件名 + * @param maxLength 日志文件最大容量 + * @param baseLength 日志文件裁减后的容量 + * @param level 日志级别 + * @param shrink 是否需要裁剪 + * @param interceptor 日志拦截器,可以在执行写日志前判断本地权限、磁盘是否准备好,决定是否要日志 + */ + public void init(final String logDir, final String logName, final int level, final int maxLength, final int baseLength, final boolean shrink, final LogInterceptor interceptor) { + this.logPath = FileUtils.getFilePath(logDir, logName); + this.level = level; + this.interceptor = interceptor; + this.maxLength = maxLength; + this.baseLength = baseLength; + + if (this.maxLength <= 0) { + this.maxLength = DEFAULT_MAX_LENGTH; + } + if (this.baseLength <= 0) { + this.baseLength = DEFAULT_BASE_LENGTH; + } + + final Runnable runnable = new Runnable() { + @Override + public void run() { + open(shrink); + } + }; + + run(runnable); + } + + /** + * 关闭日志,清理缓存 + */ + public void destroy() { + if (TextUtils.isEmpty(logPath)) { + return; + } + + final Runnable runnable = new Runnable() { + @Override + public void run() { + close(); + } + }; + + run(runnable); + } + + /** + * 尝试回写数据到文件中 + */ + public void tryFlush() { + if (TextUtils.isEmpty(logPath)) { + return; + } + + final Runnable runnable = new Runnable() { + @Override + public void run() { + forceFlush(); + } + }; + + run(runnable); + } + + /** + * 写日志 + */ + private void o(final int priority, final String tag, final String msg, final Throwable tr) { + if (TextUtils.isEmpty(logPath) || TextUtils.isEmpty(msg)) { + return; + } + + final long time = System.currentTimeMillis(); + final long threadId = Thread.currentThread().getId(); + final Runnable runnable = new Runnable() { + @Override + public void run() { + final String timeStr = LogFormat.formatTime(time); + Log.println(priority, tag, threadId + "/" + msg + '\n' + Log.getStackTraceString(tr)); + + if (level <= priority && (interceptor == null || interceptor.checkValidBeforeWrite())) { + writeLog(LogFormat.formatLog(tag, timeStr, msg, tr)); + } + } + }; + + run(runnable); + } + + private void run(Runnable runnable) { + if (RUN_ON_SINGLE_THREAD) { + logger.execute(runnable); + } else { + runnable.run(); + } + } + + public void i(String tag, String msg) { + i(tag, msg, null); + } + + public void i(String tag, String msg, Throwable tr) { + o(Log.INFO, tag, msg, tr); + } + + public void v(String tag, String msg) { + v(tag, msg, null); + } + + public void v(String tag, String msg, Throwable tr) { + o(Log.VERBOSE, tag, msg, tr); + } + + public void e(String tag, String msg) { + e(tag, msg, null); + } + + public void e(String tag, String msg, Throwable tr) { + o(Log.ERROR, tag, msg, tr); + } + + public void d(String tag, String msg) { + d(tag, msg, null); + } + + public void d(String tag, String msg, Throwable tr) { + o(Log.DEBUG, tag, msg, tr); + } + + public void w(String tag, String msg) { + w(tag, msg, null); + } + + public void w(String tag, String msg, Throwable tr) { + o(Log.WARN, tag, msg, tr); + } + + private void o(int priority, String tag, String msg) { + o(priority, tag, msg, null); + } + + /** + * 子类实现打开日志 + * + * @param shrink 是否裁剪 + */ + abstract void open(final boolean shrink); + + /** + * 子类实现写日志 + * + * @param log 日志内容 + */ + abstract void writeLog(final String log); + + /** + * 强制将缓存的数据回写到文件 + */ + abstract void forceFlush(); + + /** + * 子类实现关闭日志,清理缓存 + */ + abstract void close(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/LogFormat.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/LogFormat.java new file mode 100644 index 0000000..c5a6f6a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/LogFormat.java @@ -0,0 +1,84 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log.sdk; + +import android.text.TextUtils; +import android.util.Log; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * 日志格式 + *

+ * Created by huangjun on 2017/3/8. + */ +class LogFormat { + + /** + * ******************************* log content format ***************************** + */ + + private static final String MESSAGE_FORMAT = "MM-dd HH:mm:ss.SSS"; + private static final DateFormat messageFormat = new SimpleDateFormat(MESSAGE_FORMAT, Locale.getDefault()); + private static final Date date = new Date(); // 复用 + private static long lastTime; + private static String lastTimeStr; + + static String formatTime(final long time) { + if (time == lastTime) { + return lastTimeStr; + } + + date.setTime(time); + lastTime = time; + return lastTimeStr = messageFormat.format(date); + } + + static String formatLog(String tag, String time, String msg, Throwable tr) { + StringBuilder sb = new StringBuilder(); + + // time + sb.append(time); + sb.append(": "); + + // tag + sb.append(tag); + sb.append(": "); + + // content + sb.append(msg); + sb.append("\r\n"); + + // Throwable + if (tr != null) { + sb.append(Log.getStackTraceString(tr)); + sb.append("\r\n"); + } + + return sb.toString(); + } + + /** + * ******************************* date file format ***************************** + */ + + private static final String SUFFIX = ".log"; + private static final String FILE_FORMAT = "yyyyMMdd"; + private static final DateFormat fileNameFormat = new SimpleDateFormat(FILE_FORMAT, Locale.getDefault()); + + static String getLogFileName(String prefix) { + // nim_20170911.log or 20170911.log + StringBuilder sb = new StringBuilder(); + if (!TextUtils.isEmpty(prefix)) { + sb.append(prefix); + sb.append("_"); + } + + date.setTime(System.currentTimeMillis()); + sb.append(fileNameFormat.format(date)); + sb.append(SUFFIX); + + return sb.toString(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/NDateLogImpl.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/NDateLogImpl.java new file mode 100644 index 0000000..40b1774 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/NDateLogImpl.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log.sdk; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.util.FileUtils; + +import java.io.File; + +/** + * I/O write 方式按日期打日志,按天生成日志,日志名 prefix_date.log。支持多进程同时读写,不丢日志,写入效率较低(比NLogImpl还要牺牲一个获取日期文件名的开销)。 + *

+ * Created by huangjun on 2017/9/20. + */ +public class NDateLogImpl extends NLogImpl { + + private String logDir; + private String logNamePrefix; + + @Override + public void init(final String logDir, final String logNamePrefix, final int level, + final int maxLength, final int baseLength, final boolean shrink, final LogInterceptor interceptor) { + this.logDir = logDir; + this.logNamePrefix = logNamePrefix; + final String logName = LogFormat.getLogFileName(logNamePrefix); + + super.init(logDir, logName, level, maxLength, baseLength, shrink, interceptor); + } + + @Override + void writeLog(final String log) { + this.logPath = logDir + File.separator + LogFormat.getLogFileName(logNamePrefix); + FileUtils.appendFile(log, logPath); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/NLogImpl.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/NLogImpl.java new file mode 100644 index 0000000..be0a069 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/NLogImpl.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log.sdk; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.util.FileUtils; + +/** + * I/O write 方式打日志。支持多进程同时读写,不丢日志,写入效率略低。 + *

+ * Created by huangjun on 2017/3/8. + */ +public class NLogImpl extends LogBase { + + private static final String TAG = "Log"; + + @Override + void open(final boolean shrink) { + if (shrink) { + FileUtils.shrink(logPath, maxLength, baseLength); + i(TAG, "shrink log success"); + } + } + + @Override + void writeLog(final String log) { + FileUtils.appendFile(log, logPath); + } + + @Override + void forceFlush() { + + } + + @Override + void close() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/util/FileUtils.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/util/FileUtils.java new file mode 100644 index 0000000..d22059c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/util/FileUtils.java @@ -0,0 +1,201 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.util; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.channels.FileChannel; + +/** + * Created by huangjun on 2017/3/7. + */ + +public class FileUtils { + + private static final String TAG = "FileUtils"; + + public static File getFile(final String path) { + try { + File file = new File(path); + File dir = file.getParentFile(); + if (dir == null) { + Log.e(TAG, "file's parent dir is null, path=" + file.getCanonicalPath()); + return null; + } + + if (!dir.exists()) { + if (dir.getParentFile().exists()) { + dir.mkdir(); // dir父目录存在用mkDir + } else { + dir.mkdirs(); // dir父目录不存在用mkDirs + } + } + + if (!file.exists() && !file.createNewFile()) { + Log.e(TAG, "can not create dest file, path=" + path); + return null; + } + return file; + } catch (Throwable e) { + Log.e(TAG, "create dest file error, path=" + path, e); + } + + return null; + } + + public static boolean appendFile(final String message, final String path) { + if (TextUtils.isEmpty(message)) { + return false; + } + + if (TextUtils.isEmpty(path)) { + return false; + } + + boolean written = false; + try { + BufferedWriter fw = new BufferedWriter(new FileWriter(path, true)); + fw.write(message); + fw.flush(); + fw.close(); + + written = true; + } catch (Exception e) { + e.printStackTrace(); + } + + return written; + } + + public static boolean appendFile(final byte[] message, final String path) { + if (message == null || message.length <= 0) { + return false; + } + + if (TextUtils.isEmpty(path)) { + return false; + } + + boolean written = false; + try { + FileOutputStream fw = new FileOutputStream(path, true); + fw.write(message); + fw.close(); + + written = true; + } catch (Exception e) { + e.printStackTrace(); + } + + return written; + } + + public static synchronized void shrink(final String logPath, final int maxLength, final int baseLength) { + File file = new File(logPath); + if (file.length() < maxLength) { + return; + } else if (file.length() > Integer.MAX_VALUE) { + file.delete(); + return; + } + + File out = new File(logPath + "_tmp"); + FileInputStream fis = null; + FileOutputStream fos = null; + try { + fis = new FileInputStream(file); + fos = new FileOutputStream(out); + FileChannel input = fis.getChannel(); + + input.position(file.length() - baseLength); + FileChannel output = fos.getChannel(); + output.transferFrom(fis.getChannel(), 0, baseLength); + } catch (Exception e) { + e.printStackTrace(); + } finally { + close(fis); + close(fos); + } + + if (out.exists()) { + if (file.delete()) { + out.renameTo(file); + } + } + } + + public static void close(Closeable closeable) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String getFilePath(final String dirPath, final String fileName) { + File dir = new File(dirPath); + + if (!dir.exists()) { + if (dir.getParentFile().exists()) { + dir.mkdir(); // dir父目录存在用mkDir + } else { + dir.mkdirs(); // dir父目录不存在用mkDirs + } + } + + return dirPath + File.separator + fileName; + } + + // 是否包含扩展名 + public static boolean hasExtension(String filename) { + int dot = filename.lastIndexOf('.'); + return ((dot > -1) && (dot < (filename.length() - 1))); + } + + // 获取文件扩展名 + public static String getExtensionName(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length() - 1))) { + return filename.substring(dot + 1); + } + } + return ""; + } + + // 获取文件名 + public static String getFileNameFromPath(String filepath) { + if ((filepath != null) && (filepath.length() > 0)) { + int sep = filepath.lastIndexOf('/'); + if ((sep > -1) && (sep < filepath.length() - 1)) { + return filepath.substring(sep + 1); + } + } + return filepath; + } + + // 获取不带扩展名的文件名 + public static String getFileNameNoEx(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length()))) { + return filename.substring(0, dot); + } + } + return filename; + } + + public static String getExternalPackageDirectory(Context context) { + String externalPath = context.getExternalFilesDir("").getAbsolutePath(); + return externalPath + File.separator + context.getPackageName(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/wrapper/AbsNimLog.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/wrapper/AbsNimLog.java new file mode 100644 index 0000000..68d9e23 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/wrapper/AbsNimLog.java @@ -0,0 +1,98 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.wrapper; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.LogBase; + +/** + * 云信日志基类 + *

+ * Created by huangjun on 2017/9/20. + */ + +public abstract class AbsNimLog { + + private static LogBase log; + private static String process; // 进程标识,体现在tag里 + + protected static void init(LogBase logImpl, String processName, String logDir, String logFileName, + int level, int maxLength, int baseLength, boolean shrink, LogBase.LogInterceptor interceptor) { + log = logImpl; + process = processName; + log.init(logDir, logFileName, level, maxLength, baseLength, shrink, interceptor); + } + + public static void tryFlush() { + if (log != null) { + log.tryFlush(); + } + } + + protected static LogBase getLog() { + return log; + } + + public static void v(String tag, String msg) { + log.v(buildTag(tag), buildMessage(msg)); + } + + public static void v(String tag, String msg, Throwable thr) { + log.v(buildTag(tag), buildMessage(msg), thr); + } + + public static void d(String tag, String msg) { + log.d(buildTag(tag), buildMessage(msg)); + } + + public static void d(String tag, String msg, Throwable thr) { + log.d(buildTag(tag), buildMessage(msg), thr); + } + + public static void i(String tag, String msg) { + log.i(buildTag(tag), buildMessage(msg)); + } + + public static void i(String tag, String msg, Throwable thr) { + log.i(buildTag(tag), buildMessage(msg), thr); + } + + public static void w(String tag, String msg) { + log.w(buildTag(tag), buildMessage(msg)); + } + + public static void w(String tag, String msg, Throwable thr) { + log.w(buildTag(tag), buildMessage(msg), thr); + } + + public static void w(String tag, Throwable thr) { + log.w(buildTag(tag), buildMessage(""), thr); + } + + public static void e(String tag, String msg) { + log.e(buildTag(tag), buildMessage(msg)); + } + + public static void e(String tag, String msg, Throwable thr) { + log.e(buildTag(tag), buildMessage(msg), thr); + } + + public static void ui(String msg) { + log.i(buildTag("ui"), buildMessage(msg)); + } + + public static void core(String msg) { + log.i(buildTag("core"), buildMessage(msg)); + } + + public static void test(String msg) { + log.d(buildTag("test"), buildMessage(msg)); + } + + protected static String buildTag(String tag) { + return TextUtils.isEmpty(process) ? tag : "[" + process + "]" + tag; + } + + protected static String buildMessage(String msg) { + return msg; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/wrapper/NimLog.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/wrapper/NimLog.java new file mode 100644 index 0000000..982a847 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/log/sdk/wrapper/NimLog.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.wrapper; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.LogBase; +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.NDateLogImpl; +import com.fengliyan.tianlesue.im.uikit.common.util.log.sdk.NLogImpl; + +/** + * 云信日志封装 + *

+ * Created by huangjun on 2017/9/20. + */ +public class NimLog extends AbsNimLog { + + /** + * 初始化多进程日志系统,支持多个进程写入一个日志文件 + * 适用场景:多进程,对性能没有特别高的要求 + * 缺点:持续频繁打日志会造成CPU内核态占用升高 + * + * @param processName 进程名,单进程可以填 null,每行日志tag为[process]tag + * @param logDir 日志所在的目录,一般是 SD 卡下的目录绝对路径 + * @param logFileName 日志名称,例如 nim_sdk.log + * @param level 日志级别,大于等于此日志级别的日志才会被写入 + * @param maxLength 日志最大的文件大小,日志初始化时(一般是进程启动后),判断日志如果超过此大小将进行裁剪,填0表示默认值8M + * @param baseLength 日志裁减后的大小,填0表示默认值4M + * @param shrink 日志初始化时是否进行裁减 + * @param interceptor 日志拦截器,可以在执行写日志前判断本地权限、磁盘是否准备好,决定是否要日志 + */ + public static void initNLog(String processName, String logDir, String logFileName, int level, int maxLength, int baseLength, boolean shrink, LogBase.LogInterceptor interceptor) { + init(new NLogImpl(), processName, logDir, logFileName, level, maxLength, baseLength, shrink, interceptor); + } + + /** + * 初始化多进程按日期存储的日志系统,支持多个进程写入一个日志文件,每天产生一个日志文件。 + * 适用场景:多进程,要求按天记录日志,对性能没有特别高的要求。 + * 缺点:持续频繁打日志会造成CPU内核态占用升高 + * + * @param processName 进程名,单进程可以填 null,每行日志tag为[process]tag + * @param logDir 日志所在的目录,一般是 SD 卡下的目录绝对路径 + * @param logFileNamePrefix 日志名前缀,会自动根据日期生成日志,例如nim_20170911.log + * @param level 日志级别,大于等于此日志级别的日志才会被写入 + * @param maxLength 日志最大的文件大小,日志初始化时(一般是进程启动后),判断日志如果超过此大小将进行裁剪,填0表示默认值8M + * @param baseLength 日志裁减后的大小,填0表示默认值4M + * @param shrink 日志初始化时是否进行裁减 + * @param interceptor 日志拦截器,可以在执行写日志前判断本地权限、磁盘是否准备好,决定是否要日志 + */ + public static void initDateNLog(String processName, String logDir, String logFileNamePrefix, int level, int maxLength, int baseLength, boolean shrink, LogBase.LogInterceptor interceptor) { + init(new NDateLogImpl(), processName, logDir, logFileNamePrefix, level, maxLength, baseLength, shrink, interceptor); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/BitmapDecoder.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/BitmapDecoder.java new file mode 100644 index 0000000..88a8a2b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/BitmapDecoder.java @@ -0,0 +1,271 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.media; + +import android.annotation.TargetApi; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.media.ThumbnailUtils; +import android.os.Build; +import android.provider.MediaStore; + +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public class BitmapDecoder { + public static Bitmap decode(InputStream is) { + BitmapFactory.Options options = new BitmapFactory.Options(); + + // RGB_565 + options.inPreferredConfig = Bitmap.Config.RGB_565; + + /** + * 在4.4上,如果之前is标记被移动过,会导致解码失败 + */ + try { + if (is.markSupported()) { + is.reset(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + try { + return BitmapFactory.decodeStream(is, null, options); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + + return null; + } + + public static Bitmap decodeSampledForDisplay(String pathName) { + return decodeSampledForDisplay(pathName, true); + } + + public static Bitmap decodeSampledForDisplay(String pathName, boolean withTextureLimit) { + float ratio = ImageUtil.MAX_IMAGE_RATIO; + int[][] reqBounds = new int[][]{ + new int[]{ScreenUtil.screenWidth * 2, ScreenUtil.screenHeight}, + new int[]{ScreenUtil.screenWidth, ScreenUtil.screenHeight * 2}, + new int[]{(int) (ScreenUtil.screenWidth * 1.414), (int) (ScreenUtil.screenHeight * 1.414)}, + }; + + // decode bound + int[] bound = decodeBound(pathName); + // pick request bound + int[] reqBound = pickReqBoundWithRatio(bound, reqBounds, ratio); + + int width = bound[0]; + int height = bound[1]; + int reqWidth = reqBound[0]; + int reqHeight = reqBound[1]; + + // calculate sample size + int sampleSize = SampleSizeUtil.calculateSampleSize(width, height, reqWidth, reqHeight); + + if (withTextureLimit) { + // adjust sample size + sampleSize = SampleSizeUtil.adjustSampleSizeWithTexture(sampleSize, width, height); + } + + int RETRY_LIMIT = 5; + Bitmap bitmap = decodeSampled(pathName, sampleSize); + while (bitmap == null && RETRY_LIMIT > 0) { + sampleSize++; + RETRY_LIMIT--; + bitmap = decodeSampled(pathName, sampleSize); + } + + return bitmap; + } + + public static int[] decodeBound(String pathName) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(pathName, options); + + return new int[]{options.outWidth, options.outHeight}; + } + + public static int[] decodeBound(Resources res, int resId) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeResource(res, resId, options); + + return new int[]{options.outWidth, options.outHeight}; + } + + private static int[] pickReqBoundWithRatio(int[] bound, int[][] reqBounds, float ratio) { + float hRatio = bound[1] == 0 ? 0 : (float) bound[0] / (float) bound[1]; + float vRatio = bound[0] == 0 ? 0 : (float) bound[1] / (float) bound[0]; + + if (hRatio >= ratio) { + return reqBounds[0]; + } else if (vRatio >= ratio) { + return reqBounds[1]; + } else { + return reqBounds[2]; + } + } + + public static Bitmap decodeSampled(String pathName, int sampleSize) { + BitmapFactory.Options options = new BitmapFactory.Options(); + + // RGB_565 + options.inPreferredConfig = Bitmap.Config.RGB_565; + // sample size + options.inSampleSize = sampleSize; + + Bitmap bitmap = null; + try { + bitmap = BitmapFactory.decodeFile(pathName, options); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + return null; + } + + return checkInBitmap(bitmap, options, pathName); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private static Bitmap checkInBitmap(Bitmap bitmap, + BitmapFactory.Options options, String path) { + boolean honeycomb = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + if (honeycomb && bitmap != options.inBitmap && options.inBitmap != null) { + options.inBitmap.recycle(); + options.inBitmap = null; + } + + if (bitmap == null) { + try { + bitmap = BitmapFactory.decodeFile(path, options); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + } + return bitmap; + } + + public static int[] decodeBound(File file) { + InputStream is = null; + try { + is = new FileInputStream(file); + int[] bound = decodeBound(is); + return bound; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return new int[]{0, 0}; + } + + public static int[] decodeBound(InputStream is) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(is, null, options); + + return new int[]{options.outWidth, options.outHeight}; + } + + public static Bitmap decodeSampled(InputStream is, int reqWidth, int reqHeight) { + BitmapFactory.Options options = new BitmapFactory.Options(); + + // RGB_565 + options.inPreferredConfig = Bitmap.Config.RGB_565; + // sample size + options.inSampleSize = getSampleSize(is, reqWidth, reqHeight); + + try { + return BitmapFactory.decodeStream(is, null, options); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + + return null; + } + + public static Bitmap decodeSampled(String pathName, int reqWidth, int reqHeight) { + return decodeSampled(pathName, getSampleSize(pathName, reqWidth, reqHeight)); + } + + public static int getSampleSize(InputStream is, int reqWidth, int reqHeight) { + // decode bound + int[] bound = decodeBound(is); + + // calculate sample size + int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight); + + return sampleSize; + } + + public static int getSampleSize(String pathName, int reqWidth, int reqHeight) { + // decode bound + int[] bound = decodeBound(pathName); + + // calculate sample size + int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight); + + return sampleSize; + } + + /** + * ******************************* decode resource ****************************************** + */ + + public static Bitmap decodeSampled(Resources resources, int resId, int reqWidth, int reqHeight) { + return decodeSampled(resources, resId, getSampleSize(resources, resId, reqWidth, reqHeight)); + } + + public static int getSampleSize(Resources resources, int resId, int reqWidth, int reqHeight) { + // decode bound + int[] bound = decodeBound(resources, resId); + + // calculate sample size + int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight); + + return sampleSize; + } + + + public static Bitmap decodeSampled(Resources res, int resId, int sampleSize) { + BitmapFactory.Options options = new BitmapFactory.Options(); + + // RGB_565 + options.inPreferredConfig = Bitmap.Config.RGB_565; + // sample size + options.inSampleSize = sampleSize; + + try { + return BitmapFactory.decodeResource(res, resId, options); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + + return null; + } + + public static boolean extractThumbnail(String videoPath, String thumbPath) { + if (!AttachmentStore.isFileExist(thumbPath)) { + Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.MINI_KIND); + if (thumbnail != null) { + AttachmentStore.saveBitmap(thumbnail, thumbPath, true); + return true; + } + } + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/BitmapUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/BitmapUtil.java new file mode 100644 index 0000000..7982da3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/BitmapUtil.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.media; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +/** + * Created by huangjun on 2016/9/19. + */ +public class BitmapUtil { + + /** + * 获取压缩后的图片 + * + * @param res + * @param resId + * @param reqWidth 所需图片压缩尺寸最小宽度 + * @param reqHeight 所需图片压缩尺寸最小高度 + * @return + */ + public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { + /** + * 1.获取图片的像素宽高(不加载图片至内存中,所以不会占用资源) + * 2.计算需要压缩的比例 + * 3.按将图片用计算出的比例压缩,并加载至内存中使用 + */ + // 首先不加载图片,仅获取图片尺寸 + final BitmapFactory.Options options = new BitmapFactory.Options(); + // 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息 + options.inJustDecodeBounds = true; + // 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象 + BitmapFactory.decodeResource(res, resId, options); + + // 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4 + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + + // 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了 + options.inJustDecodeBounds = false; + options.inScaled = false; + // 利用计算的比例值获取压缩后的图片对象 + return BitmapFactory.decodeResource(res, resId, options); + } + + /** + * 计算压缩比例值 + * + * @param options 解析图片的配置信息 + * @param reqWidth 所需图片压缩尺寸最小宽度 + * @param reqHeight 所需图片压缩尺寸最小高度 + * @return + */ + public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { + // 保存图片原宽高值 + final int height = options.outHeight; + final int width = options.outWidth; + // 初始化压缩比例为1 + int inSampleSize = 1; + + // 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统 + if (height > reqHeight || width > reqWidth) { + + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + // 压缩比例值每次循环两倍增加, + // 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止 + while ((halfHeight / inSampleSize) >= reqHeight + && (halfWidth / inSampleSize) >= reqWidth) { + inSampleSize *= 2; + } + } + + return inSampleSize; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/ImageUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/ImageUtil.java new file mode 100644 index 0000000..49554fa --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/ImageUtil.java @@ -0,0 +1,448 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.media; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; +import android.graphics.Bitmap.Config; +import android.graphics.Matrix; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.media.ExifInterface; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderThumbBase; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.R; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class ImageUtil { + public static class ImageSize { + public int width = 0; + public int height = 0; + + public ImageSize(int width, int height) { + this.width = width; + this.height = height; + } + } + + public final static float MAX_IMAGE_RATIO = 5f; + + public static Bitmap getDefaultBitmapWhenGetFail() { + try { + return getBitmapImmutableCopy(NimUIKit.getContext().getResources(), R.drawable.nim_image_download_failed); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static final Bitmap getBitmapImmutableCopy(Resources res, int id) { + return getBitmap(res.getDrawable(id)).copy(Config.RGB_565, false); + } + + public static final Bitmap getBitmap(Drawable dr) { + if (dr == null) { + return null; + } + + if (dr instanceof BitmapDrawable) { + return ((BitmapDrawable) dr).getBitmap(); + } + + return null; + } + + public static Bitmap rotateBitmapInNeeded(String path, Bitmap srcBitmap) { + if (TextUtils.isEmpty(path) || srcBitmap == null) { + return null; + } + + ExifInterface localExifInterface; + try { + localExifInterface = new ExifInterface(path); + int rotateInt = localExifInterface.getAttributeInt( + ExifInterface.TAG_ORIENTATION, + ExifInterface.ORIENTATION_NORMAL); + float rotate = getImageRotate(rotateInt); + if (rotate != 0) { + Matrix matrix = new Matrix(); + matrix.postRotate(rotate); + Bitmap dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, + srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, + false); + if (dstBitmap == null) { + return srcBitmap; + } else { + if (srcBitmap != null && !srcBitmap.isRecycled()) { + srcBitmap.recycle(); + } + return dstBitmap; + } + } else { + return srcBitmap; + } + } catch (IOException e) { + e.printStackTrace(); + return srcBitmap; + } + } + + /** + * 获得旋转角度 + * + * @param rotate + * @return + */ + public static float getImageRotate(int rotate) { + float f; + if (rotate == 6) { + f = 90.0F; + } else if (rotate == 3) { + f = 180.0F; + } else if (rotate == 8) { + f = 270.0F; + } else { + f = 0.0F; + } + + return f; + } + + public static String makeThumbnail(File imageFile) { + String thumbFilePath = StorageUtil.getWritePath(imageFile.getName(), StorageType.TYPE_THUMB_IMAGE); + File thumbFile = AttachmentStore.create(thumbFilePath); + if (thumbFile == null) { + return null; + } + + boolean result = scaleThumbnail( + imageFile, + thumbFile, + MsgViewHolderThumbBase.getImageMaxEdge(), + MsgViewHolderThumbBase.getImageMinEdge(), + CompressFormat.JPEG, + 60); + if (!result) { + AttachmentStore.delete(thumbFilePath); + return null; + } + + return thumbFilePath; + } + + public static Boolean scaleThumbnail(File srcFile, File dstFile, int dstMaxWH, int dstMinWH, CompressFormat compressFormat, int quality) { + Boolean bRet = false; + Bitmap srcBitmap = null; + Bitmap dstBitmap = null; + BufferedOutputStream bos = null; + + try { + int[] bound = BitmapDecoder.decodeBound(srcFile); + ImageSize size = getThumbnailDisplaySize(bound[0], bound[1], dstMaxWH, dstMinWH); + srcBitmap = BitmapDecoder.decodeSampled(srcFile.getPath(), size.width, size.height); + + // 旋转 + ExifInterface localExifInterface = new ExifInterface(srcFile.getAbsolutePath()); + int rotateInt = localExifInterface.getAttributeInt( + ExifInterface.TAG_ORIENTATION, + ExifInterface.ORIENTATION_NORMAL); + float rotate = getImageRotate(rotateInt); + + Matrix matrix = new Matrix(); + matrix.postRotate(rotate); + + float inSampleSize = 1; + + if (srcBitmap.getWidth() >= dstMinWH && srcBitmap.getHeight() <= dstMaxWH + && srcBitmap.getWidth() >= dstMinWH && srcBitmap.getHeight() <= dstMaxWH) { + //如果第一轮拿到的srcBitmap尺寸都符合要求,不需要再做缩放 + } else { + if (srcBitmap.getWidth() != size.width || srcBitmap.getHeight() != size.height) { + float widthScale = (float) size.width / (float) srcBitmap.getWidth(); + float heightScale = (float) size.height / (float) srcBitmap.getHeight(); + + if (widthScale >= heightScale) { + size.width = srcBitmap.getWidth(); + size.height /= widthScale;//必定小于srcBitmap.getHeight() + inSampleSize = widthScale; + } else { + size.width /= heightScale;//必定小于srcBitmap.getWidth() + size.height = srcBitmap.getHeight(); + inSampleSize = heightScale; + } + } + } + + matrix.postScale(inSampleSize, inSampleSize); + + if (rotate == 0 && inSampleSize == 1) { + dstBitmap = srcBitmap; + } else { + dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, size.width, size.height, matrix, true); + } + + bos = new BufferedOutputStream(new FileOutputStream(dstFile)); + dstBitmap.compress(compressFormat, quality, bos); + bos.flush(); + bRet = true; + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (bos != null) { + try { + bos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + if (srcBitmap != null && !srcBitmap.isRecycled()) { + srcBitmap.recycle(); + srcBitmap = null; + } + + if (dstBitmap != null && !dstBitmap.isRecycled()) { + dstBitmap.recycle(); + dstBitmap = null; + } + } + return bRet; + } + + public static ImageSize getThumbnailDisplaySize(float srcWidth, float srcHeight, float dstMaxWH, float dstMinWH) { + if (srcWidth <= 0 || srcHeight <= 0) { // bounds check + return new ImageSize((int) dstMinWH, (int) dstMinWH); + } + + float shorter; + float longer; + boolean widthIsShorter; + + //store + if (srcHeight < srcWidth) { + shorter = srcHeight; + longer = srcWidth; + widthIsShorter = false; + } else { + shorter = srcWidth; + longer = srcHeight; + widthIsShorter = true; + } + + if (shorter < dstMinWH) { + float scale = dstMinWH / shorter; + shorter = dstMinWH; + if (longer * scale > dstMaxWH) { + longer = dstMaxWH; + } else { + longer *= scale; + } + } else if (longer > dstMaxWH) { + float scale = dstMaxWH / longer; + longer = dstMaxWH; + if (shorter * scale < dstMinWH) { + shorter = dstMinWH; + } else { + shorter *= scale; + } + } + + //restore + if (widthIsShorter) { + srcWidth = shorter; + srcHeight = longer; + } else { + srcWidth = longer; + srcHeight = shorter; + } + + return new ImageSize((int) srcWidth, (int) srcHeight); + } + + public static File getScaledImageFileWithMD5(File imageFile, String mimeType) { + String filePath = imageFile.getPath(); + + if (!isInvalidPictureFile(mimeType)) { + LogUtil.i("ImageUtil", "is invalid picture file"); + return null; + } + + String tempFilePath = getTempFilePath(FileUtil.getExtensionName(filePath)); + File tempImageFile = AttachmentStore.create(tempFilePath); + if (tempImageFile == null) { + return null; + } + + CompressFormat compressFormat = CompressFormat.JPEG; + // 压缩数值由第三方开发者自行决定 + int maxWidth = 720; + int quality = 60; + + if (ImageUtil.scaleImage(imageFile, tempImageFile, maxWidth, compressFormat, quality)) { + return tempImageFile; + } else { + return null; + } + } + + private static String getTempFilePath(String extension) { + return StorageUtil.getWritePath( + NimUIKit.getContext(), + "temp_image_" + StringUtil.get36UUID() + "." + extension, + StorageType.TYPE_TEMP); + } + + public static Boolean scaleImage(File srcFile, File dstFile, int dstMaxWH, CompressFormat compressFormat, int quality) { + Boolean success = false; + + try { + int inSampleSize = SampleSizeUtil.calculateSampleSize(srcFile.getAbsolutePath(), dstMaxWH * dstMaxWH); + Bitmap srcBitmap = BitmapDecoder.decodeSampled(srcFile.getPath(), inSampleSize); + if (srcBitmap == null) { + return success; + } + + float rotate; + String mimeType = com.fengliyan.tianlesue.im.uikit.common.media.picker.util.BitmapUtil.getImageType(srcFile.getAbsolutePath()); + if (!TextUtils.isEmpty(mimeType) && mimeType.equals("image/png")) { + // png格式不能使用ExifInterface + rotate = 0; + } else { + // 旋转 + ExifInterface localExifInterface = new ExifInterface(srcFile.getAbsolutePath()); + int rotateInt = localExifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); + rotate = getImageRotate(rotateInt); + } + + Bitmap dstBitmap; + float scale = (float) Math.sqrt(((float) dstMaxWH * (float) dstMaxWH) / ((float) srcBitmap.getWidth() * (float) srcBitmap.getHeight())); + if (rotate == 0f && scale >= 1) { + dstBitmap = srcBitmap; + } else { + try { + Matrix matrix = new Matrix(); + if (rotate != 0) { + matrix.postRotate(rotate); + } + if (scale < 1) { + matrix.postScale(scale, scale); + } + dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true); + } catch (OutOfMemoryError e) { + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dstFile)); + srcBitmap.compress(compressFormat, quality, bos); + bos.flush(); + bos.close(); + success = true; + + if (!srcBitmap.isRecycled()) + srcBitmap.recycle(); + srcBitmap = null; + + return success; + } + } + + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dstFile)); + dstBitmap.compress(compressFormat, quality, bos); + bos.flush(); + bos.close(); + success = true; + + if (!srcBitmap.isRecycled()) + srcBitmap.recycle(); + srcBitmap = null; + + if (!dstBitmap.isRecycled()) + dstBitmap.recycle(); + dstBitmap = null; + } catch (Exception e) { + e.printStackTrace(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + return success; + } + + public static ImageSize getThumbnailDisplaySize(int maxSide, int minSide, String imagePath) { + int[] bound = BitmapDecoder.decodeBound(imagePath); + ImageSize imageSize = getThumbnailDisplaySize(bound[0], bound[1], maxSide, minSide); + return imageSize; + } + + public static int[] getBoundWithLength(int maxSide, Object imageObject, boolean resizeToDefault) { + int width = -1; + int height = -1; + + int[] bound; + if (String.class.isInstance(imageObject)) { + bound = BitmapDecoder.decodeBound((String) imageObject); + width = bound[0]; + height = bound[1]; + } else if (Integer.class.isInstance(imageObject)) { + bound = BitmapDecoder.decodeBound(NimUIKit.getContext().getResources(), (Integer) imageObject); + width = bound[0]; + height = bound[1]; + } else if (InputStream.class.isInstance(imageObject)) { + bound = BitmapDecoder.decodeBound((InputStream) imageObject); + width = bound[0]; + height = bound[1]; + } + + int defaultWidth = maxSide; + int defaultHeight = maxSide; + if (width <= 0 || height <= 0) { + width = defaultWidth; + height = defaultHeight; + } else if (resizeToDefault) { + if (width > height) { + height = (int) (defaultWidth * ((float) height / (float) width)); + width = defaultWidth; + } else { + width = (int) (defaultHeight * ((float) width / (float) height)); + height = defaultHeight; + } + } + + return new int[]{width, height}; + } + + /** + * 下载失败与获取失败时都统一显示默认下载失败图片 + * + * @return + */ + public static Bitmap getBitmapFromDrawableRes(int res) { + try { + return getBitmapImmutableCopy(NimUIKit.getContext().getResources(), res); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static boolean isInvalidPictureFile(String mimeType) { + String lowerCaseFilepath = mimeType.toLowerCase(); + return (lowerCaseFilepath.contains("jpg") || lowerCaseFilepath.contains("jpeg") + || lowerCaseFilepath.toLowerCase().contains("png") || lowerCaseFilepath.toLowerCase().contains("bmp") || lowerCaseFilepath + .toLowerCase().contains("gif")); + } + + public static boolean isGif(String extension) { + return !TextUtils.isEmpty(extension) && extension.toLowerCase().equals("gif"); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/SampleSizeUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/SampleSizeUtil.java new file mode 100644 index 0000000..38ac035 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/media/SampleSizeUtil.java @@ -0,0 +1,133 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.media; + +import android.opengl.GLES10; + +public class SampleSizeUtil { + + public static int calculateSampleSize(String imagePath, int totalPixel) { + int[] bound = BitmapDecoder.decodeBound(imagePath); + return calculateSampleSize(bound[0], bound[1], totalPixel); + } + + public static int calculateSampleSize(int width, int height, int totalPixel) { + int ratio = 1; + + if (width > 0 && height > 0) { + ratio = (int) Math.sqrt((float) (width * height) / totalPixel); + if (ratio < 1) { + ratio = 1; + } + } + + return ratio; + } + + /** + * Calculate an inSampleSize for use in a {@link android.graphics.BitmapFactory.Options} + * object when decoding bitmaps using the decode* methods from + * {@link android.graphics.BitmapFactory}. This implementation calculates the closest + * inSampleSize that will result in the final decoded bitmap having a width + * and height equal to or larger than the requested width and height. This + * implementation does not ensure a power of 2 is returned for inSampleSize + * which can be faster when decoding but results in a larger bitmap which + * isn't as useful for caching purposes. + * + * @param width + * @param height + * @param reqWidth + * @param reqHeight + * @return + */ + public static int calculateSampleSize(int width, int height, int reqWidth, int reqHeight) { + // can't proceed + if (width <= 0 || height <= 0) { + return 1; + } + // can't proceed + if (reqWidth <= 0 && reqHeight <= 0) { + return 1; + } else if (reqWidth <= 0) { + reqWidth = (int) (width * reqHeight / (float) height + 0.5f); + } else if (reqHeight <= 0) { + reqHeight = (int) (height * reqWidth / (float) width + 0.5f); + } + + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) { + // Calculate ratios of height and width to requested height and width + final int heightRatio = Math.round((float) height / (float) reqHeight); + final int widthRatio = Math.round((float) width / (float) reqWidth); + + // Choose the smallest ratio as inSampleSize value, this will + // guarantee a final image + // with both dimensions larger than or equal to the requested height and width. + inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; + if (inSampleSize == 0) { + inSampleSize = 1; + } + + // This offers some additional logic in case the image has a strange + // aspect ratio. For example, a panorama may have a much larger + // width than height. In these cases the total pixels might still + // end up being too large to fit comfortably in memory, so we should + // be more aggressive with sample down the image (=larger + // inSampleSize). + + final float totalPixels = width * height; + + // Anything more than 2x the requested pixels we'll sample down + // further + final float totalReqPixelsCap = reqWidth * reqHeight * 2; + + while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) { + inSampleSize++; + } + } + + return inSampleSize; + } + + public static final int adjustSampleSizeWithTexture(int sampleSize, int width, int height) { + int textureSize = getTextureSize(); + + if ((textureSize > 0) && ((width > sampleSize) || (height > sampleSize))) { + while ((width / (float) sampleSize) > textureSize || (height / (float) sampleSize) > textureSize) { + sampleSize++; + } + + // 2的指数对齐 + sampleSize = SampleSizeUtil.roundup2n(sampleSize); + } + + return sampleSize; + } + + private static int textureSize = 0; + + //存在第二次拿拿不到的情况,所以把拿到的数据用一个static变量保存下来 + public static final int getTextureSize() { + if (textureSize > 0) { + return textureSize; + } + + int[] params = new int[1]; + GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, params, 0); + textureSize = params[0]; + + return textureSize; + } + + // 将x向上对齐到2的幂指数 + private static final int roundup2n(int x) { + if ((x & (x - 1)) == 0) { + return x; + } + int pos = 0; + while (x > 0) { + x >>= 1; + ++pos; + } + return 1 << pos; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/ExternalStorage.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/ExternalStorage.java new file mode 100644 index 0000000..d7a5416 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/ExternalStorage.java @@ -0,0 +1,251 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.storage; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Environment; +import android.os.StatFs; +import android.text.TextUtils; +import android.util.Log; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; + +import java.io.File; +import java.io.IOException; + +/** + * package + */ +public class ExternalStorage { + /** + * 外部存储根目录 + */ + private String sdkStorageRoot = null; + + private static ExternalStorage instance; + + private static final String TAG = "ExternalStorage"; + + private boolean hasPermission = true; // 是否拥有存储卡权限 + + private Context context; + + private ExternalStorage() { + + } + + synchronized public static ExternalStorage getInstance() { + if (instance == null) { + instance = new ExternalStorage(); + } + return instance; + } + + public void init(Context context, String sdkStorageRoot) { + this.context = context; + // 判断权限 + hasPermission = checkPermission(context); + + if (!TextUtils.isEmpty(sdkStorageRoot)) { + File dir = new File(sdkStorageRoot); + if (!dir.exists()) { + dir.mkdirs(); + } + if (dir.exists() && !dir.isFile()) { + this.sdkStorageRoot = sdkStorageRoot; + if (!sdkStorageRoot.endsWith("/")) { + this.sdkStorageRoot = sdkStorageRoot + "/"; + } + } + } + + if (TextUtils.isEmpty(this.sdkStorageRoot)) { + loadStorageState(context); + } + + createSubFolders(); + } + + private void loadStorageState(Context context) { + String externalPath = Environment.getExternalStorageDirectory().getPath(); + this.sdkStorageRoot = ConstUrl.DEFAULT_PATH; + } + + private void createSubFolders() { + boolean result = true; + File root = new File(sdkStorageRoot); + if (root.exists() && !root.isDirectory()) { + root.delete(); + } + for (StorageType storageType : StorageType.values()) { + result &= makeDirectory(sdkStorageRoot + storageType.getStoragePath()); + } + if (result) { + createNoMediaFile(sdkStorageRoot); + } + } + + /** + * 创建目录 + * + * @param path + * @return + */ + private boolean makeDirectory(String path) { + File file = new File(path); + boolean exist = file.exists(); + if (!exist) { + exist = file.mkdirs(); + } + return exist; + } + + protected static String NO_MEDIA_FILE_NAME = ".nomedia"; + + private void createNoMediaFile(String path) { + File noMediaFile = new File(path + "/" + NO_MEDIA_FILE_NAME); + try { + if (!noMediaFile.exists()) { + noMediaFile.createNewFile(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 文件全名转绝对路径(写) + * + * @param fileName 文件全名(文件名.扩展名) + * @return 返回绝对路径信息 + */ + public String getWritePath(String fileName, StorageType fileType) { + return pathForName(fileName, fileType, false, false); + } + + private String pathForName(String fileName, StorageType type, boolean dir, + boolean check) { + String directory = getDirectoryByDirType(type); + StringBuilder path = new StringBuilder(directory); + + if (!dir) { + path.append(fileName); + } + + String pathString = path.toString(); + File file = new File(pathString); + + if (check) { + if (file.exists()) { + if ((dir && file.isDirectory()) + || (!dir && !file.isDirectory())) { + return pathString; + } + } + + return ""; + } else { + return pathString; + } + } + + /** + * 返回指定类型的文件夹路径 + * + * @param fileType + * @return + */ + public String getDirectoryByDirType(StorageType fileType) { + return sdkStorageRoot + fileType.getStoragePath(); + } + + /** + * 根据输入的文件名和类型,找到该文件的全路径。 + * + * @param fileName + * @param fileType + * @return 如果存在该文件,返回路径,否则返回空 + */ + public String getReadPath(String fileName, StorageType fileType) { + if (TextUtils.isEmpty(fileName)) { + return ""; + } + + return pathForName(fileName, fileType, false, true); + } + + public boolean isSdkStorageReady() { + String externalRoot = ConstUrl.DEFAULT_PATH; + if (this.sdkStorageRoot.startsWith(externalRoot)) { + return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); + } else { + return true; + } + } + + /** + * 获取外置存储卡剩余空间 + * + * @return + */ + public long getAvailableExternalSize() { + return getResidualSpace(sdkStorageRoot); + } + + /** + * 获取目录剩余空间 + * + * @param directoryPath + * @return + */ + private long getResidualSpace(String directoryPath) { + try { + StatFs sf = new StatFs(directoryPath); + long blockSize = sf.getBlockSize(); + long availCount = sf.getAvailableBlocks(); + long availCountByte = availCount * blockSize; + return availCountByte; + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + /** + * SD卡存储权限检查 + */ + private boolean checkPermission(Context context) { + if (context == null) { + Log.e(TAG, "checkMPermission context null"); + return false; + } + + // 写权限有了默认就赋予了读权限 + PackageManager pm = context.getPackageManager(); + if (PackageManager.PERMISSION_GRANTED != + pm.checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context.getApplicationInfo().packageName)) { + Log.e(TAG, "without permission to access storage"); + return false; + } + + return true; + } + + /** + * 有效性检查 + */ + public boolean checkStorageValid() { + if (hasPermission) { + return true; // M以下版本&授权过的M版本不需要检查 + } + + hasPermission = checkPermission(context); // 检查是否已经获取权限了 + if (hasPermission) { + Log.i(TAG, "get permission to access storage"); + + // 已经重新获得权限,那么重新检查一遍初始化过程 + createSubFolders(); + } + return hasPermission; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/StorageType.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/StorageType.java new file mode 100644 index 0000000..ddfbed5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/StorageType.java @@ -0,0 +1,52 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.storage; + +public enum StorageType { + TYPE_LOG(DirectoryName.LOG_DIRECTORY_NAME), + TYPE_TEMP(DirectoryName.TEMP_DIRECTORY_NAME), + TYPE_FILE(DirectoryName.FILE_DIRECTORY_NAME), + TYPE_AUDIO(DirectoryName.AUDIO_DIRECTORY_NAME), + TYPE_IMAGE(DirectoryName.IMAGE_DIRECTORY_NAME), + TYPE_VIDEO(DirectoryName.VIDEO_DIRECTORY_NAME), + TYPE_THUMB_IMAGE(DirectoryName.THUMB_DIRECTORY_NAME), + TYPE_THUMB_VIDEO(DirectoryName.THUMB_DIRECTORY_NAME),; + private DirectoryName storageDirectoryName; + private long storageMinSize; + + public String getStoragePath() { + return storageDirectoryName.getPath(); + } + + public long getStorageMinSize() { + return storageMinSize; + } + + StorageType(DirectoryName dirName) { + this(dirName, StorageUtil.THRESHOLD_MIN_SPCAE); + } + + StorageType(DirectoryName dirName, long storageMinSize) { + this.storageDirectoryName = dirName; + this.storageMinSize = storageMinSize; + } + + enum DirectoryName { + AUDIO_DIRECTORY_NAME("audio/"), + DATA_DIRECTORY_NAME("data/"), + FILE_DIRECTORY_NAME("file/"), + LOG_DIRECTORY_NAME("log/"), + TEMP_DIRECTORY_NAME("temp/"), + IMAGE_DIRECTORY_NAME("image/"), + THUMB_DIRECTORY_NAME("thumb/"), + VIDEO_DIRECTORY_NAME("video/"),; + + private String path; + + public String getPath() { + return path; + } + + private DirectoryName(String path) { + this.path = path; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/StorageUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/StorageUtil.java new file mode 100644 index 0000000..12ed238 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/StorageUtil.java @@ -0,0 +1,127 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.storage; + +import android.content.Context; +import android.os.Build; +import android.os.Environment; +import android.text.TextUtils; + +import java.io.File; + +public class StorageUtil { + public final static long K = 1024; + public final static long M = 1024 * 1024; + // 外置存储卡默认预警临界值 + private static final long THRESHOLD_WARNING_SPACE = 100 * M; + // 保存文件时所需的最小空间的默认值 + static final long THRESHOLD_MIN_SPCAE = 20 * M; + + public static void init(Context context, String rootPath) { + ExternalStorage.getInstance().init(context, rootPath); + } + + /** + * 获取文件保存路径,没有toast提示 + * + * @param fileName + * @param fileType + * @return 可用的保存路径或者null + */ + public static String getWritePath(String fileName, StorageType fileType) { + return getWritePath(null, fileName, fileType, false); + } + + /** + * 获取文件保存路径 + * + * @param fileName 文件全名 + * @param tip 空间不足时是否给出默认的toast提示 + * @return 可用的保存路径或者null + */ + private static String getWritePath(Context context, String fileName, StorageType fileType, boolean tip) { + String path = ExternalStorage.getInstance().getWritePath(fileName, fileType); + if (TextUtils.isEmpty(path)) { + return null; + } + File dir = new File(path).getParentFile(); + if (dir != null && !dir.exists()) { + dir.mkdirs(); + } + return path; + } + + /** + * 判断能否使用外置存储 + */ + public static boolean isExternalStorageExist() { + return ExternalStorage.getInstance().isSdkStorageReady(); + } + + + /** + * 判断外部存储是否存在,以及是否有足够空间保存指定类型的文件 + * + * @param context + * @param fileType + * @param tip 是否需要toast提示 + * @return false: 无存储卡或无空间可写, true: 表示ok + */ + public static boolean hasEnoughSpaceForWrite(Context context, StorageType fileType, boolean tip) { + if (!ExternalStorage.getInstance().isSdkStorageReady()) { + return false; + } + + long residual = ExternalStorage.getInstance().getAvailableExternalSize(); + if (residual < fileType.getStorageMinSize()) { + return false; + } else if (residual < THRESHOLD_WARNING_SPACE) { + } + + return true; + } + + /** + * 根据输入的文件名和类型,找到该文件的全路径。 + * + * @param fileName + * @param fileType + * @return 如果存在该文件,返回路径,否则返回空 + */ + public static String getReadPath(String fileName, StorageType fileType) { + return ExternalStorage.getInstance().getReadPath(fileName, fileType); + } + + /** + * 获取文件保存路径,空间不足时有toast提示 + * + * @param context + * @param fileName + * @param fileType + * @return 可用的保存路径或者null + */ + public static String getWritePath(Context context, String fileName, StorageType fileType) { + return getWritePath(context, fileName, fileType, true); + } + + public static String getDirectoryByDirType(StorageType fileType) { + return ExternalStorage.getInstance().getDirectoryByDirType(fileType); + } + + public static String getSystemImagePath() { + if (Build.VERSION.SDK_INT > 7) { + String picturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath(); + return picturePath + "/nim/"; + } else { + String picturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath(); + return picturePath + "/nim/"; + } + } + + public static boolean isInvalidVideoFile(String filePath) { + return filePath.toLowerCase().endsWith(".3gp") + || filePath.toLowerCase().endsWith(".mp4"); + } + + public static void checkValid() { + ExternalStorage.getInstance().checkStorageValid(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/SysSPUtils.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/SysSPUtils.java new file mode 100644 index 0000000..f23c677 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/storage/SysSPUtils.java @@ -0,0 +1,81 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.storage; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; + +public final class SysSPUtils { + + private final static String name = "config"; + private final static int mode = Context.MODE_PRIVATE; + + /** + * 保存首选项 + * @param context + * @param key + * @param value + */ + public static void saveBoolean(Context context, String key, boolean value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + Editor edit = sp.edit(); + edit.putBoolean(key, value); + edit.commit(); + } + public static void saveInt(Context context, String key, int value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + Editor edit = sp.edit(); + edit.putInt(key, value); + edit.commit(); + } + public static void saveString(Context context, String key, String value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + Editor edit = sp.edit(); + edit.putString(key, value); + edit.commit(); + } + + + /** + * 获取首选项 + * @param context + * @param key + * @param defValue + * @return + */ + public static boolean getBoolean(Context context, String key, boolean defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getBoolean(key, defValue); + } + + public static int getInt(Context context, String key, int defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, defValue); + } + + public static int getInt(Context context, String key){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, 0); + } + + public static String getString(Context context, String key, String defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, defValue); + } + + public static String getString(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, ""); + } + + /** + * 清除保存 + * @param context + */ + public static void clear(Context context){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + Editor editor = sp.edit(); + editor.clear(); + editor.commit(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/HexDump.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/HexDump.java new file mode 100644 index 0000000..15f19c4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/HexDump.java @@ -0,0 +1,172 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.string; + +import java.io.IOException; +import java.io.StringReader; + +public class HexDump { + class HexTablifier { + private int m_row = 8; + + private String m_pre = ""; + + private String m_post = "\n"; + + public HexTablifier() { + } + + public HexTablifier(int row) { + this(row, "", "\n"); + } + + public HexTablifier(int row, String pre) { + this(row, pre, "\n"); + } + + public HexTablifier(int row, String pre, String post) { + m_row = row; + m_pre = pre; + m_post = post; + } + + public String format(String hex) { + StringReader reader = new StringReader(hex); + StringBuilder builder = new StringBuilder(hex.length() * 2); + + try { + while (getHexLine(builder, reader)) { + } + } catch (IOException e) { + // 不应该有异常出现。 + } + + return builder.toString(); + } + + private boolean getHexLine(StringBuilder builder, StringReader reader) + throws IOException { + StringBuilder lineBuilder = new StringBuilder(); + boolean result = true; + + for (int i = 0; i < m_row; i++) { + result = getHexByte(lineBuilder, reader); + + if (result == false) + break; + } + + if (lineBuilder.length() > 0) { + builder.append(m_pre); + builder.append(lineBuilder); + builder.append(m_post); + } + + return result; + } + + private boolean getHexByte(StringBuilder builder, StringReader reader) + throws IOException { + char[] hexByte = new char[4]; + int bytesRead = reader.read(hexByte); + + if (bytesRead == -1) + return false; + + builder.append(hexByte, 0, bytesRead); + builder.append(" "); + + return bytesRead == 4; + } + } + + private static final char m_hexCodes[] = {'0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + private static final int m_shifts[] = {60, 56, 52, 48, 44, 40, 36, 32, 28, + 24, 20, 16, 12, 8, 4, 0}; + + public static String tablify(byte[] bytes) { + return (new HexDump()).new HexTablifier().format(HexDump.toHex(bytes)); + } + + public static String tablify(byte[] bytes, int row) { + return (new HexDump()).new HexTablifier(row).format(HexDump + .toHex(bytes)); + } + + public static String tablify(byte[] bytes, int row, String pre) { + return (new HexDump()).new HexTablifier(row, pre).format(HexDump + .toHex(bytes)); + } + + public static String tablify(String hex, int row, String pre, String post) { + return (new HexDump()).new HexTablifier(row, pre, post).format(hex); + } + + private static String toHex(final long value, final int digitNum) { + StringBuilder result = new StringBuilder(digitNum); + + for (int j = 0; j < digitNum; j++) { + int index = (int) ((value >> m_shifts[j + (16 - digitNum)]) & 15); + result.append(m_hexCodes[index]); + } + + return result.toString(); + } + + public static String toHex(final byte value) { + return toHex(value, 2); + } + + public static String toHex(final short value) { + return toHex(value, 4); + } + + public static String toHex(final int value) { + return toHex(value, 8); + } + + public static String toHex(final long value) { + return toHex(value, 16); + } + + public static String toHex(final byte[] value) { + return toHex(value, 0, value.length); + } + + public static String toHex(final byte[] value, final int offset, + final int length) { + StringBuilder retVal = new StringBuilder(); + + int end = offset + length; + for (int x = offset; x < end; x++) + retVal.append(toHex(value[x])); + + return retVal.toString(); + } + + public static byte[] restoreBytes(String hex) { + byte[] bytes = new byte[hex.length() / 2]; + for (int i = 0; i < bytes.length; ++i) { + int c1 = charToNumber(hex.charAt(2 * i)); + int c2 = charToNumber(hex.charAt(2 * i + 1)); + if (c1 == -1 || c2 == -1) { + return null; + } + bytes[i] = (byte) ((c1 << 4) + c2); + } + + return bytes; + } + + private static int charToNumber(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 0xa; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 0xA; + } else { + return -1; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/MD5.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/MD5.java new file mode 100644 index 0000000..cc250f1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/MD5.java @@ -0,0 +1,56 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.string; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; + +public class MD5 { + + public static String getStringMD5(String value) { + if (value == null || value.trim().length() < 1) { + return null; + } + try { + return getMD5(value.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public static String getMD5(byte[] source) { + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + return HexDump.toHex(md5.digest(source)); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public static String getStreamMD5(String filePath) { + String hash = null; + byte[] buffer = new byte[4096]; + BufferedInputStream in = null; + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + in = new BufferedInputStream(new FileInputStream(filePath)); + int numRead = 0; + while ((numRead = in.read(buffer)) > 0) { + md5.update(buffer, 0, numRead); + } + in.close(); + hash = HexDump.toHex(md5.digest()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (in != null) { + try { + in.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + return hash; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/StringTextWatcher.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/StringTextWatcher.java new file mode 100644 index 0000000..4130d0e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/StringTextWatcher.java @@ -0,0 +1,41 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.string; + +import android.text.Editable; +import android.text.TextWatcher; +import android.widget.EditText; + +/** + * EditText字符数限制 + * Created by hzxuwen on 2015/5/22. + */ +public class StringTextWatcher implements TextWatcher { + private int length; + private EditText editText; + + public StringTextWatcher(int length, EditText editText) { + this.length = length; + this.editText = editText; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + int editEnd = editText.getSelectionEnd(); + editText.removeTextChangedListener(this); + while (StringUtil.counterChars(s.toString()) > length && editEnd > 0) { + s.delete(editEnd - 1, editEnd); + editEnd--; + } + editText.setSelection(editEnd); + editText.addTextChangedListener(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/StringUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/StringUtil.java new file mode 100644 index 0000000..c1061a7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/string/StringUtil.java @@ -0,0 +1,121 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.string; + +import android.text.TextUtils; + +import java.util.Locale; +import java.util.UUID; + +public class StringUtil { + + public static String getPercentString(float percent) { + return String.format(Locale.US, "%d%%", (int) (percent * 100)); + } + + /** + * 删除字符串中的空白符 + * + * @param content + * @return String + */ + public static String removeBlanks(String content) { + if (content == null) { + return null; + } + StringBuilder buff = new StringBuilder(); + buff.append(content); + for (int i = buff.length() - 1; i >= 0; i--) { + if (' ' == buff.charAt(i) || ('\n' == buff.charAt(i)) || ('\t' == buff.charAt(i)) + || ('\r' == buff.charAt(i))) { + buff.deleteCharAt(i); + } + } + return buff.toString(); + } + + /** + * 获取32位uuid + * + * @return + */ + public static String get32UUID() { + return UUID.randomUUID().toString().replaceAll("-", ""); + } + + public static boolean isEmpty(String input) { + return TextUtils.isEmpty(input); + } + + /** + * 生成唯一号 + * + * @return + */ + public static String get36UUID() { + UUID uuid = UUID.randomUUID(); + String uniqueId = uuid.toString(); + return uniqueId; + } + + public static String makeMd5(String source) { + return MD5.getStringMD5(source); + } + + public static final String filterUCS4(String str) { + if (TextUtils.isEmpty(str)) { + return str; + } + + if (str.codePointCount(0, str.length()) == str.length()) { + return str; + } + + StringBuilder sb = new StringBuilder(); + + int index = 0; + while (index < str.length()) { + int codePoint = str.codePointAt(index); + index += Character.charCount(codePoint); + if (Character.isSupplementaryCodePoint(codePoint)) { + continue; + } + + sb.appendCodePoint(codePoint); + } + + return sb.toString(); + } + + /** + * counter ASCII character as one, otherwise two + * + * @param str + * @return count + */ + public static int counterChars(String str) { + // return + if (TextUtils.isEmpty(str)) { + return 0; + } + int count = 0; + for (int i = 0; i < str.length(); i++) { + int tmp = (int) str.charAt(i); + if (tmp > 0 && tmp < 127) { + count += 1; + } else { + count += 2; + } + } + return count; + } + public static String handleBankCard(String bankCardNum) { + String str = ""; + if (bankCardNum.length() >= 4) { + str = bankCardNum.substring(0, 4) + " "; + String substring = bankCardNum.substring(4); + str += handleBankCard(substring); + } else { + str += bankCardNum; + } + return str; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ClipboardUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ClipboardUtil.java new file mode 100644 index 0000000..ea8df4d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ClipboardUtil.java @@ -0,0 +1,21 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.sys; + +import android.content.ClipData; +import android.content.Context; +import android.text.ClipboardManager; + +import com.fengliyan.tianlesue.agora.utils.ToastUtil; + +public class ClipboardUtil { + public static final void clipboardCopyText(Context context, CharSequence text) { + android.content.ClipboardManager cm = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(null, text)); + ToastUtil.showToast(context, "已复制到剪贴板"); + } + + public static final int clipboardTextLength(Context context) { + ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + CharSequence text = cm != null ? cm.getText() : null; + return text != null ? text.length() : 0; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/NetworkUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/NetworkUtil.java new file mode 100644 index 0000000..50bae39 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/NetworkUtil.java @@ -0,0 +1,865 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.sys; + +import android.content.Context; +import android.database.Cursor; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.Uri; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.telephony.TelephonyManager; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; + +public class NetworkUtil { + + public static final String TAG = "NetworkUtil"; + + public static final byte CURRENT_NETWORK_TYPE_NONE = 0; + + /* + * 根据APN区分网络类型 + */ + public static final byte CURRENT_NETWORK_TYPE_WIFI = 1;// wifi + + public static final byte CURRENT_NETWORK_TYPE_CTNET = 2;// ctnet + + public static final byte CURRENT_NETWORK_TYPE_CTWAP = 3;// ctwap + + public static final byte CURRENT_NETWORK_TYPE_CMWAP = 4;// cmwap + + public static final byte CURRENT_NETWORK_TYPE_UNIWAP = 5;// uniwap,3gwap + + public static final byte CURRENT_NETWORK_TYPE_CMNET = 6;// cmnet + + public static final byte CURRENT_NETWORK_TYPE_UNIET = 7;// uninet,3gnet + + /** + * 根据运营商区分网络类型 + */ + public static final byte CURRENT_NETWORK_TYPE_CTC = 10;// ctwap,ctnet + + public static final byte CURRENT_NETWORK_TYPE_CUC = 11;// uniwap,3gwap,uninet,3gnet + + public static final byte CURRENT_NETWORK_TYPE_CM = 12;// cmwap,cmnet + + /** + * apn值 + */ + private static final String CONNECT_TYPE_WIFI = "wifi"; + + private static final String CONNECT_TYPE_CTNET = "ctnet"; + + private static final String CONNECT_TYPE_CTWAP = "ctwap"; + + private static final String CONNECT_TYPE_CMNET = "cmnet"; + + private static final String CONNECT_TYPE_CMWAP = "cmwap"; + + private static final String CONNECT_TYPE_UNIWAP = "uniwap"; + + private static final String CONNECT_TYPE_UNINET = "uninet"; + + private static final String CONNECT_TYPE_UNI3GWAP = "3gwap"; + + private static final String CONNECT_TYPE_UNI3GNET = "3gnet"; + + private static final Uri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn"); + + public static byte curNetworkType = CURRENT_NETWORK_TYPE_NONE; + + /* + * + * 获取网络类型 + * + */ + public static int getNetType(Context context) { + NetworkInfo networkInfo = getActiveNetworkInfo(context); + if (networkInfo == null) { + return -1; + } else + return networkInfo.getType(); + } + + + /** + * 判断当前网络类型。WIFI,NET,WAP + * + * @param context + * @return + */ + public static byte getCurrentNetType(Context context) { + NetworkInfo networkInfo = getActiveNetworkInfo(context); + byte type = CURRENT_NETWORK_TYPE_NONE; + if (networkInfo != null) { + // String typeName = networkInfo.getTypeName(); + // XT800 + String typeName = networkInfo.getExtraInfo(); + if (TextUtils.isEmpty(typeName)) { + typeName = networkInfo.getTypeName(); + } + if (!TextUtils.isEmpty(typeName)) { + String temp = typeName.toLowerCase(); + if (temp.indexOf(CONNECT_TYPE_WIFI) > -1) {// wifi + type = CURRENT_NETWORK_TYPE_WIFI; + } else if (temp.indexOf(CONNECT_TYPE_CTNET) > -1) {// ctnet + type = CURRENT_NETWORK_TYPE_CTNET; + } else if (temp.indexOf(CONNECT_TYPE_CTWAP) > -1) {// ctwap + type = CURRENT_NETWORK_TYPE_CTWAP; + } else if (temp.indexOf(CONNECT_TYPE_CMNET) > -1) {// cmnet + type = CURRENT_NETWORK_TYPE_CMNET; + } else if (temp.indexOf(CONNECT_TYPE_CMWAP) > -1) {// cmwap + type = CURRENT_NETWORK_TYPE_CMWAP; + } else if (temp.indexOf(CONNECT_TYPE_UNIWAP) > -1) {// uniwap + type = CURRENT_NETWORK_TYPE_UNIWAP; + } else if (temp.indexOf(CONNECT_TYPE_UNI3GWAP) > -1) {// 3gwap + type = CURRENT_NETWORK_TYPE_UNIWAP; + } else if (temp.indexOf(CONNECT_TYPE_UNINET) > -1) {// uninet + type = CURRENT_NETWORK_TYPE_UNIET; + } else if (temp.indexOf(CONNECT_TYPE_UNI3GNET) > -1) {// 3gnet + type = CURRENT_NETWORK_TYPE_UNIET; + } + } + } + + if (type == CURRENT_NETWORK_TYPE_NONE) { + String apnType = getApnType(context); + if (apnType != null && apnType.equals(CONNECT_TYPE_CTNET)) {// ctnet + type = CURRENT_NETWORK_TYPE_CTNET; + } else if (apnType != null && apnType.equals(CONNECT_TYPE_CTWAP)) {// ctwap + type = CURRENT_NETWORK_TYPE_CTWAP; + } else if (apnType != null && apnType.equals(CONNECT_TYPE_CMWAP)) {// cmwap + type = CURRENT_NETWORK_TYPE_CMWAP; + } else if (apnType != null && apnType.equals(CONNECT_TYPE_CMNET)) {// cmnet + type = CURRENT_NETWORK_TYPE_CMNET; + } else if (apnType != null && apnType.equals(CONNECT_TYPE_UNIWAP)) {// uniwap + type = CURRENT_NETWORK_TYPE_UNIWAP; + } else if (apnType != null && apnType.equals(CONNECT_TYPE_UNI3GWAP)) {// 3gwap + type = CURRENT_NETWORK_TYPE_UNIWAP; + } else if (apnType != null && apnType.equals(CONNECT_TYPE_UNINET)) {// uninet + type = CURRENT_NETWORK_TYPE_UNIET; + } else if (apnType != null && apnType.equals(CONNECT_TYPE_UNI3GNET)) {// 3gnet + type = CURRENT_NETWORK_TYPE_UNIET; + } + } + curNetworkType = type; + + return type; + } + + /** + * 判断APNTYPE + * + * @param context + * @return + */ + /** + * @deprecated 4.0 + * doc: + * Since the DB may contain corp passwords, we should secure it. Using the same permission as writing to the DB as the read is potentially as damaging as a write + */ + public static String getApnType(Context context) { + + String apntype = "nomatch"; + Cursor c = context.getContentResolver().query(PREFERRED_APN_URI, null, null, null, null); + if (c != null) { + if (c.moveToFirst()) { + String user = c.getString(c.getColumnIndex("user")); + if (user != null && user.startsWith(CONNECT_TYPE_CTNET)) { + apntype = CONNECT_TYPE_CTNET; + } else if (user != null && user.startsWith(CONNECT_TYPE_CTWAP)) { + apntype = CONNECT_TYPE_CTWAP; + } else if (user != null && user.startsWith(CONNECT_TYPE_CMWAP)) { + apntype = CONNECT_TYPE_CMWAP; + } else if (user != null && user.startsWith(CONNECT_TYPE_CMNET)) { + apntype = CONNECT_TYPE_CMNET; + } else if (user != null && user.startsWith(CONNECT_TYPE_UNIWAP)) { + apntype = CONNECT_TYPE_UNIWAP; + } else if (user != null && user.startsWith(CONNECT_TYPE_UNINET)) { + apntype = CONNECT_TYPE_UNINET; + } else if (user != null && user.startsWith(CONNECT_TYPE_UNI3GWAP)) { + apntype = CONNECT_TYPE_UNI3GWAP; + } else if (user != null && user.startsWith(CONNECT_TYPE_UNI3GNET)) { + apntype = CONNECT_TYPE_UNI3GNET; + } + } + c.close(); + c = null; + } + + return apntype; + } + + /** + * 判断是否有网络可用 + * + * @param context + * @return + */ + public static boolean isNetAvailable(Context context) { + NetworkInfo networkInfo = getActiveNetworkInfo(context); + if (networkInfo != null) { + return networkInfo.isAvailable(); + } else { + return false; + } + } + + /** + * 此判断不可靠 + * + * @param context + * @return + */ + public static boolean isNetworkConnected(Context context) { + NetworkInfo networkInfo = getActiveNetworkInfo(context); + if (networkInfo != null) { + boolean a = networkInfo.isConnected(); + return a; + } else { + return false; + } + } + + /** + * 获取可用的网络信息 + * + * @param context + * @return + */ + private static NetworkInfo getActiveNetworkInfo(Context context) { + try { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + return cm.getActiveNetworkInfo(); + } catch (Exception e) { + return null; + } + } + + public static boolean isWifiOr3G(Context context) { + if (isWifi(context)) { + return true; + } else { + return is3G(context); + } + } + + public static boolean is2G(Context context) { + return !isWifiOr3G(context); + } + + public static boolean is3G(Context context) { + int type = getNetworkClass(context); + if (type == NETWORK_CLASS_3_G || type == NETWORK_CLASS_4_G) { + return true; + } else { + return false; + } + } + + /** + * 当前网络是否是wifi网络 + * + * @param context + * @return + */ + public static boolean isWifi(Context context) { + try { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo ni = cm.getActiveNetworkInfo(); + if (ni != null) { + if (ni.getType() == ConnectivityManager.TYPE_WIFI) { + return true; + } else { + return false; + } + } else { + return false; + } + } catch (Exception e) { + return false; + } + } + + public static boolean getNetworkConnectionStatus(Context context) { + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (manager == null) { + return false; + } + + NetworkInfo info = manager.getActiveNetworkInfo(); + if (info == null) { + return false; + } + + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + if (tm == null) { + return false; + } + + if ((tm.getDataState() == TelephonyManager.DATA_CONNECTED || tm.getDataState() == TelephonyManager.DATA_ACTIVITY_NONE) + && info.isAvailable()) { + return true; + } else { + return false; + } + } + + public static String getNetworkProxyInfo(Context context) { + String proxyHost = android.net.Proxy.getDefaultHost(); + int proxyPort = android.net.Proxy.getDefaultPort(); + String szport = String.valueOf(proxyPort); + String proxyInfo = null; + + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (manager == null) { + return null; + } else { + NetworkInfo info = manager.getActiveNetworkInfo(); + if (info != null) { + String typeName = info.getTypeName().toLowerCase(); + if (typeName != null && typeName.equals("wifi")) { + return null; + } + } else { + return null; + } + } + + if (proxyHost != null && (0 < proxyPort && proxyPort < 65535)) { + proxyInfo = proxyHost + ":" + szport; + return proxyInfo; + } else { + return null; + } + } + + public static String getNetworkProxyUrl(Context context) { + if (isWifi(context)) { + return null; + } + + String proxyHost = android.net.Proxy.getDefaultHost(); + LogUtil.e(TAG, "proxyHost:" + proxyHost); + return proxyHost; + } + + public static String getNetworkProxyUrl() { + /** + * 当网络为wifi时,直接返回空代理: 当ctwap,cmwap,uniwap,3gwap开启时同时开启wifi网络 + * ,通过下面的getDefaultHost接口将得到对应wap网络代理ip ,这是错误的,所以在此判断当前网络是否为wifi + */ + if (curNetworkType == CURRENT_NETWORK_TYPE_WIFI) { + return null; + } + + String proxyHost = android.net.Proxy.getDefaultHost(); + LogUtil.e(TAG, "proxyHost:" + proxyHost); + return proxyHost; + } + + public static int getNetworkProxyPort() { + int proxyPort = android.net.Proxy.getDefaultPort(); + return proxyPort; + } + + public static boolean isCtwap(Context context) { + if (getApnType(context).equals(CONNECT_TYPE_CTWAP)) { + return true; + } else { + return false; + } + } + + public static boolean isUniwap(Context context) { + if (getApnType(context).equals(CONNECT_TYPE_UNIWAP)) { + return true; + } else { + return false; + } + } + + public static boolean isCmwap(Context context) { + if (getApnType(context).equals(CONNECT_TYPE_CMWAP)) { + return true; + } else { + return false; + } + } + + /** + * 判断是否是电信网络(ctwap,ctnet) + * + * @return + */ + public static boolean isCtcNetwork(Context context) { + byte type = getCurrentNetType(context); + + return isCtcNetwork(type); + } + + public static boolean isCtcNetwork(String apnName) { + if (apnName == null) { + return false; + } + + if (apnName.equals(CONNECT_TYPE_CTWAP) || apnName.equals(CONNECT_TYPE_CTNET)) { + return true; + } else { + return false; + } + } + + public static boolean isCtcNetwork(byte type) { + if (type == CURRENT_NETWORK_TYPE_CTWAP || type == CURRENT_NETWORK_TYPE_CTNET) { + return true; + } else { + return false; + } + } + + /** + * 判断是否是联通网络(uniwap,uninet,3gwap,3gnet) + * + * @return + */ + public static boolean isCucNetwork(Context context) { + byte type = getCurrentNetType(context); + + return isCucNetwork(type); + } + + public static boolean isCucNetwork(String apnName) { + if (apnName == null) { + return false; + } + + if (apnName.equals(CONNECT_TYPE_UNIWAP) || apnName.equals(CONNECT_TYPE_UNINET) + || apnName.equals(CONNECT_TYPE_UNI3GWAP) || apnName.equals(CONNECT_TYPE_UNI3GNET)) { + return true; + } else { + return false; + } + } + + public static boolean isCucNetwork(byte type) { + if (type == CURRENT_NETWORK_TYPE_UNIWAP || type == CURRENT_NETWORK_TYPE_UNIET) { + return true; + } else { + return false; + } + } + + /** + * 判断是否是移动网络(cmwap,cmnet) + * + * @return + */ + public static boolean isCmbNetwork(Context context) { + byte type = getCurrentNetType(context); + + return isCmbNetwork(type); + } + + public static boolean isCmbNetwork(String apnName) { + if (apnName == null) { + return false; + } + + if (apnName.equals(CONNECT_TYPE_CMWAP) || apnName.equals(CONNECT_TYPE_CMNET)) { + return true; + } else { + return false; + } + } + + public static boolean isCmbNetwork(byte type) { + if (type == CURRENT_NETWORK_TYPE_CMWAP || type == CURRENT_NETWORK_TYPE_CMNET) { + return true; + } else { + return false; + } + } + + /** + * 获取网络运营商类型(中国移动,中国联通,中国电信,wifi) + * + * @param context + * @return + */ + public static byte getNetworkOperators(Context context) { + if (isWifi(context)) { + return CURRENT_NETWORK_TYPE_WIFI; + } else if (isCtcNetwork(context)) { + return CURRENT_NETWORK_TYPE_CTC; + } else if (isCmbNetwork(context)) { + return CURRENT_NETWORK_TYPE_CM; + } else if (isCucNetwork(context)) { + return CURRENT_NETWORK_TYPE_CUC; + } else { + return CURRENT_NETWORK_TYPE_NONE; + } + } + + public static byte getNetworkOperators(byte type) { + if (type == CURRENT_NETWORK_TYPE_NONE) { + return CURRENT_NETWORK_TYPE_NONE; + } else if (type == CURRENT_NETWORK_TYPE_WIFI) { + return CURRENT_NETWORK_TYPE_WIFI; + } else if (type == CURRENT_NETWORK_TYPE_CTNET || type == CURRENT_NETWORK_TYPE_CTWAP) { + return CURRENT_NETWORK_TYPE_CTC; + } else if (type == CURRENT_NETWORK_TYPE_CMWAP || type == CURRENT_NETWORK_TYPE_CMNET) { + return CURRENT_NETWORK_TYPE_CM; + } else if (type == CURRENT_NETWORK_TYPE_UNIWAP || type == CURRENT_NETWORK_TYPE_UNIET) { + return CURRENT_NETWORK_TYPE_CUC; + } else { + return CURRENT_NETWORK_TYPE_NONE; + } + } + + /** + * 是否需要设置代理(网络请求,一般用于wap网络,但有些机型设置代理会导致系统异常) + * + * @return + */ + public static boolean isNeedSetProxyForNetRequest() { // #00044 + + if (Build.MODEL.equals("SCH-N719") || Build.MODEL.equals("SCH-I939D")) { + return false; + } else { + return true; + } + } + + /** + * get mac address of wifi if wifi is active + */ + + public static String getActiveMacAddress(Context context) { + WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + + WifiInfo info = wifi.getConnectionInfo(); + + if (info != null) { + return info.getMacAddress(); + } + + return ""; + } + + public static String getNetworkInfo(Context context) { + String info = ""; + ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity != null) { + NetworkInfo activeNetInfo = connectivity.getActiveNetworkInfo(); + if (activeNetInfo != null) { + if (activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) { + info = activeNetInfo.getTypeName(); + } else { + StringBuilder sb = new StringBuilder(); + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + sb.append(activeNetInfo.getTypeName()); + sb.append(" ["); + if (tm != null) { + // Result may be unreliable on CDMA networks + sb.append(tm.getNetworkOperatorName()); + sb.append("#"); + } + sb.append(activeNetInfo.getSubtypeName()); + sb.append("]"); + info = sb.toString(); + } + } + } + return info; + } + + public enum NetworkSpeedMode { + LOW, NORMAL, HIGH, UNKNOWN + } + + /** + * 网络类型 + */ + public static final int NETWORK_CLASS_UNKNOWN = 0; + + public static final int NETWORK_CLASS_2_G = 1; + + public static final int NETWORK_CLASS_3_G = 2; + + public static final int NETWORK_CLASS_4_G = 3; + + public static final int NETWORK_CLASS_WIFI = 10; + + /** + * 仅判断Mobile网络的慢速.蓝牙等其他网络不做判断. + * + * @param context + * @return + */ + public static NetworkSpeedMode getNetworkSpeedModeInMobile(Context context) { + ConnectivityManager connectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivityManager != null) { + NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); + if (networkInfo != null) { + if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) { + switch (networkInfo.getSubtype()) { + case TelephonyManager.NETWORK_TYPE_IDEN: // ~25 kbps + return NetworkSpeedMode.LOW; + case TelephonyManager.NETWORK_TYPE_CDMA: // ~ 14-64 kbps + return NetworkSpeedMode.LOW; + case TelephonyManager.NETWORK_TYPE_1xRTT: // ~ 50-100 kbps + return NetworkSpeedMode.LOW; + case TelephonyManager.NETWORK_TYPE_EDGE: // ~ 50-100 kbps + return NetworkSpeedMode.LOW; + case TelephonyManager.NETWORK_TYPE_GPRS: // ~ 100 kbps + return NetworkSpeedMode.LOW; + + case TelephonyManager.NETWORK_TYPE_EVDO_0: // ~ 400-1000 + // kbps + return NetworkSpeedMode.NORMAL; + case TelephonyManager.NETWORK_TYPE_EVDO_A: // ~ 600-1400 + // kbps + return NetworkSpeedMode.NORMAL; + case TelephonyManager.NETWORK_TYPE_HSPA: // ~ 700-1700 kbps + return NetworkSpeedMode.NORMAL; + case TelephonyManager.NETWORK_TYPE_UMTS: // ~ 400-7000 kbps + return NetworkSpeedMode.NORMAL; + case 14: // TelephonyManager.NETWORK_TYPE_EHRPD: // ~ 1-2 + // Mbps + return NetworkSpeedMode.NORMAL; + case 12: // TelephonyManager.NETWORK_TYPE_EVDO_B: // ~ 5 + // Mbps + return NetworkSpeedMode.NORMAL; + + case TelephonyManager.NETWORK_TYPE_HSDPA: // ~ 2-14 Mbps + return NetworkSpeedMode.HIGH; + case TelephonyManager.NETWORK_TYPE_HSUPA: // ~ 1-23 Mbps + return NetworkSpeedMode.HIGH; + case 15: // TelephonyManager.NETWORK_TYPE_HSPAP: // ~ 10-20 + // Mbps + return NetworkSpeedMode.HIGH; + case 13: // TelephonyManager.NETWORK_TYPE_LTE: // ~ 10+ Mbps + return NetworkSpeedMode.HIGH; + + case TelephonyManager.NETWORK_TYPE_UNKNOWN: + return NetworkSpeedMode.NORMAL; + default: + break; + } + } + } + } + return NetworkSpeedMode.UNKNOWN; + } + + /** + * 获取在Mobile网络下的网络类型. 2G,3G,4G + * + * @param context + * @return + */ + public static int getNetworkClass(Context context) { + ConnectivityManager connectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivityManager != null) { + NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); + if (networkInfo != null) { + if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) { + switch (networkInfo.getSubtype()) { + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_1xRTT: + case TelephonyManager.NETWORK_TYPE_IDEN: + return NETWORK_CLASS_2_G; + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case 12: // TelephonyManager.NETWORK_TYPE_EVDO_B: + case 14: // TelephonyManager.NETWORK_TYPE_EHRPD: + case 15: // TelephonyManager.NETWORK_TYPE_HSPAP: + return NETWORK_CLASS_3_G; + case 13: // TelephonyManager.NETWORK_TYPE_LTE: + return NETWORK_CLASS_4_G; + default: + return NETWORK_CLASS_UNKNOWN; + } + } else if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { + return NETWORK_CLASS_WIFI; + } + } + } + return NETWORK_CLASS_UNKNOWN; + } + + public static String getNetworkTypeName(Context context) { + String networkName = "UNKNOWN"; + ConnectivityManager connectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivityManager != null) { + NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); + if (networkInfo != null) { + networkName = getNetworkTypeName(networkInfo.getType()); + if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) { + networkName += "#" + getNetworkTypeNameInMobile(networkInfo.getSubtype()); + } + } + } + return networkName; + } + + private static String getNetworkTypeNameInMobile(int type) { + switch (type) { + case TelephonyManager.NETWORK_TYPE_GPRS: + return "GPRS"; + case TelephonyManager.NETWORK_TYPE_EDGE: + return "EDGE"; + case TelephonyManager.NETWORK_TYPE_UMTS: + return "UMTS"; + case TelephonyManager.NETWORK_TYPE_HSDPA: + return "HSDPA"; + case TelephonyManager.NETWORK_TYPE_HSUPA: + return "HSUPA"; + case TelephonyManager.NETWORK_TYPE_HSPA: + return "HSPA"; + case TelephonyManager.NETWORK_TYPE_CDMA: + return "CDMA"; + case TelephonyManager.NETWORK_TYPE_EVDO_0: + return "CDMA - EvDo rev. 0"; + case TelephonyManager.NETWORK_TYPE_EVDO_A: + return "CDMA - EvDo rev. A"; + case TelephonyManager.NETWORK_TYPE_EVDO_B: + return "CDMA - EvDo rev. B"; + case TelephonyManager.NETWORK_TYPE_1xRTT: + return "CDMA - 1xRTT"; + case TelephonyManager.NETWORK_TYPE_LTE: + return "LTE"; + case TelephonyManager.NETWORK_TYPE_EHRPD: + return "CDMA - eHRPD"; + case TelephonyManager.NETWORK_TYPE_IDEN: + return "iDEN"; + case TelephonyManager.NETWORK_TYPE_HSPAP: + return "HSPA+"; + default: + return "UNKNOWN"; + } + } + + private static String getNetworkTypeName(int type) { + switch (type) { + case ConnectivityManager.TYPE_MOBILE: + return "MOBILE"; + case ConnectivityManager.TYPE_WIFI: + return "WIFI"; + case ConnectivityManager.TYPE_MOBILE_MMS: + return "MOBILE_MMS"; + case ConnectivityManager.TYPE_MOBILE_SUPL: + return "MOBILE_SUPL"; + case ConnectivityManager.TYPE_MOBILE_DUN: + return "MOBILE_DUN"; + case ConnectivityManager.TYPE_MOBILE_HIPRI: + return "MOBILE_HIPRI"; + case ConnectivityManager.TYPE_WIMAX: + return "WIMAX"; + case ConnectivityManager.TYPE_BLUETOOTH: + return "BLUETOOTH"; + case ConnectivityManager.TYPE_DUMMY: + return "DUMMY"; + case ConnectivityManager.TYPE_ETHERNET: + return "ETHERNET"; + case 10: // ConnectivityManager.TYPE_MOBILE_FOTA: + return "MOBILE_FOTA"; + case 11: // ConnectivityManager.TYPE_MOBILE_IMS: + return "MOBILE_IMS"; + case 12: // ConnectivityManager.TYPE_MOBILE_CBS: + return "MOBILE_CBS"; + case 13: // ConnectivityManager.TYPE_WIFI_P2P: + return "WIFI_P2P"; + default: + return Integer.toString(type); + } + } + + //中国电信 + public static final int ISP_CTCC = 0; + //中国联通 + public static final int ISP_CUCC = 1; + //中国移动 + public static final int ISP_CMCC = 2; + //中国铁通 + public static final int ISP_CTT = 3; + //其他 + public static final int ISP_OTHERS = -1; + + public static String getSimOperator(Context context) { + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + if (tm != null) { + return tm.getSimOperator(); + } + return null; + } + + public static String getNetworkOperator(Context context) { + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + if (tm != null) { + return tm.getNetworkOperator(); + } + return null; + } + + + public interface LinkNetWorkType { + public static final int UNKNOWN = 0; + public static final int WIFI = 1; + public static final int WWAN = 2; + public static final int _2G = 3; + public static final int _3G = 4; + public static final int _4G = 5; + } + + public static int getNetworkTypeForLink(Context context) { + try { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo ni = cm.getActiveNetworkInfo(); + if (ni != null) { + if (ni.getType() == ConnectivityManager.TYPE_WIFI) { + return LinkNetWorkType.WIFI; + } else { + if (ni.getType() == ConnectivityManager.TYPE_MOBILE) { + switch (ni.getSubtype()) { + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_1xRTT: + case TelephonyManager.NETWORK_TYPE_IDEN: + return LinkNetWorkType._2G; + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case 12: // TelephonyManager.NETWORK_TYPE_EVDO_B: + case 14: // TelephonyManager.NETWORK_TYPE_EHRPD: + case 15: // TelephonyManager.NETWORK_TYPE_HSPAP: + return LinkNetWorkType._3G; + case 13: // TelephonyManager.NETWORK_TYPE_LTE: + return LinkNetWorkType._4G; + default: + return LinkNetWorkType._2G; + } + } + } + } + } catch (Exception e) { + return LinkNetWorkType.UNKNOWN; + } + return LinkNetWorkType.UNKNOWN; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ReflectionUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ReflectionUtil.java new file mode 100644 index 0000000..692506f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ReflectionUtil.java @@ -0,0 +1,238 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.sys; + +import android.text.TextUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +/** + * 反射工具类 + * 通过反射获得对应函数功能 + */ +public class ReflectionUtil { + + /** + * 调用Class的静态方法 + */ + public static T invokeClassMethod(String classPath, String methodName, Class[] paramClasses, Object[] params) { + return (T) executeClassLoad(getClass(classPath), methodName, paramClasses, params); + } + + /** + * 调用Class的无参静态方法 + */ + public static Object invokeMethod(Object obj, String methodName, Object[] params) { + return invokeMethod(obj, methodName, null, params); + } + + /** + * 通过类对象,运行指定方法 + * + * @param obj 类对象 + * @param methodName 方法名 + * @param paramTypes 参数对应的类型(如果不指定,那么从params来判断,可能会判断不准确,例如把CharSequence 判断成String,导致反射时方法找不到) + * @param params 参数值 + * @return 失败返回null + */ + public static Object invokeMethod(Object obj, String methodName, Class[] paramTypes, Object[] params) { + if (obj == null || TextUtils.isEmpty(methodName)) { + return null; + } + + Class clazz = obj.getClass(); + try { + if (paramTypes == null) { + if (params != null) { + paramTypes = new Class[params.length]; + for (int i = 0; i < params.length; ++i) { + paramTypes[i] = params[i].getClass(); + } + } + } + Method method = clazz.getMethod(methodName, paramTypes); + method.setAccessible(true); + return method.invoke(obj, params); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /** + * 反射获取对象属性值 + */ + public static Object getFieldValue(Object obj, String fieldName) { + if (obj == null || TextUtils.isEmpty(fieldName)) { + return null; + } + + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(obj); + } catch (Exception e) { + e.printStackTrace(); + } + clazz = clazz.getSuperclass(); + } + + return null; + } + + /** + * 反射修改对象属性值 + */ + public static void setFieldValue(Object obj, String fieldName, Object value) { + if (obj == null || TextUtils.isEmpty(fieldName)) { + return; + } + + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj, value); + return; + } catch (Exception e) { + e.printStackTrace(); + } + clazz = clazz.getSuperclass(); + } + } + + /** + * 获取Class所有的静态成员 + */ + public static List getClassStaticField(Class clazz) { + Field[] fields = clazz.getFields(); + List ret = new ArrayList<>(); + + for (Field field : fields) { + String m = Modifier.toString(field.getModifiers()); + if (m.contains("static")) { + ret.add(field); + } + } + return ret; + } + + /** + * 获取Class所有静态字段的值 + */ + public static List getClassStaticFieldValue(Class clazz) { + Field[] fields = clazz.getFields(); + List ret = new ArrayList<>(); + + for (Field field : fields) { + String m = Modifier.toString(field.getModifiers()); + if (m.contains("static")) { + try { + ret.add(field.get(null)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + return ret; + } + + /** + * 获取某个字段的@annotation + */ + public static A getFieldAnnotationsByType(Field field, Class annotationType) { + return field.getAnnotation(annotationType); + } + + /** + * 判断某个类是否包含某个方法,前提是这个类也存在 + */ + public static boolean hasMethod(String classPath, String methodName, Class[] paramClasses) { + return getMethod(getClass(classPath), methodName, paramClasses) != null; + } + + /** + * 反射修改类的私有静态final变量(常量)的值 + * 注意:对于基本类型的静态常量,JAVA在编译的时候就会把代码中对此常量中引用的地方替换成相应常量值。 + * 结论:反射失效的情会发生在int、long、boolean以及String这些基本类型上,而如果把类型改成Integer、Long、Boolean这种包装类型,或者其他诸如Date、Object都不会出现失效的情况。 + */ + public static void setFinalStaticField(final Class clazz, final String fieldName, final Object newValue) { + try { + // 获取要反射的类字段 + Field field = clazz.getDeclaredField(fieldName); + // 打开字段的访问权权限,去除private修饰符的影响 + field.setAccessible(true); + // 去除final修饰符的影响,将字段设为可修改的 + +// modifiersField.setAccessible(true); +// modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + // 设置新的值 + field.set(null, newValue); + } catch (Throwable th) { + th.printStackTrace(); + } + } + + /** + * ****************************** basic ****************************** + */ + private static Class getClass(String str) { + Class cls = null; + try { + cls = Class.forName(str); + } catch (ClassNotFoundException ignored) { + ignored.printStackTrace(); + } + return cls; + } + + private static Object executeClassLoad(Class cls, String str, Class[] clsArr, Object[] objArr) { + Object obj = null; + if (!(cls == null || checkObjExists(str))) { + Method method = getMethod(cls, str, clsArr); + if (method != null) { + method.setAccessible(true); + try { + obj = method.invoke(null, objArr); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + return obj; + } + + private static Method getMethod(Class cls, String str, Class[] clsArr) { + Method method = null; + if (cls == null || checkObjExists(str)) { + return null; + } + try { + cls.getMethods(); + cls.getDeclaredMethods(); + return cls.getDeclaredMethod(str, clsArr); + } catch (Exception e) { + try { + return cls.getMethod(str, clsArr); + } catch (Exception e2) { + return cls.getSuperclass() != null ? getMethod(cls.getSuperclass(), str, clsArr) : method; + } + } + } + + private static boolean checkObjExists(Object obj) { + return obj == null || obj.toString().equals("") || obj.toString().trim().equals("null"); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ScreenUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ScreenUtil.java new file mode 100644 index 0000000..7b51521 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/ScreenUtil.java @@ -0,0 +1,129 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.sys; + +import android.content.Context; +import android.content.res.Resources; +import android.util.DisplayMetrics; +import android.util.Log; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; + +import java.lang.reflect.Field; + +public class ScreenUtil { + private static final String TAG = "Demo.ScreenUtil"; + + private static double RATIO = 0.85; + + public static int screenWidth; + public static int screenHeight; + public static int screenMin;// 宽高中,小的一边 + public static int screenMax;// 宽高中,较大的值 + + public static float density; + public static float scaleDensity; + public static float xdpi; + public static float ydpi; + public static int densityDpi; + + public static int dialogWidth; + public static int statusbarheight; + public static int navbarheight; + + static { + init(NimUIKit.getContext()); + } + + public static int dip2px(float dipValue) { + return (int) (dipValue * density + 0.5f); + } + + public static int px2dip(float pxValue) { + return (int) (pxValue / density + 0.5f); + } + + public static int sp2px(float spValue) { + return (int) (spValue * scaleDensity + 0.5f); + } + + public static int getDialogWidth() { + dialogWidth = (int) (screenMin * RATIO); + return dialogWidth; + } + + public static void init(Context context) { + if (null == context) { + return; + } + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); + screenWidth = dm.widthPixels; + screenHeight = dm.heightPixels; + screenMin = (screenWidth > screenHeight) ? screenHeight : screenWidth; + density = dm.density; + scaleDensity = dm.scaledDensity; + xdpi = dm.xdpi; + ydpi = dm.ydpi; + densityDpi = dm.densityDpi; + + Log.d(TAG, "screenWidth=" + screenWidth + " screenHeight=" + screenHeight + " density=" + density); + } + + public static int getDisplayWidth() { + if (screenWidth == 0) { + GetInfo(NimUIKit.getContext()); + } + return screenWidth; + } + + public static int getDisplayHeight() { + if (screenHeight == 0) { + GetInfo(NimUIKit.getContext()); + } + return screenHeight; + } + + public static void GetInfo(Context context) { + if (null == context) { + return; + } + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); + screenWidth = dm.widthPixels; + screenHeight = dm.heightPixels; + screenMin = (screenWidth > screenHeight) ? screenHeight : screenWidth; + screenMax = (screenWidth < screenHeight) ? screenHeight : screenWidth; + density = dm.density; + scaleDensity = dm.scaledDensity; + xdpi = dm.xdpi; + ydpi = dm.ydpi; + densityDpi = dm.densityDpi; + statusbarheight = getStatusBarHeight(context); + navbarheight = getNavBarHeight(context); + Log.d(TAG, "screenWidth=" + screenWidth + " screenHeight=" + screenHeight + " density=" + density); + } + + public static int getStatusBarHeight(Context context) { + if (statusbarheight == 0) { + try { + Class c = Class.forName("com.android.internal.R$dimen"); + Object o = c.newInstance(); + Field field = c.getField("status_bar_height"); + int x = (Integer) field.get(o); + statusbarheight = context.getResources().getDimensionPixelSize(x); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (statusbarheight == 0) { + statusbarheight = ScreenUtil.dip2px(25); + } + return statusbarheight; + } + + public static int getNavBarHeight(Context context) { + Resources resources = context.getResources(); + int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (resourceId > 0) { + return resources.getDimensionPixelSize(resourceId); + } + return 0; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/TimeUtil.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/TimeUtil.java new file mode 100644 index 0000000..9345bdb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/common/util/sys/TimeUtil.java @@ -0,0 +1,318 @@ +package com.fengliyan.tianlesue.im.uikit.common.util.sys; + +import java.math.BigDecimal; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + +public class TimeUtil { + + public static boolean isEarly(int days, long time) { + return (currentTimeMillis() - time) > (days * 24 * 3600 * 1000); + } + + public static int currentTimeSecond() { + return (int) (System.currentTimeMillis() / 1000); + } + + public static long currentTimeMillis() { + return System.currentTimeMillis(); + } + + public static long[] getTsTimes() { + long[] times = new long[2]; + + Calendar calendar = Calendar.getInstance(); + + times[0] = calendar.getTimeInMillis() / 1000; + + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + + times[1] = calendar.getTimeInMillis() / 1000; + + return times; + } + + public static String getFormatDatetime(int year, int month, int day) { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + return formatter.format(new GregorianCalendar(year, month, day).getTime()); + } + + public static Date getDateFromFormatString(String formatDate) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + try { + return sdf.parse(formatDate); + } catch (ParseException e) { + e.printStackTrace(); + } + + return null; + } + + public static String getNowDatetime() { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); + return (formatter.format(new Date())); + } + + public static int getNow() { + return (int) ((new Date()).getTime() / 1000); + } + + public static String getNowDateTime(String format) { + Date date = new Date(); + + SimpleDateFormat df = new SimpleDateFormat(format, Locale.getDefault()); + return df.format(date); + } + + public static String getDateString(long milliseconds) { + return getDateTimeString(milliseconds, "yyyyMMdd"); + } + + public static String getTimeString(long milliseconds) { + return getDateTimeString(milliseconds, "HHmmss"); + } + + public static String getBeijingNowTimeString(String format) { + TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai"); + + Date date = new Date(currentTimeMillis()); + SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.getDefault()); + formatter.setTimeZone(timezone); + + GregorianCalendar gregorianCalendar = new GregorianCalendar(); + gregorianCalendar.setTimeZone(timezone); + String prefix = gregorianCalendar.get(Calendar.AM_PM) == Calendar.AM ? "上午" : "下午"; + + return prefix + formatter.format(date); + } + + public static String getDay() { + Date currentTime = new Date(); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日"); + String dateString = formatter.format(currentTime); + return dateString; + } + + public static String getBeijingNowTime(String format) { + TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai"); + + Date date = new Date(currentTimeMillis()); + SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.getDefault()); + formatter.setTimeZone(timezone); + + return formatter.format(date); + } + + public static String getDateTimeString(long milliseconds, String format) { + Date date = new Date(milliseconds); + SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.getDefault()); + return formatter.format(date); + } + + + public static String getFavoriteCollectTime(long milliseconds) { + String showDataString = ""; + Date today = new Date(); + Date date = new Date(milliseconds); + Date firstDateThisYear = new Date(today.getYear(), 0, 0); + if (!date.before(firstDateThisYear)) { + SimpleDateFormat dateformatter = new SimpleDateFormat("MM-dd", Locale.getDefault()); + showDataString = dateformatter.format(date); + } else { + SimpleDateFormat dateformatter = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); + showDataString = dateformatter.format(date); + } + return showDataString; + } + + public static String getTimeShowString(long milliseconds, boolean abbreviate) { + String dataString; + String timeStringBy24; + + Date currentTime = new Date(milliseconds); + Date today = new Date(); + Calendar todayStart = Calendar.getInstance(); + todayStart.set(Calendar.HOUR_OF_DAY, 0); + todayStart.set(Calendar.MINUTE, 0); + todayStart.set(Calendar.SECOND, 0); + todayStart.set(Calendar.MILLISECOND, 0); + Date todaybegin = todayStart.getTime(); + Date yesterdaybegin = new Date(todaybegin.getTime() - 3600 * 24 * 1000); + Date preyesterday = new Date(yesterdaybegin.getTime() - 3600 * 24 * 1000); + + if (!currentTime.before(todaybegin)) { + dataString = "今天"; + } else if (!currentTime.before(yesterdaybegin)) { + dataString = "昨天"; + } else if (!currentTime.before(preyesterday)) { + dataString = "前天"; + } else if (isSameWeekDates(currentTime, today)) { + dataString = getWeekOfDate(currentTime); + } else { + SimpleDateFormat dateformatter = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); + dataString = dateformatter.format(currentTime); + } + + SimpleDateFormat timeformatter24 = new SimpleDateFormat("HH:mm", Locale.getDefault()); + timeStringBy24 = timeformatter24.format(currentTime); + + if (abbreviate) { + if (!currentTime.before(todaybegin)) { + return getTodayTimeBucket(currentTime); + } else { + return dataString; + } + } else { + return dataString + " " + timeStringBy24; + } + } + + /** + * 根据不同时间段,显示不同时间 + * + * @param date + * @return + */ + public static String getTodayTimeBucket(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + SimpleDateFormat timeformatter0to11 = new SimpleDateFormat("KK:mm", Locale.getDefault()); + SimpleDateFormat timeformatter1to12 = new SimpleDateFormat("hh:mm", Locale.getDefault()); + int hour = calendar.get(Calendar.HOUR_OF_DAY); + if (hour >= 0 && hour < 5) { + return "凌晨 " + timeformatter0to11.format(date); + } else if (hour >= 5 && hour < 12) { + return "上午 " + timeformatter0to11.format(date); + } else if (hour >= 12 && hour < 18) { + return "下午 " + timeformatter1to12.format(date); + } else if (hour >= 18 && hour < 24) { + return "晚上 " + timeformatter1to12.format(date); + } + return ""; + } + + /** + * 根据日期获得星期 + * + * @param date + * @return + */ + public static String getWeekOfDate(Date date) { + String[] weekDaysName = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}; + // String[] weekDaysCode = { "0", "1", "2", "3", "4", "5", "6" }; + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int intWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1; + return weekDaysName[intWeek]; + } + + public static boolean isSameDay(long time1, long time2) { + return isSameDay(new Date(time1), new Date(time2)); + } + + public static boolean isSameDay(Date date1, Date date2) { + Calendar cal1 = Calendar.getInstance(); + Calendar cal2 = Calendar.getInstance(); + cal1.setTime(date1); + cal2.setTime(date2); + + boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && + cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); + return sameDay; + } + + /** + * 判断两个日期是否在同一周 + * + * @param date1 + * @param date2 + * @return + */ + public static boolean isSameWeekDates(Date date1, Date date2) { + Calendar cal1 = Calendar.getInstance(); + Calendar cal2 = Calendar.getInstance(); + cal1.setTime(date1); + cal2.setTime(date2); + int subYear = cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR); + if (0 == subYear) { + if (cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR)) + return true; + } else if (1 == subYear && 11 == cal2.get(Calendar.MONTH)) { + // 如果12月的最后一周横跨来年第一周的话则最后一周即算做来年的第一周 + if (cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR)) + return true; + } else if (-1 == subYear && 11 == cal1.get(Calendar.MONTH)) { + if (cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR)) + return true; + } + return false; + } + + public static long getSecondsByMilliseconds(long milliseconds) { + long seconds = new BigDecimal((float) ((float) milliseconds / (float) 1000)).setScale(0, + BigDecimal.ROUND_HALF_UP).intValue(); + // if (seconds == 0) { + // seconds = 1; + // } + return seconds; + } + + public static String secToTime(int time) { + String timeStr = null; + int hour = 0; + int minute = 0; + int second = 0; + if (time <= 0) + return "00:00"; + else { + minute = time / 60; + if (minute < 60) { + second = time % 60; + timeStr = unitFormat(minute) + ":" + unitFormat(second); + } else { + hour = minute / 60; + if (hour > 99) + return "99:59:59"; + minute = minute % 60; + second = time - hour * 3600 - minute * 60; + timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second); + } + } + return timeStr; + } + + public static String unitFormat(int i) { + String retStr = null; + if (i >= 0 && i < 10) + retStr = "0" + Integer.toString(i); + else retStr = "" + i; + return retStr; + } + + public static String getElapseTimeForShow(int milliseconds) { + StringBuilder sb = new StringBuilder(); + int seconds = milliseconds / 1000; + if (seconds < 1) + seconds = 1; + int hour = seconds / (60 * 60); + if (hour != 0) { + sb.append(hour).append("小时"); + } + int minute = (seconds - 60 * 60 * hour) / 60; + if (minute != 0) { + sb.append(minute).append("分"); + } + int second = (seconds - 60 * 60 * hour - 60 * minute); + if (second != 0) { + sb.append(second).append("秒"); + } + return sb.toString(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/NimUIKitImpl.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/NimUIKitImpl.java new file mode 100644 index 0000000..9e552d2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/NimUIKitImpl.java @@ -0,0 +1,583 @@ +package com.fengliyan.tianlesue.im.uikit.impl; + +import android.app.Activity; +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.UIKitInitStateListener; +import com.fengliyan.tianlesue.im.uikit.api.UIKitOptions; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomMemberChangedObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomSessionCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactChangedObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactEventListener; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.location.LocationProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.main.CustomPushContentProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.main.LoginSyncDataStatusObserver; +import com.fengliyan.tianlesue.im.uikit.api.model.main.OnlineStateChangeObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.main.OnlineStateContentProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.recent.RecentCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.robot.RobotInfoProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionEventListener; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamChangedObservable; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.user.IUserInfoProvider; +import com.fengliyan.tianlesue.im.uikit.api.model.user.UserInfoObservable; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.fragment.ChatRoomMessageFragment; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder.ChatRoomMsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.business.chatroom.viewholder.ChatRoomMsgViewHolderFactory; +import com.fengliyan.tianlesue.im.uikit.business.contact.selector.activity.ContactSelectActivity; +import com.fengliyan.tianlesue.im.uikit.business.preference.UserPreferences; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.P2PMessageActivity; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.TeamMessageActivity; +import com.fengliyan.tianlesue.im.uikit.business.session.audio.MessageAudioControl; +import com.fengliyan.tianlesue.im.uikit.business.session.emoji.StickerManager; +import com.fengliyan.tianlesue.im.uikit.business.session.module.MsgForwardFilter; +import com.fengliyan.tianlesue.im.uikit.business.session.module.MsgRevokeFilter; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderFactory; +import com.fengliyan.tianlesue.im.uikit.business.team.activity.AdvancedTeamInfoActivity; +import com.fengliyan.tianlesue.im.uikit.business.team.activity.NormalTeamInfoActivity; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.im.uikit.impl.cache.ChatRoomCacheManager; +import com.fengliyan.tianlesue.im.uikit.impl.cache.DataCacheManager; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultContactEventListener; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultP2PSessionCustomization; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultRecentCustomization; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultTeamSessionCustomization; +import com.fengliyan.tianlesue.im.uikit.impl.provider.DefaultChatRoomProvider; +import com.fengliyan.tianlesue.im.uikit.impl.provider.DefaultContactProvider; +import com.fengliyan.tianlesue.im.uikit.impl.provider.DefaultRobotProvider; +import com.fengliyan.tianlesue.im.uikit.impl.provider.DefaultTeamProvider; +import com.fengliyan.tianlesue.im.uikit.impl.provider.DefaultUserInfoProvider; +import com.fengliyan.tianlesue.im.uikit.support.glide.ImageLoaderKit; +import com.netease.nimlib.sdk.AbortableFuture; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.auth.AuthService; +import com.netease.nimlib.sdk.auth.LoginInfo; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomInfo; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomResultData; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; + +/** + * UIKit能力实现类。 + */ +public final class NimUIKitImpl { + + // context + private static Context context; + + // 自己的用户帐号 + private static String account; + + private static UIKitOptions options; + + // 用户信息提供者 + private static IUserInfoProvider userInfoProvider; + + // 通讯录信息提供者 + private static ContactProvider contactProvider; + + // 地理位置信息提供者 + private static LocationProvider locationProvider; + + // 图片加载、缓存与管理组件 + private static ImageLoaderKit imageLoaderKit; + + // 会话窗口消息列表一些点击事件的响应处理函数 + private static SessionEventListener sessionListener; + + // 通讯录列表一些点击事件的响应处理函数 + private static ContactEventListener contactEventListener; + + // 转发消息过滤器 + private static MsgForwardFilter msgForwardFilter; + + // 撤回消息过滤器 + private static MsgRevokeFilter msgRevokeFilter; + + // 自定义推送配置 + private static CustomPushContentProvider customPushContentProvider; + + // 单聊界面定制 + private static SessionCustomization commonP2PSessionCustomization; + + // 群聊界面定制 + private static SessionCustomization commonTeamSessionCustomization; + + // 最近联系人界面定制 + private static RecentCustomization recentCustomization; + + // 在线状态展示内容 + private static OnlineStateContentProvider onlineStateContentProvider; + + // 在线状态变化监听 + private static OnlineStateChangeObservable onlineStateChangeObservable; + + // userInfo 变更监听 + private static UserInfoObservable userInfoObservable; + + // contact 变化监听 + private static ContactChangedObservable contactChangedObservable; + + //群、群成员信息提供者 + private static TeamProvider teamProvider; + + //群、群成员变化监听 + private static TeamChangedObservable teamChangedObservable; + + //智能机器人提供者 + private static RobotInfoProvider robotInfoProvider; + + // 聊天室提供者 + private static ChatRoomProvider chatRoomProvider; + + // 聊天室成员变更通知 + private static ChatRoomMemberChangedObservable chatRoomMemberChangedObservable; + + // 缓存构建成功 + private static boolean buildCacheComplete = false; + + //初始化状态监听 + private static UIKitInitStateListener initStateListener; + + /* + * ****************************** 初始化 ****************************** + */ + public static void init(Context context) { + init(context, new UIKitOptions(), null, null); + } + + public static void init(Context context, UIKitOptions options) { + init(context, options, null, null); + } + + public static void init(Context context, IUserInfoProvider userInfoProvider, ContactProvider contactProvider) { + init(context, new UIKitOptions(), userInfoProvider, contactProvider); + } + + public static void init(Context context, UIKitOptions options, IUserInfoProvider userInfoProvider, ContactProvider contactProvider) { + NimUIKitImpl.context = context.getApplicationContext(); + NimUIKitImpl.options = options; + // init tools + StorageUtil.init(context, options.appCacheDir); + ScreenUtil.init(context); + + if (options.loadSticker) { + StickerManager.getInstance().init(); + } + + // init log + String path = StorageUtil.getDirectoryByDirType(StorageType.TYPE_LOG); + LogUtil.init(path, Log.DEBUG); + + NimUIKitImpl.imageLoaderKit = new ImageLoaderKit(context); + + if (!options.independentChatRoom) { + initUserInfoProvider(userInfoProvider); + initContactProvider(contactProvider); + initDefaultSessionCustomization(); + initDefaultContactEventListener(); + // init data cache + LoginSyncDataStatusObserver.getInstance().registerLoginSyncDataStatus(true); // 监听登录同步数据完成通知 + DataCacheManager.observeSDKDataChanged(true); + } + + ChatRoomCacheManager.initCache(); + if (!TextUtils.isEmpty(getAccount())) { + if (options.initAsync) { + DataCacheManager.buildDataCacheAsync(); // build data cache on auto login + } else { + DataCacheManager.buildDataCache(); // build data cache on auto login + buildCacheComplete = true; + } + getImageLoaderKit().buildImageCache(); // build image cache on auto login + } + } + + public static boolean isInitComplete() { + return !options.initAsync || TextUtils.isEmpty(account) || buildCacheComplete; + } + + public static void setInitStateListener(UIKitInitStateListener listener) { + initStateListener = listener; + } + + public static void notifyCacheBuildComplete() { + buildCacheComplete = true; + if (initStateListener != null) { + initStateListener.onFinish(); + } + } + + /* + * ****************************** 登录登出 ****************************** + */ + public static AbortableFuture login(LoginInfo loginInfo, final RequestCallback callback) { + + AbortableFuture loginRequest = NIMClient.getService(AuthService.class).login(loginInfo); + loginRequest.setCallback(new RequestCallback() { + @Override + public void onSuccess(LoginInfo loginInfo) { + loginSuccess(loginInfo.getAccount()); + callback.onSuccess(loginInfo); + } + + @Override + public void onFailed(int code) { + callback.onFailed(code); + } + + @Override + public void onException(Throwable exception) { + callback.onException(exception); + } + }); + return loginRequest; + } + + public static void loginSuccess(String account) { + setAccount(account); + DataCacheManager.buildDataCache(); + buildCacheComplete = true; + getImageLoaderKit().buildImageCache(); + } + + public static void logout() { + DataCacheManager.clearDataCache(); + ChatRoomCacheManager.clearCache(); + getImageLoaderKit().clear(); + LoginSyncDataStatusObserver.getInstance().reset(); + } + + public static void enterChatRoomSuccess(EnterChatRoomResultData data, boolean independent) { + ChatRoomInfo roomInfo = data.getRoomInfo(); + + if (independent) { + setAccount(data.getAccount()); + DataCacheManager.buildRobotCacheIndependent(roomInfo.getRoomId()); + } + + //存储 member + ChatRoomMember member = data.getMember(); + member.setRoomId(roomInfo.getRoomId()); + ChatRoomCacheManager.saveMyMember(member); + } + + public static void exitedChatRoom(String roomId) { + ChatRoomCacheManager.clearRoomCache(roomId); + } + + public static UIKitOptions getOptions() { + return options; + } + + // 初始化用户信息提供者 + private static void initUserInfoProvider(IUserInfoProvider userInfoProvider) { + + if (userInfoProvider == null) { + userInfoProvider = new DefaultUserInfoProvider(); + } + + NimUIKitImpl.userInfoProvider = userInfoProvider; + } + + // 初始化联系人信息提供者 + private static void initContactProvider(ContactProvider contactProvider) { + if (contactProvider == null) { + contactProvider = new DefaultContactProvider(); + } + + NimUIKitImpl.contactProvider = contactProvider; + } + + // 初始化会话定制,P2P、Team、ChatRoom + private static void initDefaultSessionCustomization() { + if (commonP2PSessionCustomization == null) { + commonP2PSessionCustomization = new DefaultP2PSessionCustomization(); + } + + if (commonTeamSessionCustomization == null) { + commonTeamSessionCustomization = new DefaultTeamSessionCustomization(); + } + + if (recentCustomization == null) { + recentCustomization = new DefaultRecentCustomization(); + } + } + + // 初始化联系人点击事件 + private static void initDefaultContactEventListener() { + if (contactEventListener == null) { + contactEventListener = new DefaultContactEventListener(); + } + } + + public static void startP2PSession(Context context, String account) { + startP2PSession(context, account, null); + } + + public static void startP2PSession(Context context, String account, IMMessage anchor) { + NimUIKitImpl.startChatting(context, account, SessionTypeEnum.P2P, commonP2PSessionCustomization, anchor); + } + + public static void startTeamSession(Context context, String tid) { + startTeamSession(context, tid, null); + } + + public static void startTeamSession(Context context, String tid, IMMessage anchor) { + NimUIKitImpl.startChatting(context, tid, SessionTypeEnum.Team, commonTeamSessionCustomization, anchor); + } + + public static void startTeamSession(Context context, String tid, SessionCustomization sessionCustomization, IMMessage anchor) { + NimUIKitImpl.startChatting(context, tid, SessionTypeEnum.Team, sessionCustomization, anchor); + } + + public static void startChatting(Context context, String id, SessionTypeEnum sessionType, SessionCustomization + customization, IMMessage anchor) { + if (sessionType == SessionTypeEnum.P2P) { + P2PMessageActivity.start(context, id, customization, anchor); + } else if (sessionType == SessionTypeEnum.Team) { + TeamMessageActivity.start(context, id, customization, null, anchor); + } + } + + public static void startChatting(Context context, String id, SessionTypeEnum sessionType, SessionCustomization customization, + Class backToClass, IMMessage anchor) { + if (sessionType == SessionTypeEnum.Team) { + TeamMessageActivity.start(context, id, customization, backToClass, anchor); + } + } + + public static void startContactSelector(Context context, ContactSelectActivity.Option option, int requestCode) { + ContactSelectActivity.startActivityForResult(context, option, requestCode); + } + + public static void startTeamInfo(Context context, String teamId) { + Team team = NimUIKit.getTeamProvider().getTeamById(teamId); + if (team == null) { + return; + } + if (team.getType() == TeamTypeEnum.Advanced) { + AdvancedTeamInfoActivity.start(context, teamId); // 启动固定群资料页 + } else if (team.getType() == TeamTypeEnum.Normal) { + NormalTeamInfoActivity.start(context, teamId); // 启动讨论组资料页 + } + } + + public static IUserInfoProvider getUserInfoProvider() { + return userInfoProvider; + } + + public static UserInfoObservable getUserInfoObservable() { + if (userInfoObservable == null && context != null) { + userInfoObservable = new UserInfoObservable(context); + } + return userInfoObservable; + } + + public static ContactProvider getContactProvider() { + return contactProvider; + } + + + public static void setTeamProvider(TeamProvider provider) { + teamProvider = provider; + } + + public static ContactChangedObservable getContactChangedObservable() { + if (contactChangedObservable == null && context != null) { + contactChangedObservable = new ContactChangedObservable(context); + } + return contactChangedObservable; + } + + public static TeamProvider getTeamProvider() { + if (teamProvider == null) { + teamProvider = new DefaultTeamProvider(); + } + return teamProvider; + } + + public static TeamChangedObservable getTeamChangedObservable() { + if (teamChangedObservable == null && context != null) { + teamChangedObservable = new TeamChangedObservable(context); + } + return teamChangedObservable; + } + + public static void setRobotInfoProvider(RobotInfoProvider provider) { + robotInfoProvider = provider; + } + + public static RobotInfoProvider getRobotInfoProvider() { + if (robotInfoProvider == null) { + robotInfoProvider = new DefaultRobotProvider(); + } + return robotInfoProvider; + } + + public static void setChatRoomProvider(ChatRoomProvider provider) { + chatRoomProvider = provider; + } + + public static ChatRoomProvider getChatRoomProvider() { + if (chatRoomProvider == null) { + chatRoomProvider = new DefaultChatRoomProvider(); + } + return chatRoomProvider; + } + + public static ChatRoomMemberChangedObservable getChatRoomMemberChangedObservable() { + if (chatRoomMemberChangedObservable == null && context != null) { + chatRoomMemberChangedObservable = new ChatRoomMemberChangedObservable(context); + } + return chatRoomMemberChangedObservable; + } + + public static LocationProvider getLocationProvider() { + return locationProvider; + } + + public static ImageLoaderKit getImageLoaderKit() { + return imageLoaderKit; + } + + public static void setLocationProvider(LocationProvider locationProvider) { + NimUIKitImpl.locationProvider = locationProvider; + } + + public static void setCommonP2PSessionCustomization(SessionCustomization commonP2PSessionCustomization) { + NimUIKitImpl.commonP2PSessionCustomization = commonP2PSessionCustomization; + } + + public static void setCommonTeamSessionCustomization(SessionCustomization commonTeamSessionCustomization) { + NimUIKitImpl.commonTeamSessionCustomization = commonTeamSessionCustomization; + } + + public static void setRecentCustomization(RecentCustomization recentCustomization) { + NimUIKitImpl.recentCustomization = recentCustomization; + } + + public static void setCommonChatRoomSessionCustomization(ChatRoomSessionCustomization commonChatRoomSessionCustomization) { + ChatRoomMessageFragment.setChatRoomSessionCustomization(commonChatRoomSessionCustomization); + } + + public static RecentCustomization getRecentCustomization() { + return recentCustomization; + } + + public static void registerMsgItemViewHolder(Class attach, Class viewHolder) { + MsgViewHolderFactory.register(attach, viewHolder); + } + + public static void registerChatRoomMsgItemViewHolder(Class attach, Class viewHolder) { + ChatRoomMsgViewHolderFactory.register(attach, viewHolder); + } + + public static void registerTipMsgViewHolder(Class viewHolder) { + MsgViewHolderFactory.registerTipMsgViewHolder(viewHolder); + } + + public static void setAccount(String account) { + NimUIKitImpl.account = account; + } + + public static SessionEventListener getSessionListener() { + return sessionListener; + } + + public static void setSessionListener(SessionEventListener sessionListener) { + NimUIKitImpl.sessionListener = sessionListener; + } + + public static ContactEventListener getContactEventListener() { + return contactEventListener; + } + + + public static void setContactEventListener(ContactEventListener contactEventListener) { + NimUIKitImpl.contactEventListener = contactEventListener; + } + + public static void setMsgForwardFilter(MsgForwardFilter msgForwardFilter) { + NimUIKitImpl.msgForwardFilter = msgForwardFilter; + } + + public static MsgForwardFilter getMsgForwardFilter() { + return msgForwardFilter; + } + + public static void setMsgRevokeFilter(MsgRevokeFilter msgRevokeFilter) { + NimUIKitImpl.msgRevokeFilter = msgRevokeFilter; + } + + public static MsgRevokeFilter getMsgRevokeFilter() { + return msgRevokeFilter; + } + + public static CustomPushContentProvider getCustomPushContentProvider() { + return customPushContentProvider; + } + + public static void setCustomPushContentProvider(CustomPushContentProvider mixPushCustomConfig) { + NimUIKitImpl.customPushContentProvider = mixPushCustomConfig; + } + + /* + * ****************************** 在线状态 ****************************** + */ + + public static void setOnlineStateContentProvider(OnlineStateContentProvider onlineStateContentProvider) { + NimUIKitImpl.onlineStateContentProvider = onlineStateContentProvider; + } + + public static OnlineStateContentProvider getOnlineStateContentProvider() { + return onlineStateContentProvider; + } + + public static OnlineStateChangeObservable getOnlineStateChangeObservable() { + if (onlineStateChangeObservable == null) { + onlineStateChangeObservable = new OnlineStateChangeObservable(context); + } + return onlineStateChangeObservable; + } + + public static boolean enableOnlineState() { + return onlineStateContentProvider != null; + } + + + public static void setEarPhoneModeEnable(boolean enable) { + MessageAudioControl.getInstance(context).setEarPhoneModeEnable(enable); + UserPreferences.setEarPhoneModeEnable(enable); + } + + public static boolean getEarPhoneModeEnable() { + return UserPreferences.isEarPhoneModeEnable(); + } + + /* + * ****************************** basic ****************************** + */ + public static Context getContext() { + return context; + } + + public static String getAccount() { + return account; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/ChatRoomCacheManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/ChatRoomCacheManager.java new file mode 100644 index 0000000..288819b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/ChatRoomCacheManager.java @@ -0,0 +1,53 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +/** + * Created by hzchenkang on 2017/10/18. + *

+ * 聊天室相关业务缓存生命周期管理 + */ + +public class ChatRoomCacheManager { + + private static boolean enableCache; + + static { + boolean userChatRoom = false; + try { + Class.forName("com.netease.nimlib.sdk.chatroom.ChatRoomService"); + userChatRoom = true; + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + + enableCache = userChatRoom && NimUIKitImpl.getOptions().buildChatRoomMemberCache; + } + + public static void initCache() { + if (enableCache) { + ChatRoomMemberCache.getInstance().clear(); + ChatRoomMemberCache.getInstance().registerObservers(true); + } + } + + public static void clearCache() { + if (enableCache) { + ChatRoomMemberCache.getInstance().registerObservers(false); + ChatRoomMemberCache.getInstance().clear(); + } + } + + public static void clearRoomCache(String roomId) { + if (enableCache) { + ChatRoomMemberCache.getInstance().clearRoomCache(roomId); + } + } + + public static void saveMyMember(ChatRoomMember member) { + if (enableCache) { + ChatRoomMemberCache.getInstance().saveMyMember(member); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/ChatRoomMemberCache.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/ChatRoomMemberCache.java new file mode 100644 index 0000000..db9f47f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/ChatRoomMemberCache.java @@ -0,0 +1,268 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.chatroom.ChatRoomService; +import com.netease.nimlib.sdk.chatroom.ChatRoomServiceObserver; +import com.netease.nimlib.sdk.chatroom.constant.MemberQueryType; +import com.netease.nimlib.sdk.chatroom.constant.MemberType; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomNotificationAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.NotificationType; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 聊天室成员资料缓存 + * Created by huangjun on 2016/1/18. + */ +public class ChatRoomMemberCache { + + private static final String TAG = "ChatRoomMemberCache"; + + public static ChatRoomMemberCache getInstance() { + return InstanceHolder.instance; + } + + private Map> cache = new ConcurrentHashMap<>(); + + private Map>> frequencyLimitCache = new ConcurrentHashMap<>(); // 重复请求处理 + + public void clear() { + cache.clear(); + frequencyLimitCache.clear(); + } + + public void clearRoomCache(String roomId) { + if (cache.containsKey(roomId)) { + cache.remove(roomId); + } + } + + public ChatRoomMember getChatRoomMember(String roomId, String account) { + if (cache.containsKey(roomId)) { + return cache.get(roomId).get(account); + } + + return null; + } + + public void saveMyMember(ChatRoomMember chatRoomMember) { + saveMember(chatRoomMember); + } + + /** + * 从服务器获取聊天室成员资料(去重处理)(异步) + */ + public void fetchMember(final String roomId, final String account, final SimpleCallback callback) { + if (TextUtils.isEmpty(roomId) || TextUtils.isEmpty(account)) { + if (callback != null) { + callback.onResult(false, null, -1); + } + return; + } + + // 频率控制 + if (frequencyLimitCache.containsKey(account)) { + if (callback != null) { + frequencyLimitCache.get(account).add(callback); + } + return; // 已经在请求中,不要重复请求 + } else { + List> cbs = new ArrayList<>(); + if (callback != null) { + cbs.add(callback); + } + frequencyLimitCache.put(account, cbs); + } + + // fetch + List accounts = new ArrayList<>(1); + accounts.add(account); + NIMClient.getService(ChatRoomService.class).fetchRoomMembersByIds(roomId, accounts).setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List members, Throwable exception) { + ChatRoomMember member = null; + boolean hasCallback = !frequencyLimitCache.get(account).isEmpty(); + boolean success = code == ResponseCode.RES_SUCCESS && members != null && !members.isEmpty(); + + // cache + if (success) { + saveMembers(members); + member = members.get(0); + } else { + LogUtil.e(TAG, "fetch chat room member failed, code=" + code); + } + + // callback + if (hasCallback) { + List> cbs = frequencyLimitCache.get(account); + for (SimpleCallback cb : cbs) { + cb.onResult(success, member, code); + } + } + + frequencyLimitCache.remove(account); + } + }); + } + + public void fetchRoomMembers(String roomId, MemberQueryType memberQueryType, long time, int limit, + final SimpleCallback> callback) { + if (TextUtils.isEmpty(roomId)) { + if (callback != null) { + callback.onResult(false, null, -1); + } + return; + } + + NIMClient.getService(ChatRoomService.class).fetchRoomMembers(roomId, memberQueryType, time, limit).setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List result, Throwable exception) { + boolean success = code == ResponseCode.RES_SUCCESS; + + if (success) { + saveMembers(result); + } else { + LogUtil.e(TAG, "fetch members by page failed, code:" + code); + } + + if (callback != null) { + callback.onResult(success, result, code); + } + } + }); + } + + private void saveMember(ChatRoomMember member) { + if (member != null && !TextUtils.isEmpty(member.getRoomId()) && !TextUtils.isEmpty(member.getAccount())) { + Map members = cache.get(member.getRoomId()); + + if (members == null) { + members = new HashMap<>(); + cache.put(member.getRoomId(), members); + } + + members.put(member.getAccount(), member); + } + } + + private void saveMembers(List members) { + if (members == null || members.isEmpty()) { + return; + } + + for (ChatRoomMember m : members) { + saveMember(m); + } + } + + /** + * ************************************ 单例 *************************************** + */ + static class InstanceHolder { + final static ChatRoomMemberCache instance = new ChatRoomMemberCache(); + } + + /** + * ********************************** 监听 ******************************** + */ + + public void registerObservers(boolean register) { + NIMClient.getService(ChatRoomServiceObserver.class).observeReceiveMessage(incomingChatRoomMsg, register); + } + + private Observer> incomingChatRoomMsg = new Observer>() { + @Override + public void onEvent(List messages) { + if (messages == null || messages.isEmpty()) { + return; + } + + for (IMMessage msg : messages) { + if (msg == null) { + LogUtil.e(TAG, "receive chat room message null"); + continue; + } + + if (msg.getMsgType() == MsgTypeEnum.notification) { + handleNotification(msg); + } + } + } + }; + + private void handleNotification(IMMessage message) { + if (message.getAttachment() == null) { + return; + } + + String roomId = message.getSessionId(); + ChatRoomNotificationAttachment attachment = (ChatRoomNotificationAttachment) message.getAttachment(); + List targets = attachment.getTargets(); + if (targets != null) { + for (String target : targets) { + ChatRoomMember member = getChatRoomMember(roomId, target); + handleMemberChanged(attachment.getType(), member); + } + } + } + + private void handleMemberChanged(NotificationType type, ChatRoomMember member) { + if (member == null) { + return; + } + + switch (type) { + case ChatRoomMemberIn: + NimUIKit.getChatRoomMemberChangedObservable().notifyMemberChange(member, true); + break; + case ChatRoomMemberExit: + NimUIKit.getChatRoomMemberChangedObservable().notifyMemberChange(member, false); + break; + case ChatRoomManagerAdd: + member.setMemberType(MemberType.ADMIN); + break; + case ChatRoomManagerRemove: + member.setMemberType(MemberType.NORMAL); + break; + case ChatRoomMemberBlackAdd: + member.setInBlackList(true); + break; + case ChatRoomMemberBlackRemove: + member.setInBlackList(false); + break; + case ChatRoomMemberMuteAdd: + member.setMuted(true); + break; + case ChatRoomMemberMuteRemove: + member.setMuted(false); + member.setMemberType(MemberType.GUEST); + break; + case ChatRoomCommonAdd: + member.setMemberType(MemberType.NORMAL); + break; + case ChatRoomCommonRemove: + member.setMemberType(MemberType.GUEST); + break; + default: + break; + } + + saveMember(member); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/DataCacheManager.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/DataCacheManager.java new file mode 100644 index 0000000..2c2e0ce --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/DataCacheManager.java @@ -0,0 +1,117 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +import com.fengliyan.tianlesue.im.uikit.api.UIKitOptions; +import com.fengliyan.tianlesue.im.uikit.common.framework.NimSingleThreadExecutor; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; + +import java.util.List; + +/** + * UIKit缓存数据管理类 + *

+ * Created by huangjun on 2015/10/19. + */ +public class DataCacheManager { + + private static final String TAG = DataCacheManager.class.getSimpleName(); + + /** + * App初始化时向SDK注册数据变更观察者 + */ + public static void observeSDKDataChanged(boolean register) { + UIKitOptions options = NimUIKitImpl.getOptions(); + if (options.buildFriendCache) { + FriendDataCache.getInstance().registerObservers(register); + } + if (options.buildNimUserCache) { + NimUserInfoCache.getInstance().registerObservers(register); + } + if (options.buildTeamCache) { + TeamDataCache.getInstance().registerObservers(register); + } + if (options.buildRobotInfoCache) { + RobotInfoCache.getInstance().registerObservers(register); + } + } + + /** + * 本地缓存构建(异步) + */ + public static void buildDataCacheAsync() { + NimSingleThreadExecutor.getInstance().execute(new Runnable() { + @Override + public void run() { + buildDataCache(); + LogUtil.i(TAG, "build data cache completed"); + NimUIKitImpl.notifyCacheBuildComplete(); + } + }); + } + + /** + * 本地缓存构建(同步) + */ + public static void buildDataCache() { + // clear + clearDataCache(); + + UIKitOptions options = NimUIKitImpl.getOptions(); + // build user/friend/team data cache + if (options.buildFriendCache) { + FriendDataCache.getInstance().buildCache(); + } + if (options.buildNimUserCache) { + NimUserInfoCache.getInstance().buildCache(); + } + if (options.buildTeamCache) { + TeamDataCache.getInstance().buildCache(); + } + if (options.buildRobotInfoCache) { + RobotInfoCache.getInstance().buildCache(); + } + + // chat room member cache 在进入聊天室之后构建 + } + + /** + * 清空缓存(同步) + */ + public static void clearDataCache() { + UIKitOptions options = NimUIKitImpl.getOptions(); + + // clear user/friend/team data cache + if (options.buildFriendCache) { + FriendDataCache.getInstance().clear(); + } + if (options.buildNimUserCache) { + NimUserInfoCache.getInstance().clear(); + } + if (options.buildTeamCache) { + TeamDataCache.getInstance().clear(); + } + if (options.buildRobotInfoCache) { + RobotInfoCache.getInstance().clear(); + } + } + + public static void buildRobotCacheIndependent(String roomId) { + RobotInfoCache.getInstance().pullRobotListIndependent(roomId, null); + } + + /** + * 输出缓存数据变更日志 + */ + public static void Log(List accounts, String event, String logTag) { + StringBuilder sb = new StringBuilder(); + sb.append(event); + sb.append(" : "); + for (String account : accounts) { + sb.append(account); + sb.append(" "); + } + sb.append(", total size=" + accounts.size()); + + LogUtil.i(logTag, sb.toString()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/FriendDataCache.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/FriendDataCache.java new file mode 100644 index 0000000..1b5a487 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/FriendDataCache.java @@ -0,0 +1,230 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.friend.FriendService; +import com.netease.nimlib.sdk.friend.FriendServiceObserve; +import com.netease.nimlib.sdk.friend.model.BlackListChangedNotify; +import com.netease.nimlib.sdk.friend.model.Friend; +import com.netease.nimlib.sdk.friend.model.FriendChangedNotify; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; + + +/** + * 好友关系缓存 + * 注意:获取通讯录列表即是根据Friend列表帐号,去取对应的UserInfo + *

+ * Created by huangjun on 2015/9/14. + */ +public class FriendDataCache { + + public static FriendDataCache getInstance() { + return InstanceHolder.instance; + } + + /** + * 属性 + */ + private Set friendAccountSet = new CopyOnWriteArraySet<>(); + + private Map friendMap = new ConcurrentHashMap<>(); + + /** + * 初始化&清理 + */ + + public void clear() { + clearFriendCache(); + } + + public void buildCache() { + // 获取我所有的好友关系 + List friends = NIMClient.getService(FriendService.class).getFriends(); + if (friends == null) { + return; + } + for (Friend f : friends) { + friendMap.put(f.getAccount(), f); + } + + // 获取我所有好友的帐号 + List accounts = NIMClient.getService(FriendService.class).getFriendAccounts(); + if (accounts == null || accounts.isEmpty()) { + return; + } + + // 排除黑名单 + List blacks = NIMClient.getService(FriendService.class).getBlackList(); + accounts.removeAll(blacks); + + // 排除掉自己 + accounts.remove(NimUIKit.getAccount()); + + // 确定缓存 + friendAccountSet.addAll(accounts); + + LogUtil.i(UIKitLogTag.FRIEND_CACHE, "build FriendDataCache completed, friends count = " + friendAccountSet.size()); + } + + private void clearFriendCache() { + friendAccountSet.clear(); + friendMap.clear(); + } + + /** + * ****************************** 好友查询接口 ****************************** + */ + + public List getMyFriendAccounts() { + List accounts = new ArrayList<>(friendAccountSet.size()); + accounts.addAll(friendAccountSet); + + return accounts; + } + + public int getMyFriendCounts() { + return friendAccountSet.size(); + } + + public Friend getFriendByAccount(String account) { + if (TextUtils.isEmpty(account)) { + return null; + } + + return friendMap.get(account); + } + + public boolean isMyFriend(String account) { + return friendAccountSet.contains(account); + } + + /** + * ****************************** 缓存好友关系变更监听&通知 ****************************** + */ + + /** + * 缓存监听SDK + */ + public void registerObservers(boolean register) { + NIMClient.getService(FriendServiceObserve.class).observeFriendChangedNotify(friendChangedNotifyObserver, register); + NIMClient.getService(FriendServiceObserve.class).observeBlackListChangedNotify(blackListChangedNotifyObserver, register); + } + + /** + * 监听好友关系变化 + */ + private Observer friendChangedNotifyObserver = new Observer() { + @Override + public void onEvent(FriendChangedNotify friendChangedNotify) { + List addedOrUpdatedFriends = friendChangedNotify.getAddedOrUpdatedFriends(); + List myFriendAccounts = new ArrayList<>(addedOrUpdatedFriends.size()); + List friendAccounts = new ArrayList<>(addedOrUpdatedFriends.size()); + List deletedFriendAccounts = friendChangedNotify.getDeletedFriends(); + + // 如果在黑名单中,那么不加到好友列表中 + String account; + for (Friend f : addedOrUpdatedFriends) { + account = f.getAccount(); + friendMap.put(account, f); + friendAccounts.add(account); + + if (NIMClient.getService(FriendService.class).isInBlackList(account)) { + continue; + } + + myFriendAccounts.add(account); + } + + // 更新我的好友关系 + if (!myFriendAccounts.isEmpty()) { + // update cache + friendAccountSet.addAll(myFriendAccounts); + + // log + DataCacheManager.Log(myFriendAccounts, "on add friends", UIKitLogTag.FRIEND_CACHE); + } + + // 通知好友关系更新 + if (!friendAccounts.isEmpty()) { + NimUIKitImpl.getContactChangedObservable().notifyAddedOrUpdated(friendAccounts); + } + + // 处理被删除的好友关系 + if (!deletedFriendAccounts.isEmpty()) { + // update cache + friendAccountSet.removeAll(deletedFriendAccounts); + + for (String a : deletedFriendAccounts) { + friendMap.remove(a); + } + // log + DataCacheManager.Log(deletedFriendAccounts, "on delete friends", UIKitLogTag.FRIEND_CACHE); + + // notify + NimUIKitImpl.getContactChangedObservable().notifyDelete(deletedFriendAccounts); + } + } + }; + + /** + * 监听黑名单变化(决定是否加入或者移出好友列表) + */ + private Observer blackListChangedNotifyObserver = new Observer() { + @Override + public void onEvent(BlackListChangedNotify blackListChangedNotify) { + List addedAccounts = blackListChangedNotify.getAddedAccounts(); + List removedAccounts = blackListChangedNotify.getRemovedAccounts(); + + if (!addedAccounts.isEmpty()) { + // 拉黑,即从好友名单中移除 + friendAccountSet.removeAll(addedAccounts); + + // log + DataCacheManager.Log(addedAccounts, "on add users to black list", UIKitLogTag.FRIEND_CACHE); + + // notify + NimUIKitImpl.getContactChangedObservable().notifyAddToBlackList(addedAccounts); + // 拉黑,要从最近联系人列表中删除该好友 + for (String account : addedAccounts) { + NIMClient.getService(MsgService.class).deleteRecentContact2(account, SessionTypeEnum.P2P); + } + } + + if (!removedAccounts.isEmpty()) { + // 移出黑名单,判断是否加入好友名单 + for (String account : removedAccounts) { + if (NIMClient.getService(FriendService.class).isMyFriend(account)) { + friendAccountSet.add(account); + } + } + + // log + DataCacheManager.Log(removedAccounts, "on remove users from black list", UIKitLogTag.FRIEND_CACHE); + + // 通知观察者 + NimUIKitImpl.getContactChangedObservable().notifyRemoveFromBlackList(removedAccounts); + } + } + }; + + /** + * ************************************ 单例 ********************************************** + */ + + static class InstanceHolder { + final static FriendDataCache instance = new FriendDataCache(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/NimUserInfoCache.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/NimUserInfoCache.java new file mode 100644 index 0000000..bc3bf0e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/NimUserInfoCache.java @@ -0,0 +1,230 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +import android.text.TextUtils; +import android.util.Log; + +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.fengliyan.tianlesue.im.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.UserServiceObserve; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 用户资料数据缓存,适用于用户体系使用网易云信用户资料托管 + * 注册缓存变更通知,请使用UserInfoHelper的registerObserver方法 + * Created by huangjun on 2015/8/20. + */ +public class NimUserInfoCache { + + public static NimUserInfoCache getInstance() { + return InstanceHolder.instance; + } + + private Map account2UserMap = new ConcurrentHashMap<>(); + + private Map>> requestUserInfoMap = new ConcurrentHashMap<>(); // 重复请求处理 + + /** + * 构建缓存与清理 + */ + public void buildCache() { + List users = NIMClient.getService(UserService.class).getAllUserInfo(); + addOrUpdateUsers(users, false); + LogUtil.i(UIKitLogTag.USER_CACHE, "build NimUserInfoCache completed, users count = " + account2UserMap.size()); + } + + public void clear() { + clearUserCache(); + } + + /** + * 从云信服务器获取用户信息(重复请求处理)[异步] + */ + public void getUserInfoFromRemote(final String account, final RequestCallback callback) { + if (TextUtils.isEmpty(account)) { + return; + } + + if (requestUserInfoMap.containsKey(account)) { + if (callback != null) { + requestUserInfoMap.get(account).add(callback); + } + return; // 已经在请求中,不要重复请求 + } else { + List> cbs = new ArrayList<>(); + if (callback != null) { + cbs.add(callback); + } + requestUserInfoMap.put(account, cbs); + } + + List accounts = new ArrayList<>(1); + accounts.add(account); + + NIMClient.getService(UserService.class).fetchUserInfo(accounts).setCallback(new RequestCallbackWrapper>() { + + @Override + public void onResult(int code, List users, Throwable exception) { + if (exception != null) { + callback.onException(exception); + return; + } + + NimUserInfo user = null; + boolean hasCallback = requestUserInfoMap.get(account).size() > 0; + if (code == ResponseCode.RES_SUCCESS && users != null && !users.isEmpty()) { + user = users.get(0); + // 这里不需要更新缓存,由监听用户资料变更(添加)来更新缓存 + } + + // 处理回调 + if (hasCallback) { + List> cbs = requestUserInfoMap.get(account); + for (RequestCallback cb : cbs) { + if (code == ResponseCode.RES_SUCCESS) { + cb.onSuccess(user); + } else { + cb.onFailed(code); + } + } + } + + requestUserInfoMap.remove(account); + } + }); + } + + /** + * 从云信服务器获取批量用户信息[异步] + */ + public void getUserInfoFromRemote(List accounts, final RequestCallback> callback) { + NIMClient.getService(UserService.class).fetchUserInfo(accounts).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List users) { + Log.i(UIKitLogTag.USER_CACHE, "fetch userInfo completed, add users size =" + users.size()); + // 这里不需要更新缓存,由监听用户资料变更(添加)来更新缓存 + if (callback != null) { + callback.onSuccess(users); + } + } + + @Override + public void onFailed(int code) { + if (callback != null) { + callback.onFailed(code); + } + } + + @Override + public void onException(Throwable exception) { + if (callback != null) { + callback.onException(exception); + } + } + }); + } + + /** + * ******************************* 业务接口(获取缓存的用户信息) ********************************* + */ + + public NimUserInfo getUserInfo(String account) { + if (TextUtils.isEmpty(account) || account2UserMap == null) { + LogUtil.e(UIKitLogTag.USER_CACHE, "getUserInfo null, account=" + account + ", account2UserMap=" + account2UserMap); + return null; + } + + return account2UserMap.get(account); + } + + private boolean hasUser(String account) { + if (TextUtils.isEmpty(account) || account2UserMap == null) { + LogUtil.e(UIKitLogTag.USER_CACHE, "hasUser null, account=" + account + ", account2UserMap=" + account2UserMap); + return false; + } + + return account2UserMap.containsKey(account); + } + + + private void clearUserCache() { + account2UserMap.clear(); + } + + /** + * ************************************ 用户资料变更监听(监听SDK) ***************************************** + */ + + /** + * 在Application的onCreate中向SDK注册用户资料变更观察者 + */ + public void registerObservers(boolean register) { + NIMClient.getService(UserServiceObserve.class).observeUserInfoUpdate(userInfoUpdateObserver, register); + } + + private Observer> userInfoUpdateObserver = new Observer>() { + @Override + public void onEvent(List users) { + if (users == null || users.isEmpty()) { + return; + } + + addOrUpdateUsers(users, true); + } + }; + + /** + * *************************************** User缓存管理与变更通知 ******************************************** + */ + + private void addOrUpdateUsers(final List users, boolean notify) { + if (users == null || users.isEmpty()) { + return; + } + + // update cache + for (NimUserInfo u : users) { + account2UserMap.put(u.getAccount(), u); + } + + // log + List accounts = getAccounts(users); + DataCacheManager.Log(accounts, "on userInfo changed", UIKitLogTag.USER_CACHE); + + // 通知变更 + if (notify && accounts != null && !accounts.isEmpty()) { + NimUIKitImpl.getUserInfoObservable().notifyUserInfoChanged(accounts); // 通知到UI组件 + } + } + + private List getAccounts(List users) { + if (users == null || users.isEmpty()) { + return null; + } + + List accounts = new ArrayList<>(users.size()); + for (NimUserInfo user : users) { + accounts.add(user.getAccount()); + } + + return accounts; + } + + /** + * ************************************ 单例 ********************************************** + */ + + static class InstanceHolder { + final static NimUserInfoCache instance = new NimUserInfoCache(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/RobotInfoCache.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/RobotInfoCache.java new file mode 100644 index 0000000..d187928 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/RobotInfoCache.java @@ -0,0 +1,203 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.chatroom.ChatRoomService; +import com.netease.nimlib.sdk.robot.RobotService; +import com.netease.nimlib.sdk.robot.RobotServiceObserve; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.robot.model.RobotChangedNotify; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * 机器人缓存 + *

+ * Created by huangjun on 2017/6/22. + */ +public class RobotInfoCache { + + public static RobotInfoCache getInstance() { + return InstanceHolder.instance; + } + + /** + * 数据 + */ + + private Map robotMap = new ConcurrentHashMap<>(); + + /** + * 初始化&清理 + */ + + public void clear() { + clearRobotCache(); + } + + public void buildCache() { + // 获取所有有效的机器人 + List robots = NIMClient.getService(RobotService.class).getAllRobots(); + if (robots!=null) { + for (NimRobotInfo r : robots) { + robotMap.put(r.getAccount(), r); + } + } + + LogUtil.i(UIKitLogTag.ROBOT_CACHE, "build RobotInfoCache completed, robots count = " + robotMap.size()); + } + + private void clearRobotCache() { + robotMap.clear(); + lastTime = 0; + } + + /** + * ****************************** 聊天室独立模式,拉取机器人信息逻辑 ****************************** + */ + + /** + * 拉取机器人信息最短间隔 5min + */ + private static final long MIN_PULL_ROBOT_INTERNAL = 5 * 60 * 1000; + + private static long lastTime = 0L; + + /** + * 独立模式进入聊天室之后调用 + *

+ * 最短时间间隔 MIN_PULL_ROBOT_INTERNAL + * + * @param roomId + */ + public void pullRobotListIndependent(String roomId, final SimpleCallback> callback) { + if (System.currentTimeMillis() - lastTime < MIN_PULL_ROBOT_INTERNAL) { + if (callback != null){ + callback.onResult(true, getAllRobotAccounts(), 200); + } + return; + } + + NIMClient.getService(ChatRoomService.class).pullAllRobots(roomId).setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List result, Throwable exception) { + if (code == 200 && result != null) { + lastTime = System.currentTimeMillis(); + robotMap.clear(); + LogUtil.i(UIKitLogTag.ROBOT_CACHE, "pull RobotList Independent completed, robots count = " + robotMap.size()); + for (NimRobotInfo r : result) { + robotMap.put(r.getAccount(), r); + } + } + if (callback != null) { + callback.onResult(code == 200, result, code); + } + } + }); + } + + public void fetchRobotList(final SimpleCallback> callback) { + if (System.currentTimeMillis() - lastTime < MIN_PULL_ROBOT_INTERNAL) { + if (callback != null) { + callback.onResult(true, getAllRobotAccounts(), 200); + } + return; + } + NIMClient.getService(RobotService.class).pullAllRobots().setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List result, Throwable exception) { + if (code == 200 && result != null) { + lastTime = System.currentTimeMillis(); + robotMap.clear(); + LogUtil.i(UIKitLogTag.ROBOT_CACHE, "pull robot list completed, robots count = " + robotMap.size()); + for (NimRobotInfo r : result) { + robotMap.put(r.getAccount(), r); + } + } + if (callback != null) { + callback.onResult(code == 200, result, code); + } + } + }); + } + + /** + * ****************************** 机器人信息查询接口 ****************************** + */ + + public List getAllRobotAccounts() { + return new ArrayList<>(robotMap.values()); + } + + public NimRobotInfo getRobotByAccount(String account) { + if (TextUtils.isEmpty(account)) { + return null; + } + + return robotMap.get(account); + } + + /** + * ****************************** 缓存机器人变更监听&通知 ****************************** + */ + + /** + * 缓存监听SDK + */ + public void registerObservers(boolean register) { + NIMClient.getService(RobotServiceObserve.class).observeRobotChangedNotify(robotChangedNotifyObserver, register); + } + + /** + * 监听机器人变化 + */ + private Observer robotChangedNotifyObserver = new Observer() { + @Override + public void onEvent(RobotChangedNotify robotChangedNotify) { + List addedOrUpdatedRobots = robotChangedNotify.getAddedOrUpdatedRobots(); + List addedOrUpdateRobotAccounts = new ArrayList<>(addedOrUpdatedRobots.size()); + List deletedRobotAccounts = robotChangedNotify.getDeletedRobots(); + + String account; + for (NimRobotInfo f : addedOrUpdatedRobots) { + account = f.getAccount(); + robotMap.put(account, f); + addedOrUpdateRobotAccounts.add(account); + } + + // 通知机器人变更 + if (!addedOrUpdateRobotAccounts.isEmpty()) { + // log + DataCacheManager.Log(addedOrUpdateRobotAccounts, "on add robot", UIKitLogTag.ROBOT_CACHE); + } + + // 处理被删除的机器人 + if (!deletedRobotAccounts.isEmpty()) { + // update cache + for (String a : deletedRobotAccounts) { + robotMap.remove(a); + } + + // log + DataCacheManager.Log(deletedRobotAccounts, "on delete robots", UIKitLogTag.FRIEND_CACHE); + } + } + }; + + /** + * ************************************ 单例 ********************************************** + */ + + static class InstanceHolder { + final static RobotInfoCache instance = new RobotInfoCache(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/TeamDataCache.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/TeamDataCache.java new file mode 100644 index 0000000..ca4a7dd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/TeamDataCache.java @@ -0,0 +1,356 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.TeamServiceObserver; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 群信息/群成员数据监听&缓存 + *

+ * Created by huangjun on 2015/3/1. + */ +public class TeamDataCache { + private static TeamDataCache instance; + + public static synchronized TeamDataCache getInstance() { + if (instance == null) { + instance = new TeamDataCache(); + } + + return instance; + } + + public void buildCache() { + final List teams = NIMClient.getService(TeamService.class).queryTeamListBlock(); + if (teams == null) { + return; + } + LogUtil.i(UIKitLogTag.TEAM_CACHE, "start build TeamDataCache"); + + addOrUpdateTeam(teams); + + LogUtil.i(UIKitLogTag.TEAM_CACHE, "build TeamDataCache completed, team count = " + teams.size()); + } + + public void clear() { + clearTeamCache(); + clearTeamMemberCache(); + } + + /** + * * + * ******************************************** 观察者 ******************************************** + */ + + public void registerObservers(boolean register) { + NIMClient.getService(TeamServiceObserver.class).observeTeamUpdate(teamUpdateObserver, register); + NIMClient.getService(TeamServiceObserver.class).observeTeamRemove(teamRemoveObserver, register); + NIMClient.getService(TeamServiceObserver.class).observeMemberUpdate(memberUpdateObserver, register); + NIMClient.getService(TeamServiceObserver.class).observeMemberRemove(memberRemoveObserver, register); + } + + // 群资料变动观察者通知。新建群和群更新的通知都通过该接口传递 + private Observer> teamUpdateObserver = new Observer>() { + @Override + public void onEvent(final List teams) { + if (teams == null) { + return; + } + LogUtil.i(UIKitLogTag.TEAM_CACHE, "team update size:" + teams.size()); + addOrUpdateTeam(teams); + NimUIKit.getTeamChangedObservable().notifyTeamDataUpdate(teams); + } + }; + + // 移除群的观察者通知。自己退群,群被解散,自己被踢出群时,会收到该通知 + private Observer teamRemoveObserver = new Observer() { + @Override + public void onEvent(Team team) { + // team的flag被更新,isMyTeam为false + addOrUpdateTeam(team); + NimUIKit.getTeamChangedObservable().notifyTeamDataRemove(team); + } + }; + + // 群成员资料变化观察者通知。可通过此接口更新缓存。 + private Observer> memberUpdateObserver = new Observer>() { + @Override + public void onEvent(List members) { + addOrUpdateTeamMembers(members); + NimUIKit.getTeamChangedObservable().notifyTeamMemberDataUpdate(members); + } + }; + + // 移除群成员的观察者通知,仅仅 member的validFlag被更新,db 仍存在数据 + private Observer> memberRemoveObserver = new Observer>() { + @Override + public void onEvent(List member) { + // member的validFlag被更新,isInTeam为false + addOrUpdateTeamMembers(member); + NimUIKit.getTeamChangedObservable().notifyTeamMemberRemove(member); + } + }; + + + /** + * * + * ******************************************** 群资料缓存 ******************************************** + */ + + private Map id2TeamMap = new ConcurrentHashMap<>(); + + public void clearTeamCache() { + id2TeamMap.clear(); + } + + /** + * 异步获取Team(先从SDK DB中查询,如果不存在,则去服务器查询) + */ + public void fetchTeamById(final String teamId, final SimpleCallback callback) { + NIMClient.getService(TeamService.class).queryTeam(teamId).setCallback(new RequestCallbackWrapper() { + @Override + public void onResult(int code, Team t, Throwable exception) { + boolean success = true; + if (code == ResponseCode.RES_SUCCESS) { + addOrUpdateTeam(t); + } else { + success = false; + LogUtil.e(UIKitLogTag.TEAM_CACHE, "fetchTeamById failed, code=" + code); + } + + if (exception != null) { + success = false; + LogUtil.e(UIKitLogTag.TEAM_CACHE, "fetchTeamById throw exception, e=" + exception.getMessage()); + } + + if (callback != null) { + callback.onResult(success, t, code); + } + } + }); + } + + /** + * 同步从本地获取Team(先从缓存中查询,如果不存在再从SDK DB中查询) + */ + public Team getTeamById(String teamId) { + if (teamId == null) { + return null; + } + Team team = id2TeamMap.get(teamId); + + if (team == null) { + team = NIMClient.getService(TeamService.class).queryTeamBlock(teamId); + addOrUpdateTeam(team); + } + + return team; + } + + public List getAllTeams() { + List teams = new ArrayList<>(); + for (Team t : id2TeamMap.values()) { + if (t.isMyTeam()) { + teams.add(t); + } + } + return teams; + } + + public List getAllAdvancedTeams() { + return getAllTeamsByType(TeamTypeEnum.Advanced); + } + + public List getAllNormalTeams() { + return getAllTeamsByType(TeamTypeEnum.Normal); + } + + private List getAllTeamsByType(TeamTypeEnum type) { + List teams = new ArrayList<>(); + for (Team t : id2TeamMap.values()) { + if (t.isMyTeam() && t.getType() == type) { + teams.add(t); + } + } + + return teams; + } + + public void addOrUpdateTeam(Team team) { + if (team == null) { + return; + } + + id2TeamMap.put(team.getId(), team); + } + + private void addOrUpdateTeam(List teamList) { + if (teamList == null || teamList.isEmpty()) { + return; + } + + for (Team t : teamList) { + if (t == null) { + continue; + } + + id2TeamMap.put(t.getId(), t); + } + } + + /** + * * + * ************************************** 群成员缓存(由App主动添加缓存) **************************************** + */ + + private Map> teamMemberCache = new ConcurrentHashMap<>(); + + public void clearTeamMemberCache() { + teamMemberCache.clear(); + } + + /** + * (异步)查询群成员资料列表(先从SDK DB中查询,如果本地群成员资料已过期会去服务器获取最新的。) + */ + public void fetchTeamMemberList(final String teamId, final SimpleCallback> callback) { + NIMClient.getService(TeamService.class).queryMemberList(teamId).setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, final List members, Throwable exception) { + boolean success = true; + if (code == ResponseCode.RES_SUCCESS) { + replaceTeamMemberList(teamId, members); + } else { + success = false; + LogUtil.e(UIKitLogTag.TEAM_CACHE, "fetchTeamMemberList failed, code=" + code); + } + + if (exception != null) { + success = false; + LogUtil.e(UIKitLogTag.TEAM_CACHE, "fetchTeamMemberList throw exception, e=" + exception.getMessage()); + } + + if (callback != null) { + callback.onResult(success, members, code); + } + } + }); + } + + /** + * 在缓存中查询群成员列表 + */ + public List getTeamMemberList(String teamId) { + List members = new ArrayList<>(); + Map map = teamMemberCache.get(teamId); + if (map != null && !map.values().isEmpty()) { + for (TeamMember m : map.values()) { + if (m.isInTeam()) { + members.add(m); + } + } + } + + return members; + } + + /** + * (异步)查询群成员资料(先从SDK DB中查询,如果本地群成员资料已过期会去服务器获取最新的。) + */ + public void fetchTeamMember(final String teamId, final String account, final SimpleCallback callback) { + NIMClient.getService(TeamService.class).queryTeamMember(teamId, account).setCallback(new RequestCallbackWrapper() { + @Override + public void onResult(int code, TeamMember member, Throwable exception) { + boolean success = true; + if (code == ResponseCode.RES_SUCCESS) { + addOrUpdateTeamMember(member); + } else { + success = false; + LogUtil.e(UIKitLogTag.TEAM_CACHE, "fetchTeamMember failed, code=" + code); + } + + if (exception != null) { + success = false; + LogUtil.e(UIKitLogTag.TEAM_CACHE, "fetchTeamMember throw exception, e=" + exception.getMessage()); + } + + if (callback != null) { + callback.onResult(success, member, code); + } + } + }); + } + + /** + * 查询群成员资料(先从缓存中查,如果没有则从SDK DB中查询) + */ + public TeamMember getTeamMember(String teamId, String account) { + Map map = teamMemberCache.get(teamId); + if (map == null) { + map = new ConcurrentHashMap<>(); + teamMemberCache.put(teamId, map); + } + + if (!map.containsKey(account)) { + TeamMember member = NIMClient.getService(TeamService.class).queryTeamMemberBlock(teamId, account); + if (member != null) { + map.put(account, member); + } + } + + return map.get(account); + } + + private void replaceTeamMemberList(String tid, List members) { + if (members == null || members.isEmpty() || TextUtils.isEmpty(tid)) { + return; + } + + Map map = teamMemberCache.get(tid); + if (map == null) { + map = new ConcurrentHashMap<>(); + teamMemberCache.put(tid, map); + } else { + map.clear(); + } + + for (TeamMember m : members) { + map.put(m.getAccount(), m); + } + } + + private void addOrUpdateTeamMember(TeamMember member) { + if (member == null) { + return; + } + + Map map = teamMemberCache.get(member.getTid()); + if (map == null) { + map = new ConcurrentHashMap<>(); + teamMemberCache.put(member.getTid(), map); + } + + map.put(member.getAccount(), member); + } + + private void addOrUpdateTeamMembers(List members) { + for (TeamMember m : members) { + addOrUpdateTeamMember(m); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/UIKitLogTag.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/UIKitLogTag.java new file mode 100644 index 0000000..28b140f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/cache/UIKitLogTag.java @@ -0,0 +1,12 @@ +package com.fengliyan.tianlesue.im.uikit.impl.cache; + +/** + * Created by huangjun on 2015/10/13. + */ +public class UIKitLogTag { + public static final String CONTACT = "CONTACT"; + public static final String FRIEND_CACHE = "FRIEND_CACHE"; + public static final String USER_CACHE = "USER_CACHE"; + public static final String TEAM_CACHE = "TEAM_CACHE"; + public static final String ROBOT_CACHE = "ROBOT_CACHE"; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultContactEventListener.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultContactEventListener.java new file mode 100644 index 0000000..1af6466 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultContactEventListener.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.im.uikit.impl.customization; + +import android.content.Context; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactEventListener; + +/** + * ContactEventListener 通讯录联系人列表一些点击事件的响应处理 + *

+ * DefaultContactEventListener 提供了默认处理,其中点击Item 和 Avatar 响应为打开P2P聊天界面 + *

+ * Created by hzchenkang on 2016/12/21. + */ + +public class DefaultContactEventListener implements ContactEventListener { + + @Override + public void onItemClick(Context context, String account) { + // 点击联系人之后,可以选择打开个人信息页面或者聊天页面 + NimUIKit.startP2PSession(context, account); + } + + @Override + public void onItemLongClick(Context context, String account) { + // 长按联系人 + } + + @Override + public void onAvatarClick(Context context, String account) { + // 点击联系人之后,可以选择打开个人信息页面或者聊天页面 + NimUIKit.startP2PSession(context, account); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultP2PSessionCustomization.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultP2PSessionCustomization.java new file mode 100644 index 0000000..31200c9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultP2PSessionCustomization.java @@ -0,0 +1,30 @@ +package com.fengliyan.tianlesue.im.uikit.impl.customization; + +import android.app.Activity; +import android.content.Intent; + +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; + +/** + * SessionCustomization 可以实现聊天界面定制项: + * 1. 聊天背景
+ * 2. 加号展开后的按钮和动作,如自定义消息
+ * 3. ActionBar右侧按钮。 + *

+ * Created by hzchenkang on 2016/12/19. + */ + +public class DefaultP2PSessionCustomization extends SessionCustomization { + + @Override + public void onActivityResult(final Activity activity, int requestCode, int resultCode, Intent data) { + super.onActivityResult(activity, requestCode, resultCode, data); + } + + @Override + public MsgAttachment createStickerAttachment(String category, String item) { + return null; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultRecentCustomization.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultRecentCustomization.java new file mode 100644 index 0000000..1cac8e0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultRecentCustomization.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.im.uikit.impl.customization; + +import com.fengliyan.tianlesue.im.uikit.api.model.recent.RecentCustomization; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.TeamNotificationHelper; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.NotificationAttachment; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.RecentContact; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by huangjun on 2017/9/29. + */ + +public class DefaultRecentCustomization extends RecentCustomization { + + /** + * 最近联系人列表项文案定制 + * + * @param recent 最近联系人 + * @return 默认文案 + */ + public String getDefaultDigest(RecentContact recent) { + switch (recent.getMsgType()) { + case text: + return recent.getContent(); + case image: + return "[图片]"; + case video: + return "[视频]"; + case audio: + return "[语音消息]"; + case location: + return "[位置]"; + case file: + return "[文件]"; + case tip: + List uuids = new ArrayList<>(); + uuids.add(recent.getRecentMessageId()); + List messages = NIMClient.getService(MsgService.class).queryMessageListByUuidBlock(uuids); + if (messages != null && messages.size() > 0) { + return messages.get(0).getContent(); + } + return "[通知提醒]"; + case notification: + return TeamNotificationHelper.getTeamNotificationText(recent.getContactId(), + recent.getFromAccount(), + (NotificationAttachment) recent.getAttachment()); + case robot: + return "[机器人消息]"; + default: + return "[神秘惊喜] "; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultTeamSessionCustomization.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultTeamSessionCustomization.java new file mode 100644 index 0000000..816ffa0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/customization/DefaultTeamSessionCustomization.java @@ -0,0 +1,63 @@ +package com.fengliyan.tianlesue.im.uikit.impl.customization; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.view.View; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.business.team.model.TeamExtras; +import com.fengliyan.tianlesue.im.uikit.business.team.model.TeamRequestCode; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.netease.nim.uikit.R; +import com.netease.nimlib.sdk.team.model.Team; + +import java.util.ArrayList; + +/** + * SessionCustomization 可以实现聊天界面定制项: + * 1. 聊天背景
+ * 2. 加号展开后的按钮和动作,如自定义消息
+ * 3. ActionBar右侧按钮。 + *

+ * DefaultTeamSessionCustomization 提供默认的群聊界面定制,添加了ActionBar右侧按钮,用于跳转群信息界面 + *

+ * Created by hzchenkang on 2016/12/20. + */ + +public class DefaultTeamSessionCustomization extends SessionCustomization { + + public DefaultTeamSessionCustomization() { + + // ActionBar右侧按钮,跳转至群信息界面 + OptionsButton infoButton = new OptionsButton() { + @Override + public void onClick(Context context, View view, String sessionId) { + Team team = NimUIKit.getTeamProvider().getTeamById(sessionId); + if (team != null && team.isMyTeam()) { + NimUIKit.startTeamInfo(context, sessionId); + } else { + ToastHelper.showToast(context, R.string.team_invalid_tip); + } + } + }; + infoButton.iconId = R.drawable.nim_ic_message_actionbar_team; + buttons = new ArrayList<>(); + buttons.add(infoButton); + } + + public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { + if (requestCode == TeamRequestCode.REQUEST_CODE) { + if (resultCode == Activity.RESULT_OK) { + String reason = data.getStringExtra(TeamExtras.RESULT_EXTRA_REASON); + boolean finish = reason != null && (reason.equals(TeamExtras + .RESULT_EXTRA_REASON_DISMISS) || reason.equals(TeamExtras.RESULT_EXTRA_REASON_QUIT)); + if (finish) { + activity.finish(); // 退出or解散群直接退出多人会话 + } + } + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/preference/UserPreferences.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/preference/UserPreferences.java new file mode 100644 index 0000000..6dcd943 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/preference/UserPreferences.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.im.uikit.impl.preference; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; + +/** + * Created by hzxuwen on 2015/10/21. + */ +public class UserPreferences { + + private final static String KEY_EARPHONE_MODE = "KEY_EARPHONE_MODE"; + + public static void setEarPhoneModeEnable(boolean on) { + saveBoolean(KEY_EARPHONE_MODE, on); + } + + public static boolean isEarPhoneModeEnable() { + return getBoolean(KEY_EARPHONE_MODE, true); + } + + private static boolean getBoolean(String key, boolean value) { + return getSharedPreferences().getBoolean(key, value); + } + + private static void saveBoolean(String key, boolean value) { + SharedPreferences.Editor editor = getSharedPreferences().edit(); + editor.putBoolean(key, value); + editor.apply(); + } + + private static SharedPreferences getSharedPreferences() { + return NimUIKit.getContext().getSharedPreferences("UIKit." + NimUIKit.getAccount(), Context.MODE_PRIVATE); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultChatRoomProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultChatRoomProvider.java new file mode 100644 index 0000000..5c7d231 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultChatRoomProvider.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.im.uikit.impl.provider; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.chatroom.ChatRoomProvider; +import com.fengliyan.tianlesue.im.uikit.impl.cache.ChatRoomMemberCache; +import com.netease.nimlib.sdk.chatroom.constant.MemberQueryType; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +import java.util.List; + +/** + * Created by hzchenkang on 2017/11/2. + */ + +public class DefaultChatRoomProvider implements ChatRoomProvider { + + @Override + public ChatRoomMember getChatRoomMember(String roomId, String account) { + return ChatRoomMemberCache.getInstance().getChatRoomMember(roomId, account); + } + + @Override + public void fetchMember(String roomId, String account, SimpleCallback callback) { + ChatRoomMemberCache.getInstance().fetchMember(roomId, account, callback); + } + + @Override + public void fetchRoomMembers(String roomId, MemberQueryType memberQueryType, long time, int limit, SimpleCallback> callback) { + ChatRoomMemberCache.getInstance().fetchRoomMembers(roomId, memberQueryType, time, limit, callback); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultContactProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultContactProvider.java new file mode 100644 index 0000000..6294948 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultContactProvider.java @@ -0,0 +1,41 @@ +package com.fengliyan.tianlesue.im.uikit.impl.provider; + +import android.text.TextUtils; + +import com.fengliyan.tianlesue.im.uikit.api.model.contact.ContactProvider; +import com.fengliyan.tianlesue.im.uikit.impl.cache.FriendDataCache; +import com.netease.nimlib.sdk.friend.model.Friend; + +import java.util.List; + +/** + * UIKit默认的通讯录(联系人)数据源提供者, + * Created by hzchenkang on 2016/12/19. + */ + +public class DefaultContactProvider implements ContactProvider { + + @Override + public List getUserInfoOfMyFriends() { + return FriendDataCache.getInstance().getMyFriendAccounts(); + } + + @Override + public int getMyFriendsCount() { + return FriendDataCache.getInstance().getMyFriendCounts(); + } + + @Override + public String getAlias(String account) { + Friend friend = FriendDataCache.getInstance().getFriendByAccount(account); + if (friend != null && !TextUtils.isEmpty(friend.getAlias())) { + return friend.getAlias(); + } + return null; + } + + @Override + public boolean isMyFriend(String account) { + return FriendDataCache.getInstance().isMyFriend(account); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultRobotProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultRobotProvider.java new file mode 100644 index 0000000..ec001d3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultRobotProvider.java @@ -0,0 +1,35 @@ +package com.fengliyan.tianlesue.im.uikit.impl.provider; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.robot.RobotInfoProvider; +import com.fengliyan.tianlesue.im.uikit.impl.cache.RobotInfoCache; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; + +import java.util.List; + +/** + * Created by hzchenkang on 2017/11/2. + */ + +public class DefaultRobotProvider implements RobotInfoProvider { + + @Override + public NimRobotInfo getRobotByAccount(String account) { + return RobotInfoCache.getInstance().getRobotByAccount(account); + } + + @Override + public List getAllRobotAccounts() { + return RobotInfoCache.getInstance().getAllRobotAccounts(); + } + + @Override + public void fetchRobotList(SimpleCallback> callback) { + RobotInfoCache.getInstance().fetchRobotList(callback); + } + + @Override + public void fetchRobotListIndependent(String roomId, SimpleCallback> callback) { + RobotInfoCache.getInstance().pullRobotListIndependent(roomId, callback); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultTeamProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultTeamProvider.java new file mode 100644 index 0000000..05509f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultTeamProvider.java @@ -0,0 +1,62 @@ +package com.fengliyan.tianlesue.im.uikit.impl.provider; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.team.TeamProvider; +import com.fengliyan.tianlesue.im.uikit.impl.cache.TeamDataCache; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.List; + +/** + * Created by hzchenkang on 2017/11/1. + */ + +public class DefaultTeamProvider implements TeamProvider { + @Override + public void fetchTeamById(String teamId, SimpleCallback callback) { + TeamDataCache.getInstance().fetchTeamById(teamId, callback); + } + + @Override + public Team getTeamById(String teamId) { + return TeamDataCache.getInstance().getTeamById(teamId); + } + + @Override + public List getAllTeams() { + return TeamDataCache.getInstance().getAllTeams(); + } + + @Override + public List getAllTeamsByType(TeamTypeEnum teamTypeEnum) { + if (teamTypeEnum == TeamTypeEnum.Advanced) { + return TeamDataCache.getInstance().getAllAdvancedTeams(); + } else if (teamTypeEnum == TeamTypeEnum.Normal) { + return TeamDataCache.getInstance().getAllNormalTeams(); + } else { + return null; + } + } + + @Override + public void fetchTeamMemberList(String teamId, SimpleCallback> callback) { + TeamDataCache.getInstance().fetchTeamMemberList(teamId, callback); + } + + @Override + public void fetchTeamMember(String teamId, String account, SimpleCallback callback) { + TeamDataCache.getInstance().fetchTeamMember(teamId, account, callback); + } + + @Override + public List getTeamMemberList(String teamId) { + return TeamDataCache.getInstance().getTeamMemberList(teamId); + } + + @Override + public TeamMember getTeamMember(String teamId, String account) { + return TeamDataCache.getInstance().getTeamMember(teamId, account); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultUserInfoProvider.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultUserInfoProvider.java new file mode 100644 index 0000000..365be8d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/impl/provider/DefaultUserInfoProvider.java @@ -0,0 +1,64 @@ +package com.fengliyan.tianlesue.im.uikit.impl.provider; + +import com.fengliyan.tianlesue.im.uikit.api.model.SimpleCallback; +import com.fengliyan.tianlesue.im.uikit.api.model.user.IUserInfoProvider; +import com.fengliyan.tianlesue.im.uikit.impl.cache.NimUserInfoCache; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by hzchenkang on 2017/10/24. + */ + +public class DefaultUserInfoProvider implements IUserInfoProvider { + + @Override + public NimUserInfo getUserInfo(String account) { + NimUserInfo user = NimUserInfoCache.getInstance().getUserInfo(account); + if (user == null) { + NimUserInfoCache.getInstance().getUserInfoFromRemote(account, null); + } + + return user; + } + + @Override + public List getUserInfo(List accounts) { + List users = new ArrayList<>(); + for (String account : accounts) { + NimUserInfo userInfo = getUserInfo(account); + if (userInfo != null) { + users.add(userInfo); + } + } + return users; + } + + @Override + public void getUserInfoAsync(String account, final SimpleCallback callback) { + NimUserInfoCache.getInstance().getUserInfoFromRemote(account, new RequestCallbackWrapper() { + @Override + public void onResult(int code, NimUserInfo result, Throwable exception) { + if (callback != null) { + callback.onResult(code == ResponseCode.RES_SUCCESS, result, code); + } + } + }); + } + + @Override + public void getUserInfoAsync(List accounts, final SimpleCallback> callback) { + NimUserInfoCache.getInstance().getUserInfoFromRemote(accounts, new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List result, Throwable exception) { + if (callback != null) { + callback.onResult(code == ResponseCode.RES_SUCCESS, result, code); + } + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/glide/ImageLoaderKit.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/glide/ImageLoaderKit.java new file mode 100644 index 0000000..8291d25 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/glide/ImageLoaderKit.java @@ -0,0 +1,101 @@ +package com.fengliyan.tianlesue.im.uikit.support.glide; + +import android.content.Context; +import android.graphics.Bitmap; +import android.text.TextUtils; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.framework.NimSingleThreadExecutor; +import com.fengliyan.tianlesue.im.uikit.common.ui.imageview.HeadImageView; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +import java.util.concurrent.TimeUnit; + +/** + * 图片缓存管理组件 + */ +public class ImageLoaderKit { + + private static final String TAG = "ImageLoaderKit"; + + private Context context; + + public ImageLoaderKit(Context context) { + this.context = context; + } + + /** + * 清空图像缓存 + */ + + public void clear() { + NIMGlideModule.clearMemoryCache(context); + } + + /** + * 构建图像缓存 + */ + public void buildImageCache() { + // 不必清除缓存,并且这个缓存清除比较耗时 + // clear(); + + // build self avatar cache + asyncLoadAvatarBitmapToCache(NimUIKit.getAccount()); + } + + /** + * 获取通知栏提醒所需的头像位图,只存内存缓存/磁盘缓存中取,如果没有则返回空,自动发起异步加载 + * 注意:该方法在后台线程执行 + */ + public Bitmap getNotificationBitmapFromCache(String url) { + if (TextUtils.isEmpty(url)) { + return null; + } + final int imageSize = HeadImageView.DEFAULT_AVATAR_NOTIFICATION_ICON_SIZE; + + Bitmap cachedBitmap = null; + try { + cachedBitmap = Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions() + .centerCrop() + .override(imageSize, imageSize)) + .submit() + .get(200, TimeUnit.MILLISECONDS)// 最大等待200ms + ; + } catch (Exception e) { + e.printStackTrace(); + } + + return cachedBitmap; + } + + /** + * 异步加载头像位图到Glide缓存中 + */ + private void asyncLoadAvatarBitmapToCache(final String account) { + NimSingleThreadExecutor.getInstance().execute(new Runnable() { + @Override + public void run() { + UserInfo userInfo = NimUIKit.getUserInfoProvider().getUserInfo(account); + if (userInfo != null) { + loadAvatarBitmapToCache(userInfo.getAvatar()); + } + } + }); + } + + private void loadAvatarBitmapToCache(String url) { + if (TextUtils.isEmpty(url)) { + return; + } + + final int imageSize = HeadImageView.DEFAULT_AVATAR_THUMB_SIZE; + Glide.with(context) + .load(url) + .submit(imageSize, imageSize); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/glide/NIMGlideModule.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/glide/NIMGlideModule.java new file mode 100644 index 0000000..4686f5f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/glide/NIMGlideModule.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.im.uikit.support.glide; + +import android.content.Context; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.GlideBuilder; +import com.bumptech.glide.Registry; +import com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory; +import com.bumptech.glide.module.GlideModule; + +/** + * Created by huangjun on 2017/4/1. + */ +public class NIMGlideModule implements GlideModule { + private static final String TAG = "NIMGlideModule"; + + private static final int M = 1024 * 1024; + private static final int MAX_DISK_CACHE_SIZE = 256 * M; + + /** + * ************************ Memory Cache ************************ + */ + + static void clearMemoryCache(Context context) { + Glide.get(context).clearMemory(); + } + + /** + * ************************ GlideModule override ************************ + */ + @Override + public void applyOptions(Context context, GlideBuilder builder) { + // sdcard/Android/data/com.netease.nim.demo/glide + final String cachedDirName = "glide"; + builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, cachedDirName, MAX_DISK_CACHE_SIZE)); +// LogUtil.i(TAG, "NIMGlideModule apply options, disk cached path=" + context.getExternalCacheDir() + File.pathSeparator + cachedDirName); + } + + @Override + public void registerComponents(Context context, Glide glide, Registry registry) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/BaseMPermission.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/BaseMPermission.java new file mode 100644 index 0000000..f26c473 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/BaseMPermission.java @@ -0,0 +1,205 @@ +package com.fengliyan.tianlesue.im.uikit.support.permission; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.pm.PackageManager; +import android.os.Build; +import android.util.Log; + +import androidx.fragment.app.Fragment; + +import java.util.ArrayList; +import java.util.List; + +public class BaseMPermission { + + private static final String TAG = "MPermission"; + + public enum MPermissionResultEnum { + GRANTED, DENIED, DENIED_NEVER_ASK_AGAIN + } + + static boolean isOverMarshmallow() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; + } + + static Activity getActivity(Object object) { + if (object instanceof Fragment) { + return ((Fragment) object).getActivity(); + } else if (object instanceof Activity) { + return (Activity) object; + } + return null; + } + + /** + * 获取权限请求结果 + */ + public static List getPermissionResult(Activity activity, String[] permissions) { + return findPermissionResult(activity, permissions); + } + + public static List getPermissionResult(Fragment fragment, String[] permissions) { + return findPermissionResult(fragment.getActivity(), permissions); + } + + @TargetApi(value = Build.VERSION_CODES.M) + private static List findPermissionResult(Activity activity, String... permissions) { + boolean overM = isOverMarshmallow(); + List result = new ArrayList<>(); + for (String p : permissions) { + if (overM) { + if (activity.checkSelfPermission(p) == PackageManager.PERMISSION_GRANTED) { + result.add(MPermissionResultEnum.GRANTED); + } else { + if (!activity.shouldShowRequestPermissionRationale(p)) { + result.add(MPermissionResultEnum.DENIED_NEVER_ASK_AGAIN); + } else { + result.add(MPermissionResultEnum.DENIED); + } + } + } else { + result.add(MPermissionResultEnum.GRANTED); + } + } + + return result; + } + + /** + * 获取所有被未被授权的权限 + */ + public static List getDeniedPermissions(Activity activity, String[] permissions) { + return findDeniedPermissions(activity, permissions); + } + + public static List getDeniedPermissions(Fragment fragment, String[] permissions) { + return findDeniedPermissions(fragment.getActivity(), permissions); + } + + @TargetApi(value = Build.VERSION_CODES.M) + static List findDeniedPermissions(Activity activity, String... permissions) { + if (!isOverMarshmallow()) { + return null; + } + + List denyPermissions = new ArrayList<>(); + for (String value : permissions) { + if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED) { + denyPermissions.add(value); + } + } + return denyPermissions; + } + + /** + * 获取被拒绝且勾选不再询问的权限 + * 请在请求权限结果回调中使用,因为从未请求过的权限也会被认为是该结果集 + */ + public static List getNeverAskAgainPermissions(Activity activity, String[] permissions) { + return findNeverAskAgainPermissions(activity, permissions); + } + + public static List getNeverAskAgainPermissions(Fragment fragment, String[] permissions) { + return findNeverAskAgainPermissions(fragment.getActivity(), permissions); + } + + @TargetApi(value = Build.VERSION_CODES.M) + private static List findNeverAskAgainPermissions(Activity activity, String... permissions) { + if (!isOverMarshmallow()) { + return null; + } + + List neverAskAgainPermission = new ArrayList<>(); + for (String value : permissions) { + if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED && + !activity.shouldShowRequestPermissionRationale(value)) { + // 拒绝&不要需要解释了(用户勾选了不再询问) + // 坑爹:第一次不做任何设置,返回值也是false。建议在权限授权结果里判断!!! + neverAskAgainPermission.add(value); + } + } + + return neverAskAgainPermission; + } + + @TargetApi(value = Build.VERSION_CODES.M) + static boolean hasNeverAskAgainPermission(Activity activity, List permission) { + if (!isOverMarshmallow()) { + return false; + } + + for (String value : permission) { + if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED && + !activity.shouldShowRequestPermissionRationale(value)) { + return true; + } + } + + return false; + } + + /** + * 获取被拒绝但没有勾选不再询问的权限(可以继续申请,会继续弹框) + */ + public static List getDeniedPermissionsWithoutNeverAskAgain(Activity activity, String[] permissions) { + return findDeniedPermissionWithoutNeverAskAgain(activity, permissions); + } + + public static List getDeniedPermissionsWithoutNeverAskAgain(Fragment fragment, String[] permissions) { + return findDeniedPermissionWithoutNeverAskAgain(fragment.getActivity(), permissions); + } + + @TargetApi(value = Build.VERSION_CODES.M) + private static List findDeniedPermissionWithoutNeverAskAgain(Activity activity, String... permission) { + if (!isOverMarshmallow()) { + return null; + } + + List denyPermissions = new ArrayList<>(); + for (String value : permission) { + if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED && + activity.shouldShowRequestPermissionRationale(value)) { + denyPermissions.add(value); // 上次申请被用户拒绝了 + } + } + + return denyPermissions; + } + + /** + * Log专用 + */ + public static void printMPermissionResult(boolean preRequest, Activity activity, String[] permissions) { + Log.i(TAG, "----- MPermission result " + (preRequest ? "before" : "after") + " request:"); + List result = getPermissionResult(activity, permissions); + int i = 0; + for (BaseMPermission.MPermissionResultEnum p : result) { + Log.i(TAG, "* MPermission=" + permissions[i++] + ", result=" + p); + } + } + + static String toString(List permission) { + if (permission == null || permission.isEmpty()) { + return ""; + } + + return toString(permission.toArray(new String[permission.size()])); + } + + private static String toString(String[] permission) { + if (permission == null || permission.length <= 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + for (String p : permission) { + sb.append(p.replaceFirst("android.permission.", "")); + sb.append(","); + } + + sb.deleteCharAt(sb.length() - 1); + + return sb.toString(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/MPermission.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/MPermission.java new file mode 100644 index 0000000..f7c1a13 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/MPermission.java @@ -0,0 +1,170 @@ +package com.fengliyan.tianlesue.im.uikit.support.permission; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.pm.PackageManager; +import android.os.Build; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import com.fengliyan.tianlesue.im.uikit.support.permission.annotation.OnMPermissionDenied; +import com.fengliyan.tianlesue.im.uikit.support.permission.annotation.OnMPermissionGranted; +import com.fengliyan.tianlesue.im.uikit.support.permission.annotation.OnMPermissionNeverAskAgain; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public class MPermission extends BaseMPermission { + + private int requestCode; + private String[] permissions; + private Object object; // activity or fragment + + private MPermission(Object object) { + this.object = object; + } + + public static MPermission with(Activity activity) { + return new MPermission(activity); + } + + public static MPermission with(Fragment fragment) { + return new MPermission(fragment); + } + + public MPermission setRequestCode(int requestCode) { + this.requestCode = requestCode; + return this; + } + + public MPermission permissions(String... permissions) { + this.permissions = permissions; + return this; + } + + /** + * ********************* request ********************* + */ + + @TargetApi(value = Build.VERSION_CODES.M) + public void request() { + doRequestPermissions(object, requestCode, permissions); + } + + @TargetApi(value = Build.VERSION_CODES.M) + private static void doRequestPermissions(Object object, int requestCode, String[] permissions) { + if (!isOverMarshmallow()) { + doExecuteSuccess(object, requestCode); + return; + } + + List deniedPermissions = findDeniedPermissions(getActivity(object), permissions); + if (deniedPermissions != null && deniedPermissions.size() > 0) { + if (object instanceof Activity) { + ((Activity) object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode); + } else if (object instanceof Fragment) { + ((Fragment) object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode); + } else { + throw new IllegalArgumentException(object.getClass().getName() + " is not supported"); + } + } else { + doExecuteSuccess(object, requestCode); + } + } + + /** + * ********************* on result ********************* + */ + + public static void onRequestPermissionsResult(Activity activity, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + dispatchResult(activity, requestCode, permissions, grantResults); + } + + public static void onRequestPermissionsResult(Fragment fragment, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + dispatchResult(fragment, requestCode, permissions, grantResults); + } + + private static void dispatchResult(Object obj, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + List deniedPermissions = new ArrayList<>(); + for (int i = 0; i < grantResults.length; i++) { + if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { + deniedPermissions.add(permissions[i]); + } + } + + if (deniedPermissions.size() > 0) { + if (hasNeverAskAgainPermission(getActivity(obj), deniedPermissions)) { + doExecuteFailAsNeverAskAgain(obj, requestCode); + } else { + doExecuteFail(obj, requestCode); + } + } else { + doExecuteSuccess(obj, requestCode); + } + } + + /** + * ********************* reflect execute result ********************* + */ + + private static void doExecuteSuccess(Object activity, int requestCode) { + executeMethod(activity, findMethodWithRequestCode(activity.getClass(), OnMPermissionGranted.class, requestCode)); + } + + private static void doExecuteFail(Object activity, int requestCode) { + executeMethod(activity, findMethodWithRequestCode(activity.getClass(), OnMPermissionDenied.class, requestCode)); + } + + private static void doExecuteFailAsNeverAskAgain(Object activity, int requestCode) { + executeMethod(activity, findMethodWithRequestCode(activity.getClass(), OnMPermissionNeverAskAgain.class, requestCode)); + } + + private static Method findMethodWithRequestCode(Class clazz, Class annotation, int + requestCode) { + for (Method method : clazz.getDeclaredMethods()) { + if (method.getAnnotation(annotation) != null && + isEqualRequestCodeFromAnnotation(method, annotation, requestCode)) { + return method; + } + } + return null; + } + + private static boolean isEqualRequestCodeFromAnnotation(Method m, Class clazz, int requestCode) { + if (clazz.equals(OnMPermissionDenied.class)) { + return requestCode == m.getAnnotation(OnMPermissionDenied.class).value(); + } else if (clazz.equals(OnMPermissionGranted.class)) { + return requestCode == m.getAnnotation(OnMPermissionGranted.class).value(); + } else if (clazz.equals(OnMPermissionNeverAskAgain.class)) { + return requestCode == m.getAnnotation(OnMPermissionNeverAskAgain.class).value(); + } else { + return false; + } + } + + /** + * ********************* reflect execute method ********************* + */ + + private static void executeMethod(Object activity, Method executeMethod) { + executeMethodWithParam(activity, executeMethod, new Object[]{}); + } + + private static void executeMethodWithParam(Object activity, Method executeMethod, Object... args) { + if (executeMethod != null) { + try { + if (!executeMethod.isAccessible()) { + executeMethod.setAccessible(true); + } + executeMethod.invoke(activity, args); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionDenied.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionDenied.java new file mode 100644 index 0000000..171fd57 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionDenied.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.support.permission.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * register a method invoked when permission requests are denied without check never ask again. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface OnMPermissionDenied { + int value(); +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionGranted.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionGranted.java new file mode 100644 index 0000000..417509c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionGranted.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.support.permission.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * register a method invoked when permission requests are succeeded. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface OnMPermissionGranted { + int value(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionNeverAskAgain.java b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionNeverAskAgain.java new file mode 100644 index 0000000..21eb3bd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/im/uikit/support/permission/annotation/OnMPermissionNeverAskAgain.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.im.uikit.support.permission.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * register some methods handling the user's choice to permanently deny permissions checking never ask again. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface OnMPermissionNeverAskAgain { + int value(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/chat/ChatCardRewardBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/chat/ChatCardRewardBean.java new file mode 100644 index 0000000..53091b2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/chat/ChatCardRewardBean.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.model.chat; + +import java.io.Serializable; + +/** + * 自定义文本消息实体类 + */ +public class ChatCardRewardBean implements Serializable { + + private String give_num; + private String is_pop_up;//1.显示 + + public String getGive_num() { + return give_num; + } + + public void setGive_num(String give_num) { + this.give_num = give_num; + } + + public String getIs_pop_up() { + return is_pop_up; + } + + public void setIs_pop_up(String is_pop_up) { + this.is_pop_up = is_pop_up; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/chat/ImageCheckBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/chat/ImageCheckBean.java new file mode 100644 index 0000000..c43ae5c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/chat/ImageCheckBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.chat; + +public class ImageCheckBean { + public int getIs_upload() { + return is_upload; + } + + public void setIs_upload(int is_upload) { + this.is_upload = is_upload; + } + + private int is_upload; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/chat/RecoverBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/chat/RecoverBean.java new file mode 100644 index 0000000..27be5cb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/chat/RecoverBean.java @@ -0,0 +1,35 @@ +package com.fengliyan.tianlesue.model.chat; + +import java.io.Serializable; + +public class RecoverBean implements Serializable { + private static final long serialVersionUID = -4256232088185617007L; + private int messageType; + private String value; + private String nickName; + + public int getMessageType() { + return messageType; + } + + public void setMessageType(int messageType) { + this.messageType = messageType; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getNickName() { + + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/CommentBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/CommentBean.java new file mode 100644 index 0000000..57ebf36 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/CommentBean.java @@ -0,0 +1,130 @@ +package com.fengliyan.tianlesue.model.dynamics; + +public class CommentBean { + private int id; + private int dynamic_id; + private int uid; + private int parentId; + private String user_id; + private String content; + private String create_time; + private String avatar; + private String nickname; + private int age; + private int gender; + private String city; + private String pnickname; + private int is_like; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getDynamic_id() { + return dynamic_id; + } + + public void setDynamic_id(int dynamic_id) { + this.dynamic_id = dynamic_id; + } + + public int getUid() { + return uid; + } + + public void setUid(int uid) { + this.uid = uid; + } + + public int getParentId() { + return parentId; + } + + public void setParentId(int parentId) { + this.parentId = parentId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getCreate_time() { + return create_time; + } + + public void setCreate_time(String create_time) { + this.create_time = create_time; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getPnickname() { + return pnickname; + } + + public void setPnickname(String pnickname) { + this.pnickname = pnickname; + } + + public int getIs_like() { + return is_like; + } + + public void setIs_like(int is_like) { + this.is_like = is_like; + } + + public String getUser_id() { + return user_id; + } + + public void setUser_id(String user_id) { + this.user_id = user_id; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicImage.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicImage.java new file mode 100644 index 0000000..48b1a61 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicImage.java @@ -0,0 +1,50 @@ +package com.fengliyan.tianlesue.model.dynamics; + +public class DynamicImage { + private String url; + private int width; + private int height; + private String exts; + + public String getVideo_url() { + return video_url; + } + + public void setVideo_url(String video_url) { + this.video_url = video_url; + } + + private String video_url; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + + public String getExts() { + return exts; + } + + public void setExts(String exts) { + this.exts = exts; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicPostBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicPostBean.java new file mode 100644 index 0000000..503c6d0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicPostBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.dynamics; + +public class DynamicPostBean { + private String dynamic_id; + + public String getDynamic_id() { + return dynamic_id; + } + + public void setDynamic_id(String dynamic_id) { + this.dynamic_id = dynamic_id; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicsItemBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicsItemBean.java new file mode 100644 index 0000000..8b97a03 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicsItemBean.java @@ -0,0 +1,208 @@ +package com.fengliyan.tianlesue.model.dynamics; + +import java.util.List; + +public class DynamicsItemBean { + private String avatar; + private String nickname; + private int age; + private String id; + private String user_id; + private int gender; + private String content; + private List images; + private int is_follow; + private int is_like; + private int like_count; + private int reward_count; + private String city; + private String create_time; + private List comments; + private List list; + private List likes; + private boolean expand; + + public int getMark() { + return mark; + } + + public void setMark(int mark) { + this.mark = mark; + } + + private int mark; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public List getComments() { + return comments; + } + + public void setComments(List comments) { + this.comments = comments; + } + + public List getLikes() { + return likes; + } + + public void setLikes(List likes) { + this.likes = likes; + } + + public int getComment_count() { + return comment_count; + } + + public void setComment_count(int comment_count) { + this.comment_count = comment_count; + } + + private int comment_count; + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUser_id() { + return user_id; + } + + public void setUser_id(String user_id) { + this.user_id = user_id; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public List getImages() { + return images; + } + + public void setImages(List images) { + this.images = images; + } + + public int getIs_follow() { + return is_follow; + } + + public void setIs_follow(int is_follow) { + this.is_follow = is_follow; + } + + public int getIs_like() { + return is_like; + } + + public void setIs_like(int is_like) { + this.is_like = is_like; + } + + public int getLike_count() { + return like_count; + } + + public void setLike_count(int like_count) { + this.like_count = like_count; + } + + public int getReward_count() { + return reward_count; + } + + public void setReward_count(int reward_count) { + this.reward_count = reward_count; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCreate_time() { + return create_time; + } + + public void setCreate_time(String create_time) { + this.create_time = create_time; + } + + public boolean getExpand() { + return expand; + } + + public void setExpand(boolean expand) { + this.expand = expand; + } + + @Override + public String toString() { + return "DynamicsItemBean{" + + "avatar='" + avatar + '\'' + + ", nickname='" + nickname + '\'' + + ", age=" + age + + ", id='" + id + '\'' + + ", user_id='" + user_id + '\'' + + ", gender=" + gender + + ", content='" + content + '\'' + + ", images=" + images + + ", is_follow=" + is_follow + + ", is_like=" + is_like + + ", like_count=" + like_count + + ", reward_count=" + reward_count + + ", city='" + city + '\'' + + ", create_time='" + create_time + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicsListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicsListBean.java new file mode 100644 index 0000000..c4d519d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/DynamicsListBean.java @@ -0,0 +1,25 @@ +package com.fengliyan.tianlesue.model.dynamics; + +import java.util.ArrayList; +import java.util.List; + +public class DynamicsListBean { + private int total; + private List list = new ArrayList<>(); + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/ImageUploadBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/ImageUploadBean.java new file mode 100644 index 0000000..739073d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/ImageUploadBean.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.model.dynamics; + +import java.util.List; + +public class ImageUploadBean { + private int dynamic_id; + private List images; + + public int getDynamic_id() { + return dynamic_id; + } + + public void setDynamic_id(int dynamic_id) { + this.dynamic_id = dynamic_id; + } + + public List getImages() { + return images; + } + + public void setImages(List images) { + this.images = images; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/ImageUploadItemBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/ImageUploadItemBean.java new file mode 100644 index 0000000..ada6044 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/ImageUploadItemBean.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.model.dynamics; + +public class ImageUploadItemBean { + private int id; + private int user_id; + private int dynamic_id; + private String url; + private long create_time; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public int getDynamic_id() { + return dynamic_id; + } + + public void setDynamic_id(int dynamic_id) { + this.dynamic_id = dynamic_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public long getCreate_time() { + return create_time; + } + + public void setCreate_time(long create_time) { + this.create_time = create_time; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/UploadImageBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/UploadImageBean.java new file mode 100644 index 0000000..4ae77ba --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/dynamics/UploadImageBean.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.model.dynamics; + +public class UploadImageBean { + private String type; + private String url; + + public String getImg_id() { + return img_id; + } + + public void setImg_id(String img_id) { + this.img_id = img_id; + } + + private String img_id; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/CustomerTipBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/CustomerTipBean.java new file mode 100644 index 0000000..6e63abe --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/CustomerTipBean.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.model.login.bean; + +import java.util.List; + +public class CustomerTipBean { + private String title; + private String color_text; + private String copy_text; + private List content; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getColor_text() { + return color_text; + } + + public void setColor_text(String color_text) { + this.color_text = color_text; + } + + public String getCopy_text() { + return copy_text; + } + + public void setCopy_text(String copy_text) { + this.copy_text = copy_text; + } + + public List getContent() { + return content; + } + + public void setContent(List content) { + this.content = content; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/LoginBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/LoginBean.java new file mode 100644 index 0000000..fd98b27 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/LoginBean.java @@ -0,0 +1,50 @@ +package com.fengliyan.tianlesue.model.login.bean; + +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; + +import java.util.List; + +/** + * Created by abby on 2018/4/7. + */ + +public class LoginBean { + private BaseUserInfo userinfo; + + public BaseUserInfo getUserinfo() { + return userinfo; + } + + public void setUserinfo(BaseUserInfo userinfo) { + this.userinfo = userinfo; + } + + private String title; + private String color_text; + private List content; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getColor_text() { + return color_text; + } + + public void setColor_text(String color_text) { + this.color_text = color_text; + } + + public List getContent() { + return content; + } + + public void setContent(List content) { + this.content = content; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/NickNameBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/NickNameBean.java new file mode 100644 index 0000000..196e9bc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/NickNameBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.login.bean; + +public class NickNameBean { + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + private String nickname; + private String avatar; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/VipBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/VipBean.java new file mode 100644 index 0000000..68e4dd5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/login/bean/VipBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.login.bean; + +/** + * Created by abby on 2018/4/7.1 + */ + +public class VipBean { + + /** + * if_vip : 1 + */ + + private int if_vip; + + public int getIf_vip() { + return if_vip; + } + + public void setIf_vip(int if_vip) { + this.if_vip = if_vip; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/AnchorBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/AnchorBean.java new file mode 100644 index 0000000..8835b60 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/AnchorBean.java @@ -0,0 +1,204 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; +import java.util.List; + +public class AnchorBean implements Serializable { + private static final long serialVersionUID = -1554873974708007628L; + private int userid; + private String nickname; + private String cover; + private String city; + private int gender; + private int age; + private String signature; + private String job; + private float video_amount; + private float give_score; + private int greet_status;//显示打招呼状态:1 = 显示打招呼、0 = 显示私信 + private int vip; + private String cover_video; + private List img_list; + private int online_status;//在线状态, 1.在线 0.不在线 + private boolean isVideo; + private boolean is_follow;//true关注false未关注 + private int anchor_tag;// 1=王牌 2=人气 + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + private int price; + + public int getMark() { + return mark; + } + + public void setMark(int mark) { + this.mark = mark; + } + + private int mark; + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getCover() { + return cover; + } + + public void setCover(String cover) { + this.cover = cover; + } + + public float getVideo_amount() { + return video_amount; + } + + public void setVideo_amount(float video_amount) { + this.video_amount = video_amount; + } + + public float getGive_score() { + return give_score; + } + + public void setGive_score(float give_score) { + this.give_score = give_score; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public int getGreet_status() { + return greet_status; + } + + public void setGreet_status(int greet_status) { + this.greet_status = greet_status; + } + + public int getVip() { + return vip; + } + + public void setVip(int vip) { + this.vip = vip; + } + + public String getCover_video() { + return cover_video; + } + + public void setCover_video(String cover_video) { + this.cover_video = cover_video; + } + + public List getImg_list() { + return img_list; + } + + public void setImg_list(List img_list) { + this.img_list = img_list; + } + + public int getOnline_status() { + return online_status; + } + + public void setOnline_status(int online_status) { + this.online_status = online_status; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public String getJob() { + return job; + } + + public void setJob(String job) { + this.job = job; + } + + public boolean isVideo() { + return isVideo; + } + + public void setVideo(boolean video) { + isVideo = video; + } + + public boolean isIs_follow() { + return is_follow; + } + + public void setIs_follow(boolean is_follow) { + this.is_follow = is_follow; + } + + public int getAnchor_tag() { + return anchor_tag; + } + + public void setAnchor_tag(int anchor_tag) { + this.anchor_tag = anchor_tag; + } + + @Override + public String toString() { + return "AnchorBean{" + + "userid=" + userid + + ", nickname='" + nickname + '\'' + + ", cover='" + cover + '\'' + + ", city='" + city + '\'' + + ", gender=" + gender + + ", age=" + age + + ", video_amount=" + video_amount + + ", give_score=" + give_score + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/AnchorListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/AnchorListBean.java new file mode 100644 index 0000000..e992260 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/AnchorListBean.java @@ -0,0 +1,61 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.ArrayList; +import java.util.List; + +public class AnchorListBean { + private int skill_id; + private String skill_name; + private String skill_icon; + private int total; + private List anchors = new ArrayList<>(); + private List list = new ArrayList<>(); + + public List getAnchors() { + return anchors; + } + + public void setAnchors(List anchors) { + this.anchors = anchors; + } + + public int getSkill_id() { + return skill_id; + } + + public void setSkill_id(int skill_id) { + this.skill_id = skill_id; + } + + public String getSkill_name() { + return skill_name; + } + + public void setSkill_name(String skill_name) { + this.skill_name = skill_name; + } + + public String getSkill_icon() { + return skill_icon; + } + + public void setSkill_icon(String skill_icon) { + this.skill_icon = skill_icon; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/AttentionBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/AttentionBean.java new file mode 100644 index 0000000..e202d51 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/AttentionBean.java @@ -0,0 +1,94 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by zhangbin on 2019/1/10. + */ + +public class AttentionBean { + + private int id; + private String avatar; + private String name; + private int select; //0是选中,1是没有选中 + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getSelect() { + return select; + } + + public void setSelect(int select) { + this.select = select; + } + + @Override + public String toString() { + return "AttentionBean{" + + "id=" + id + + ", avatar='" + avatar + '\'' + + ", name='" + name + '\'' + + ", select=" + select + + '}'; + } + + /** + userid":320, + "nickname":"路", + "usercode":"106210", + "gender":1, + "age":18, + "cover":"uploads/album/201901/02/6db6f66ebcb47a3d7ba9b1628be5cdc4.jpg", + "city":"深圳", + "give_score":"5.00" + */ + + private int userid; + private String nickname; + private String cover; + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getCover() { + return cover; + } + + public void setCover(String cover) { + this.cover = cover; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/AttentionDialogBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/AttentionDialogBean.java new file mode 100644 index 0000000..f86a00b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/AttentionDialogBean.java @@ -0,0 +1,20 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.List; + +/** + * Created by zhangbin on 2019/1/11. + */ + +public class AttentionDialogBean { + + private List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/BannerBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/BannerBean.java new file mode 100644 index 0000000..4b2c5f4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/BannerBean.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.model.main; + +public class BannerBean { + private String title; + private String image; + private int link_type; + private String link_url; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public int getLink_type() { + return link_type; + } + + public void setLink_type(int link_type) { + this.link_type = link_type; + } + + public String getLink_url() { + return link_url; + } + + public void setLink_url(String link_url) { + this.link_url = link_url; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/BlackBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/BlackBean.java new file mode 100644 index 0000000..8ec69d5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/BlackBean.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by zhangbin on 2019/1/14. + */ + +public class BlackBean { + + String action; + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/CallBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/CallBean.java new file mode 100644 index 0000000..486c53c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/CallBean.java @@ -0,0 +1,232 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; + +public class CallBean implements Serializable { + private static final long serialVersionUID = -2185989143401723848L; + private String room_id; + private int from_uid; + private String from_nickname; + private String from_avatar; + private int to_uid; + private String to_nickname; + private String to_avatar; + private String free_num; + private String socket_url; + private CallSkillBean skill; + private PornCheckBean porn_check; + private PornCheckBeanV2 porn_check_v2; + private VideoGuardBean guard; + private int call_type; + private String nickname; + private String avatar_url; + private int gender; + private String video_url; + private boolean is_follow; + private String user_id; + private int age; + private int from_risk_status; // 自己风险用户 0否1是 + private int to_risk_status;// 对方风险用户 0否1是 + + public String getRoom_id() { + return room_id; + } + + public void setRoom_id(String room_id) { + this.room_id = room_id; + } + + public int getFrom_uid() { + return from_uid; + } + + public void setFrom_uid(int from_uid) { + this.from_uid = from_uid; + } + + public String getFrom_nickname() { + return from_nickname; + } + + public void setFrom_nickname(String from_nickname) { + this.from_nickname = from_nickname; + } + + public String getFrom_avatar() { + return from_avatar; + } + + public void setFrom_avatar(String from_avatar) { + this.from_avatar = from_avatar; + } + + public int getTo_uid() { + return to_uid; + } + + public void setTo_uid(int to_uid) { + this.to_uid = to_uid; + } + + public String getTo_nickname() { + return to_nickname; + } + + public void setTo_nickname(String to_nickname) { + this.to_nickname = to_nickname; + } + + public String getTo_avatar() { + return to_avatar; + } + + public void setTo_avatar(String to_avatar) { + this.to_avatar = to_avatar; + } + + public String getFree_num() { + return free_num; + } + + public void setFree_num(String free_num) { + this.free_num = free_num; + } + + public String getSocket_url() { + return socket_url; + } + + public void setSocket_url(String socket_url) { + this.socket_url = socket_url; + } + + public CallSkillBean getSkill() { + return skill; + } + + public void setSkill(CallSkillBean skill) { + this.skill = skill; + } + + public PornCheckBean getPorn_check() { + return porn_check; + } + + public PornCheckBeanV2 getPorn_checkV2() { + return porn_check_v2; + } + + public void setPorn_checkV2(PornCheckBeanV2 porn_check_v2) { + this.porn_check_v2 = porn_check_v2; + } + + public void setPorn_check(PornCheckBean porn_check) { + this.porn_check = porn_check; + } + + public VideoGuardBean getGuard() { + return guard; + } + + public void setGuard(VideoGuardBean guard) { + this.guard = guard; + } + + public int getCall_type() { + return call_type; + } + + public void setCall_type(int call_type) { + this.call_type = call_type; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar_url() { + return avatar_url; + } + + public void setAvatar_url(String avatar_url) { + this.avatar_url = avatar_url; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public String getVideo_url() { + return video_url; + } + + public void setVideo_url(String video_url) { + this.video_url = video_url; + } + + public boolean isIs_follow() { + return is_follow; + } + + public void setIs_follow(boolean is_follow) { + this.is_follow = is_follow; + } + + public String getUser_id() { + return user_id; + } + + public void setUser_id(String user_id) { + this.user_id = user_id; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getFrom_risk_status() { + return from_risk_status; + } + + public void setFrom_risk_status(int from_risk_status) { + this.from_risk_status = from_risk_status; + } + + public int getTo_risk_status() { + return to_risk_status; + } + + public void setTo_risk_status(int to_risk_status) { + this.to_risk_status = to_risk_status; + } + + @Override + public String toString() { + return "CallBean{" + + "room_id='" + room_id + '\'' + + ", from_uid=" + from_uid + + ", from_nickname='" + from_nickname + '\'' + + ", from_avatar='" + from_avatar + '\'' + + ", to_uid=" + to_uid + + ", to_nickname='" + to_nickname + '\'' + + ", to_avatar='" + to_avatar + '\'' + + ", socket_url='" + socket_url + '\'' + + ", skill=" + skill + + ", free_num=" + free_num + + ", porn_check=" + porn_check + + ", porn_check_v2=" + porn_check_v2 + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/CallSkillBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/CallSkillBean.java new file mode 100644 index 0000000..a48745c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/CallSkillBean.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.model.main; + +public class CallSkillBean { + private int id; + private String name; + private String price; + private String score; + private int service_count; + private int service_time; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getScore() { + return score; + } + + public void setScore(String score) { + this.score = score; + } + + public int getService_count() { + return service_count; + } + + public void setService_count(int service_count) { + this.service_count = service_count; + } + + public int getService_time() { + return service_time; + } + + public void setService_time(int service_time) { + this.service_time = service_time; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/ChannelAnchorBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/ChannelAnchorBean.java new file mode 100644 index 0000000..beaef14 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/ChannelAnchorBean.java @@ -0,0 +1,81 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.ArrayList; +import java.util.List; + +public class ChannelAnchorBean { + private int skill_id; + private String skill_name; + private int type; + private List banner = new ArrayList<>(); + private AnchorListBean list; + private RankBean rank; + private AnchorBean video_list; + + public int getSkill_id() { + return skill_id; + } + + public void setSkill_id(int skill_id) { + this.skill_id = skill_id; + } + + public String getSkill_name() { + return skill_name; + } + + public void setSkill_name(String skill_name) { + this.skill_name = skill_name; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public List getBanner() { + return banner; + } + + public void setBanner(List banner) { + this.banner = banner; + } + + public AnchorListBean getList() { + return list; + } + + public void setList(AnchorListBean list) { + this.list = list; + } + + public RankBean getRank() { + return rank; + } + + public void setRank(RankBean rank) { + this.rank = rank; + } + + public AnchorBean getVideo_list() { + return video_list; + } + + public void setVideo_list(AnchorBean video_list) { + this.video_list = video_list; + } + + @Override + public String toString() { + return "ChannelAnchorBean{" + + "skill_id=" + skill_id + + ", skill_name='" + skill_name + '\'' + + ", type=" + type + + ", banner=" + banner + + ", list=" + list + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/ChannelBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/ChannelBean.java new file mode 100644 index 0000000..5f32bf7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/ChannelBean.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.model.main; + +public class ChannelBean { + private String id; + private String name; + private String icon; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/ChatShootBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/ChatShootBean.java new file mode 100644 index 0000000..e0c03e2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/ChatShootBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.main; + +public class ChatShootBean { + private int is_upload; + + public int getIs_upload() { + return is_upload; + } + + public void setIs_upload(int is_upload) { + this.is_upload = is_upload; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/CityBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/CityBean.java new file mode 100644 index 0000000..0506269 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/CityBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.main; + +public class CityBean { + private String id; + private String name; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/CloseGreetBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/CloseGreetBean.java new file mode 100644 index 0000000..968f24f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/CloseGreetBean.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; + +public class CloseGreetBean implements Serializable { + private int no_greet; + + public int getNo_greet() { + return no_greet; + } + + public void setNo_greet(int no_greet) { + this.no_greet = no_greet; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/ComplaintListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/ComplaintListBean.java new file mode 100644 index 0000000..5f4f721 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/ComplaintListBean.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.model.main; + +public class ComplaintListBean { + private int id; + private String name; + private boolean isChecked; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isChecked() { + return isChecked; + } + + public void setChecked(boolean checked) { + isChecked = checked; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/ConfigBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/ConfigBean.java new file mode 100644 index 0000000..f8411df --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/ConfigBean.java @@ -0,0 +1,130 @@ +package com.fengliyan.tianlesue.model.main; + +public class ConfigBean { + private String sysId; + private String servId; + private String servIds; + private String image_server; + private String default_pay_type;//"1":"支付宝","2":"微信" + private String resource_version;//图片资源版本号 + private String wechat_switch; //微信功能的开关:1 = 开、0 = 关 + private int send_video_porn_img_num;//发送视频鉴黄截帧最大数量 + private int send_video_porn_interval;//视频鉴黄截帧间隔 + private int chat_real_name_switch;// 发消息和视频是否要先实名认证 0.否 1.是 + private int dynamic_real_name_switch; // 发动态是否要先实名认证 0.否 1.是 + private int risk_face_status;//实名人脸状态开关:1 = 开、0 = 关 + private int turntable_switch;//转盘抽奖活动入口:1 = 显示、0 = 不显示 + private int turntable_coupon_switch;//转盘卡券显示:1 = 显示、0 = 不显示 + + public String getSysId() { + return sysId; + } + + public void setSysId(String sysId) { + this.sysId = sysId; + } + + public String getServId() { + return servId; + } + + public void setServId(String servId) { + this.servId = servId; + } + + public String getServIds() { + return servIds; + } + + public void setServIds(String servIds) { + this.servIds = servIds; + } + + public String getImage_server() { + return image_server; + } + + public void setImage_server(String image_server) { + this.image_server = image_server; + } + + public String getDefault_pay_type() { + return default_pay_type; + } + + public void setDefault_pay_type(String default_pay_type) { + this.default_pay_type = default_pay_type; + } + + public String getResource_version() { + return resource_version; + } + + public void setResource_version(String resource_version) { + this.resource_version = resource_version; + } + + public String getWechat_switch() { + return wechat_switch; + } + + public void setWechat_switch(String wechat_switch) { + this.wechat_switch = wechat_switch; + } + + public int getSend_video_porn_img_num() { + return send_video_porn_img_num; + } + + public void setSend_video_porn_img_num(int send_video_porn_img_num) { + this.send_video_porn_img_num = send_video_porn_img_num; + } + + public int getSend_video_porn_interval() { + return send_video_porn_interval; + } + + public void setSend_video_porn_interval(int send_video_porn_interval) { + this.send_video_porn_interval = send_video_porn_interval; + } + + public int getChat_real_name_switch() { + return chat_real_name_switch; + } + + public void setChat_real_name_switch(int chat_real_name_switch) { + this.chat_real_name_switch = chat_real_name_switch; + } + + public int getDynamic_real_name_switch() { + return dynamic_real_name_switch; + } + + public void setDynamic_real_name_switch(int dynamic_real_name_switch) { + this.dynamic_real_name_switch = dynamic_real_name_switch; + } + + public int getRisk_face_status() { + return risk_face_status; + } + + public void setRisk_face_status(int risk_face_status) { + this.risk_face_status = risk_face_status; + } + + public int getTurntable_switch() { + return turntable_switch; + } + + public void setTurntable_switch(int turntable_switch) { + this.turntable_switch = turntable_switch; + } + + public int getTurntable_coupon_switch() { + return turntable_coupon_switch; + } + + public void setTurntable_coupon_switch(int turntable_coupon_switch) { + this.turntable_coupon_switch = turntable_coupon_switch; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/ContactBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/ContactBean.java new file mode 100644 index 0000000..97d9164 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/ContactBean.java @@ -0,0 +1,155 @@ +package com.fengliyan.tianlesue.model.main; + +import android.text.TextUtils; + +public class ContactBean { + + + /** + * if_forbidden : 1 + * wechat : {"status":2,"content":"","price":0,"giftCoin":0,"wechat_price":null} + * qq : {"status":2,"content":"","price":0} + */ + + private int if_forbidden; + private WechatBean wechat; + private QqBean qq; + + public int getIf_forbidden() { + return if_forbidden; + } + + public void setIf_forbidden(int if_forbidden) { + this.if_forbidden = if_forbidden; + } + + public WechatBean getWechat() { + return wechat; + } + + public void setWechat(WechatBean wechat) { + this.wechat = wechat; + } + + public QqBean getQq() { + return qq; + } + + public void setQq(QqBean qq) { + this.qq = qq; + } + + public static class WechatBean { + /** + * status : 2 + * content : + * price : 0 + * giftCoin : 0 + * wechat_price : null + */ + + private int status;//1展示微信号 2不展示微信号 + private String content; + private int price; + private int giftCoin; + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getIf_forbidden() { + return if_forbidden; + } + + public void setIf_forbidden(int if_forbidden) { + this.if_forbidden = if_forbidden; + } + + private int gender; + private int if_forbidden; + private String wechat_price; + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public int getGiftCoin() { + return giftCoin; + } + + public void setGiftCoin(int giftCoin) { + this.giftCoin = giftCoin; + } + + public String getWechat_price() { + if (TextUtils.isEmpty(wechat_price)) { + return String.valueOf(price); + } + return wechat_price; + } + + public void setWechat_price(String wechat_price) { + this.wechat_price = wechat_price; + } + } + + public static class QqBean { + /** + * status : 2 + * content : + * price : 0 + */ + + private int status; + private String content; + private int price; + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/DialogAdBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/DialogAdBean.java new file mode 100644 index 0000000..b1fecd8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/DialogAdBean.java @@ -0,0 +1,69 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by ying on 2020/4/17. + * 广告弹窗 + */ +public class DialogAdBean { + + + /** + * advert : {"image":"images/banner/2b21357e0adb99f816782bbad2e81fdd.png","link_type":2,"link_url":"http://www.ncaicai.tech/index/about/recharge","status":1} + */ + + private AdvertBean advert; + + public AdvertBean getAdvert() { + return advert; + } + + public void setAdvert(AdvertBean advert) { + this.advert = advert; + } + + public static class AdvertBean { + /** + * image : images/banner/2b21357e0adb99f816782bbad2e81fdd.png + * link_type : 2 + * link_url : http://www.ncaicai.tech/index/about/recharge + * status : 1 + */ + + private String image; + private int link_type; + private String link_url; + private int status; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public int getLink_type() { + return link_type; + } + + public void setLink_type(int link_type) { + this.link_type = link_type; + } + + public String getLink_url() { + return link_url; + } + + public void setLink_url(String link_url) { + this.link_url = link_url; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/FollowResultBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/FollowResultBean.java new file mode 100644 index 0000000..46b64d4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/FollowResultBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.main; + +public class FollowResultBean { + private String action; + private int user_id; + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/FreeVideoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/FreeVideoBean.java new file mode 100644 index 0000000..8aecb3e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/FreeVideoBean.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.List; + +/** + * ying 2020/12/16 + * Describe : + */ + +public class FreeVideoBean { + + /** + * show_status : 1 + * anchor_list : [{"user_id":187116,"avatar":"uploads/album/202010/30/e64e223125e5444496991db0d4499475_.pic.jpg"},{"user_id":135001,"avatar":"uploads/album/202010/02/c5ecf8d56f82c66deaf6b07ddcfc8617_.pic.jpg"},{"user_id":219227,"avatar":"uploads/album/202012/10/353813f2b9b70fc0fba229d54cfb1c78_.pic.jpg"},{"user_id":191497,"avatar":"uploads/album/202011/16/5cee64864fea871972415742168c3a4f_.pic.jpg"},{"user_id":156739,"avatar":"uploads/album/202010/07/b1ad4f38fb05dbbf7c4d788cc8d1f52a_.pic.jpg"},{"user_id":213582,"avatar":"uploads/album/202012/03/63428343b2694b4acdb3e820fd03ed96_.pic.jpg"},{"user_id":214306,"avatar":"uploads/album/202011/20/5b6dc00a08f909f6e70393152f177104_.pic.jpg"},{"user_id":201340,"avatar":"uploads/album/202010/14/2d005d7479c351c9cf384e6516a82eb7_.pic.jpg"},{"user_id":186480,"avatar":"uploads/album/202011/19/ab26202f1ffdcd718e1c76be11b201bb_.pic.jpg"},{"user_id":127496,"avatar":"uploads/album/202007/13/204fbeebae8fd94a540e5df0c75ed5b7_.pic.jpg"},{"user_id":200227,"avatar":"uploads/album/202012/03/4213184b76e199739749661c800a3d45_.pic.jpg"},{"user_id":193388,"avatar":"uploads/album/202010/26/53fce8af197c2404e523a371954e673d_.pic.jpg"},{"user_id":192243,"avatar":"uploads/album/202012/12/a024ced9d4da3728a791d9ca410e02f5_.pic.jpg"},{"user_id":211411,"avatar":"uploads/album/202011/14/401b294fd875acbabd0e378167e545ff_.pic.jpg"},{"user_id":198360,"avatar":"uploads/album/202011/11/0fbc7c411306431770784f65900c166a_.pic.jpg"},{"user_id":90218,"avatar":"uploads/album/202011/15/93266675cff005cc3938d598662769f1_.pic.jpg"},{"user_id":137351,"avatar":"uploads/album/202011/07/7610f3d7cd9ce6fbd2e042ccdb1c109b_.pic.jpg"},{"user_id":207442,"avatar":"uploads/album/202012/09/d032186621f6288dc7f755bc403365c7_.pic.jpg"},{"user_id":212011,"avatar":"uploads/album/202011/27/924ecdf557bf6726615edfd88d485cf0_.pic.jpg"},{"user_id":199515,"avatar":"uploads/album/202009/23/78d7acf6fe64a247faaa6fdabebef07a_.pic.jpg"},{"user_id":188934,"avatar":"uploads/album/202011/20/4597d384b5ce1eab99a2a4ea8463e8b4_.pic.jpg"},{"user_id":102587,"avatar":"uploads/album/202011/24/d6d37ebf93542e9e6e9a7b86c4fa07d2_.pic.jpg"},{"user_id":210104,"avatar":"uploads/album/202012/09/df5de39e4e5167377f5f6b3c667be244_.pic.jpg"},{"user_id":104249,"avatar":"uploads/album/202011/10/8dd08f2573a6b6e2e865d4420efeca1b_.pic.jpg"},{"user_id":70958,"avatar":"uploads/album/202002/13/57d70fc09a19b2ed09c81104c26aa5e4_.pic.jpg"},{"user_id":200298,"avatar":"uploads/album/202012/16/d1406c408fcbf3bcde21e382aca54e45_.pic.jpg"},{"user_id":198747,"avatar":"uploads/album/202011/26/b93572afcd8e8915c51eaa313d6e4199_.pic.jpg"},{"user_id":172371,"avatar":"uploads/album/202006/13/5878f759691ca3311ae6f33633f736f0_.pic.jpg"},{"user_id":202029,"avatar":"uploads/album/202012/03/a854480bad1dcf24190fbfb9de4a30a5_.pic.jpg"},{"user_id":1610,"avatar":"uploads/album/202005/22/ca05e08e379d8a057e00e54a610811e1_.pic.jpg"}] + */ + + public int show_status; + public List anchor_list; + + public static class AnchorListBean { + /** + * user_id : 187116 + * avatar : uploads/album/202010/30/e64e223125e5444496991db0d4499475_.pic.jpg + */ + + public int user_id; + public String avatar; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftBean.java new file mode 100644 index 0000000..c3eb6ab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.main; + +public class GiftBean { + private int id; + private String img; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftReceivedBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftReceivedBean.java new file mode 100644 index 0000000..e41f47f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftReceivedBean.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.ArrayList; +import java.util.List; + +public class GiftReceivedBean { + private int userid; + private String nickname; + private List list = new ArrayList<>(); + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftReceivedItemBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftReceivedItemBean.java new file mode 100644 index 0000000..8e92ebc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GiftReceivedItemBean.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.model.main; + +public class GiftReceivedItemBean { + private int id; + private String name; + private String img; + private String total; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public String getTotal() { + return total; + } + + public void setTotal(String total) { + this.total = total; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GlobalConfigBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GlobalConfigBean.java new file mode 100644 index 0000000..dfdf8bc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GlobalConfigBean.java @@ -0,0 +1,178 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class GlobalConfigBean { + private ConfigBean config; + private VersionBean version; + private List new_user_video_card; + private AgoraInfoBean agora; + private GreetBean greet; + private ProfileBean profile; + + public ConfigBean getConfig() { + return config; + } + + public void setConfig(ConfigBean config) { + this.config = config; + } + + public VersionBean getVersion() { + return version; + } + + public ProfileBean getProfile() { + return profile; + } + + public void setProfile(ProfileBean profile) { + this.profile = profile; + } + + public void setVersion(VersionBean version) { + this.version = version; + } + + public List getNew_user_video_card() { + return new_user_video_card; + } + + public void setNew_user_video_card(List new_user_video_card) { + this.new_user_video_card = new_user_video_card; + } + + public AgoraInfoBean getAgora() { + return agora; + } + + public void setAgora(AgoraInfoBean agora) { + this.agora = agora; + } + + public GreetBean getGreet() { + return greet; + } + + public void setGreet(GreetBean greet) { + this.greet = greet; + } + + public class AgoraInfoBean implements Serializable { + private static final long serialVersionUID = 4377059052110639528L; + private String appid; + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + } + + public class GreetBean implements Serializable { + private int send_user_total; + private int greet_gap_hour; + private int greet_day_total; + + public int getSend_user_total() { + return send_user_total; + } + + public void setSend_user_total(int send_user_total) { + this.send_user_total = send_user_total; + } + + public int getGreet_gap_hour() { + return greet_gap_hour; + } + + public void setGreet_gap_hour(int greet_gap_hour) { + this.greet_gap_hour = greet_gap_hour; + } + + public int getGreet_day_total() { + return greet_day_total; + } + + public void setGreet_day_total(int greet_day_total) { + this.greet_day_total = greet_day_total; + } + } + + public class ProfileBean { + private TagListBean tag_list; + private List job_list; + + public TagListBean getTag_list() { + return tag_list; + } + + public void setTag_list(TagListBean tag_list) { + this.tag_list = tag_list; + } + + public List getJob_list() { + return job_list; + } + + public void setJob_list(List job_list) { + this.job_list = job_list; + } + + public class TagListBean { + private ArrayList status; + private ArrayList character; + private ArrayList hobby; + + public ArrayList getStatus() { + return status; + } + + public void setStatus(ArrayList status) { + this.status = status; + } + + public ArrayList getCharacter() { + return character; + } + + public void setCharacter(ArrayList character) { + this.character = character; + } + + public ArrayList getHobby() { + return hobby; + } + + public void setHobby(ArrayList hobby) { + this.hobby = hobby; + } + } + + public class JobListBean { + private String name; + private ArrayList menu; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ArrayList getMenu() { + return menu; + } + + public void setMenu(ArrayList menu) { + this.menu = menu; + } + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GroupCallBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GroupCallBean.java new file mode 100644 index 0000000..471392e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GroupCallBean.java @@ -0,0 +1,62 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.List; + +/** + * Created by zhangbin on 2019/1/28. + */ + +public class GroupCallBean { + /** + * "count":10, + "tonum":20, + "status":"1" + */ + + private List list; + private int count; + private int tonum; + private boolean status; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public int getTonum() { + return tonum; + } + + public void setTonum(int tonum) { + this.tonum = tonum; + } + + public boolean isStatus() { + return status; + } + + public void setStatus(boolean status) { + this.status = status; + } + + @Override + public String toString() { + return "GroupCallBean{" + + "list=" + list + + ", count=" + count + + ", tonum=" + tonum + + ", status='" + status + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GroupCallListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GroupCallListBean.java new file mode 100644 index 0000000..f3351f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GroupCallListBean.java @@ -0,0 +1,84 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by zhangbin on 2019/1/28. + */ + +public class GroupCallListBean { + + /** + "id":3, + "user_id":368, + "type":0, + "title":"hello1", + "status":0, + "create_time":1547725661 + */ + + private int id; + private int user_id; + private int type; + private String title; + private int status; + private long create_time; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public long getCreate_time() { + return create_time; + } + + public void setCreate_time(long create_time) { + this.create_time = create_time; + } + + @Override + public String toString() { + return "GroupCallListBean{" + + "id=" + id + + ", user_id=" + user_id + + ", type=" + type + + ", title='" + title + '\'' + + ", status=" + status + + ", create_time=" + create_time + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardListBean.java new file mode 100644 index 0000000..9dc82eb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardListBean.java @@ -0,0 +1,20 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class GuardListBean { + + private List list = new ArrayList<>(); + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardOtherBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardOtherBean.java new file mode 100644 index 0000000..75c5e9f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardOtherBean.java @@ -0,0 +1,92 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/12/16. + */ +public class GuardOtherBean { + + private List list = new ArrayList<>(); + private String nickname; + private String avatar; + private int diff_num; //距离上一名 + private int intimate_num; //亲密值 + private int guard_price; + private int first_diff_num; //距离上一名 + private int guard_symbol_total; //守护符的个数 + private int guard_person_total; //守护的人数 + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getDiff_num() { + return diff_num; + } + + public void setDiff_num(int diff_num) { + this.diff_num = diff_num; + } + + public int getIntimate_num() { + return intimate_num; + } + + public void setIntimate_num(int intimate_num) { + this.intimate_num = intimate_num; + } + + public int getFirst_diff_num() { + return first_diff_num; + } + + public void setFirst_diff_num(int first_diff_num) { + this.first_diff_num = first_diff_num; + } + + public int getGuard_price() { + return guard_price; + } + + public void setGuard_price(int guard_price) { + this.guard_price = guard_price; + } + + public int getGuard_person_total() { + return guard_person_total; + } + + public void setGuard_person_total(int guard_person_total) { + this.guard_person_total = guard_person_total; + } + + public int getGuard_symbol_total() { + return guard_symbol_total; + } + + public void setGuard_symbol_total(int guard_symbol_total) { + this.guard_symbol_total = guard_symbol_total; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardRankBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardRankBean.java new file mode 100644 index 0000000..1bca10c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/GuardRankBean.java @@ -0,0 +1,54 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by zhangbin on 2019/12/17. + */ +public class GuardRankBean { + + private int no; + private String avatar; + private String nickname; + private int totalMoney; + private int user_id; + + public int getNo() { + return no; + } + + public void setNo(int no) { + this.no = no; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getTotalMoney() { + return totalMoney; + } + + public void setTotalMoney(int totalMoney) { + this.totalMoney = totalMoney; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/InviteCodeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/InviteCodeBean.java new file mode 100644 index 0000000..7c9b8fa --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/InviteCodeBean.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; + +public class InviteCodeBean implements Serializable { + private String invite_code; + + public String getInvite_code() { + return invite_code; + } + + public void setInvite_code(String invite_code) { + this.invite_code = invite_code; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/IsKidModelBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/IsKidModelBean.java new file mode 100644 index 0000000..db7dfa8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/IsKidModelBean.java @@ -0,0 +1,17 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by zhangbin on 2019/12/23. + */ +public class IsKidModelBean { + + private int is_open; + + public int getIs_open() { + return is_open; + } + + public void setIs_open(int is_open) { + this.is_open = is_open; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/MainBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainBean.java new file mode 100644 index 0000000..d16e96f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainBean.java @@ -0,0 +1,52 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.ArrayList; +import java.util.List; + +public class MainBean { + private String keyword; + private List skill = new ArrayList<>(); + private List banner = new ArrayList<>(); + private List list = new ArrayList<>(); + private RankBean rank; + + public List getSkill() { + return skill; + } + + public void setSkill(List skill) { + this.skill = skill; + } + + public List getBanner() { + return banner; + } + + public void setBanner(List banner) { + this.banner = banner; + } + + public String getKeyword() { + return keyword; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public RankBean getRank() { + return rank; + } + + public void setRank(RankBean rank) { + this.rank = rank; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageAnchorBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageAnchorBean.java new file mode 100644 index 0000000..23e9478 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageAnchorBean.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.model.main; + +public class MainPageAnchorBean { + private int open_video_status; + private int open_voice_status; + private int video_status; + + public int getOpen_video_status() { + return open_video_status; + } + + public void setOpen_video_status(int open_video_status) { + this.open_video_status = open_video_status; + } + + public int getOpen_voice_status() { + return open_voice_status; + } + + public void setOpen_voice_status(int open_voice_status) { + this.open_voice_status = open_voice_status; + } + + public int getVideo_status() { + return video_status; + } + + public void setVideo_status(int video_status) { + this.video_status = video_status; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageBean.java new file mode 100644 index 0000000..4eaba70 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageBean.java @@ -0,0 +1,173 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.List; + +public class MainPageBean { + private int is_anchor; + private MainPageAnchorBean anchor; + private List album; + private MainPageInfoBean info; + private List skill; + private List dynamic; + private List gifts; + private GuardOtherBean guard; + private int private_letter; + private ContactBean contact; + private int video_status; + private String video_url; + private String video_cover_url; + private String can_free_call;//是否有视频卡可以免费拨打:1=是、0=否 + + // 打招呼对象数组,如果用户发送的了此处的招呼用户,发送消息时,云信自定义字段需带上 is_greet = 1 + private List list; + // 是否显示+号:1 = 是、0 = 否 + private String show_add; + // 双方是否互动过建联:1 = 是、0 = 否 + private String is_interactive; + // 是否给对方发过消息:1 = 是、0 = 否 + private String is_sent; + + public ContactBean getContact() { + return contact; + } + + public void setContact(ContactBean contact) { + this.contact = contact; + } + + public int getPrivate_letter() { + return private_letter; + } + + public void setPrivate_letter(int private_letter) { + this.private_letter = private_letter; + } + + public int getIs_anchor() { + return is_anchor; + } + + public void setIs_anchor(int is_anchor) { + this.is_anchor = is_anchor; + } + + public MainPageAnchorBean getAnchor() { + return anchor; + } + + public void setAnchor(MainPageAnchorBean anchor) { + this.anchor = anchor; + } + + public List getAlbum() { + return album; + } + + public void setAlbum(List album) { + this.album = album; + } + + public MainPageInfoBean getInfo() { + return info; + } + + public void setInfo(MainPageInfoBean info) { + this.info = info; + } + + public List getSkill() { + return skill; + } + + public void setSkill(List skill) { + this.skill = skill; + } + + public List getDynamic() { + return dynamic; + } + + public void setDynamic(List dynamic) { + this.dynamic = dynamic; + } + + public List getGifts() { + return gifts; + } + + public void setGifts(List gifts) { + this.gifts = gifts; + } + + public GuardOtherBean getGuard() { + return guard; + } + + public void setGuard(GuardOtherBean guard) { + this.guard = guard; + } + + public int getVideo_status() { + return video_status; + } + + public void setVideo_status(int video_status) { + this.video_status = video_status; + } + + public String getVideo_url() { + return video_url; + } + + public void setVideo_url(String video_url) { + this.video_url = video_url; + } + + public String getVideo_cover_url() { + return video_cover_url; + } + + public void setVideo_cover_url(String video_cover_url) { + this.video_cover_url = video_cover_url; + } + + public String getCan_free_call() { + return can_free_call; + } + + public void setCan_free_call(String can_free_call) { + this.can_free_call = can_free_call; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public String getShow_add() { + return show_add; + } + + public void setShow_add(String show_add) { + this.show_add = show_add; + } + + public String getIs_interactive() { + return is_interactive; + } + + public void setIs_interactive(String is_interactive) { + this.is_interactive = is_interactive; + } + + public String getIs_sent() { + return is_sent; + } + + public void setIs_sent(String is_sent) { + this.is_sent = is_sent; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageInfoBean.java new file mode 100644 index 0000000..094a7a2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageInfoBean.java @@ -0,0 +1,206 @@ +package com.fengliyan.tianlesue.model.main; + +import com.fengliyan.tianlesue.model.settings.UserFrameBean; + +public class MainPageInfoBean { + private int userid; + private String nickname; + private int age; + private int gender; + private String avatar; + private String city; + private String update_time; + private int fans_count; + private int follow_count; + private int visitor_count; + private int is_follow; + private int vip = 2; + private String usercode; + private int is_black; + private String ip_province; + private String camera_status;//0 未认证 1 已认证 + private String signature; + private int online_status;//1.在线,2.离线 + private UserFrameBean user_frame; + private int anchor_tag; + + public int getMobile_mark() { + return mobile_mark; + } + + public void setMobile_mark(int mobile_mark) { + this.mobile_mark = mobile_mark; + } + + private int mobile_mark; + + public int getMark() { + return mark; + } + + public void setMark(int mark) { + this.mark = mark; + } + + private int mark; + + public String getUpdate_time() { + return update_time; + } + + public void setUpdate_time(String update_time) { + this.update_time = update_time; + } + + public int getIs_black() { + return is_black; + } + + public void setIs_black(int is_black) { + this.is_black = is_black; + } + + public int getUserId() { + return userid; + } + + public void setUserId(int userId) { + this.userid = userId; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public int getFans_count() { + return fans_count; + } + + public void setFans_count(int fans_count) { + this.fans_count = fans_count; + } + + public int getFollow_count() { + return follow_count; + } + + public void setFollow_count(int follow_count) { + this.follow_count = follow_count; + } + + public int getVisitor_count() { + return visitor_count; + } + + public void setVisitor_count(int visitor_count) { + this.visitor_count = visitor_count; + } + + public int getIs_follow() { + return is_follow; + } + + public void setIs_follow(int is_follow) { + this.is_follow = is_follow; + } + + public int getVip() { + return vip; + } + + public void setVip(int vip) { + this.vip = vip; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getIp_province() { + return ip_province; + } + + public void setIp_province(String ip_province) { + this.ip_province = ip_province; + } + + public String getCamera_status() { + return camera_status; + } + + public void setCamera_status(String camera_status) { + this.camera_status = camera_status; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public int getOnline_status() { + return online_status; + } + + public void setOnline_status(int online_status) { + this.online_status = online_status; + } + + public UserFrameBean getUser_frame() { + return user_frame; + } + + public void setUser_frame(UserFrameBean user_frame) { + this.user_frame = user_frame; + } + + public int getAnchor_tag() { + return anchor_tag; + } + + public void setAnchor_tag(int anchor_tag) { + this.anchor_tag = anchor_tag; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageSwitchSwerviceNumBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageSwitchSwerviceNumBean.java new file mode 100644 index 0000000..b4f1a43 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/MainPageSwitchSwerviceNumBean.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.model.main; + +public class MainPageSwitchSwerviceNumBean { + + /** + * hide_service_num : 1 + */ + + private int hide_service_num; + + public int getHide_service_num() { + return hide_service_num; + } + + public void setHide_service_num(int hide_service_num) { + this.hide_service_num = hide_service_num; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/NewUserVideoCardBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/NewUserVideoCardBean.java new file mode 100644 index 0000000..ca11c6c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/NewUserVideoCardBean.java @@ -0,0 +1,44 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; + +public class NewUserVideoCardBean implements Serializable { + private static final long serialVersionUID = -5538821414458094442L; + + private String title; + private String number; + private String button_text; + private String button_status; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public String getButton_text() { + return button_text; + } + + public void setButton_text(String button_text) { + this.button_text = button_text; + } + + public String getButton_status() { + return button_status; + } + + public void setButton_status(String button_status) { + this.button_status = button_status; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/PornCheckBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/PornCheckBean.java new file mode 100644 index 0000000..d8eacdc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/PornCheckBean.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by zhangbin on 2019/10/26. + */ + +public class PornCheckBean { + + private int is_open; + private int interval; + private int period; + + public int getIs_open() { + return is_open; + } + + public void setIs_open(int is_open) { + this.is_open = is_open; + } + + public int getInterval() { + return interval; + } + + public void setInterval(int interval) { + this.interval = interval; + } + + public int getPeriod() { + return period; + } + + public void setPeriod(int period) { + this.period = period; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/PornCheckBeanV2.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/PornCheckBeanV2.java new file mode 100644 index 0000000..e0d3143 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/PornCheckBeanV2.java @@ -0,0 +1,73 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; +import java.util.List; + +public class PornCheckBeanV2 implements Serializable { + private int is_open; + private int interval; + private int check_from_user; + private List period_array; + private int show_mask_second;//涉黄开启遮罩后,多少秒后关闭 + + public int getIs_open() { + return is_open; + } + + public void setIs_open(int is_open) { + this.is_open = is_open; + } + + public int getInterval() { + return interval; + } + + public void setInterval(int interval) { + this.interval = interval; + } + + public List getPeriodArray() { + return period_array; + } + + public void setPeriodArray(List period_array) { + this.period_array = period_array; + } + + public int getCheck_from_user() { + return check_from_user; + } + + public void setCheck_from_user(int check_from_user) { + this.check_from_user = check_from_user; + } + + public int getShow_mask_second() { + return show_mask_second; + } + + public void setShow_mask_second(int show_mask_second) { + this.show_mask_second = show_mask_second; + } + + public static class PornCheckV2 implements Serializable { + private long start; + private long end; + + public long getStart() { + return start; + } + + public void setStart(long start) { + this.start = start; + } + + public long getEnd() { + return end; + } + + public void setEnd(long end) { + this.end = end; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/PrizeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/PrizeBean.java new file mode 100644 index 0000000..708f7fd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/PrizeBean.java @@ -0,0 +1,119 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; +import java.util.List; + +public class PrizeBean implements Serializable { + + private List prize_detail; + private int surplus_num;//剩余可抽奖次数 + private String bg; + private String prize_id;//奖品ID + private int prize_type;//奖品类型(奖品类型0=谢谢参与1=金币2=免费视频卡3=免费聊天卡4超级会员) + private String prize_name;//奖品名称 + private String prize_url;//奖品图片地址 + private String rule_url; + private String activity_url; + + public String getActivity_url() { + return activity_url; + } + + public void setActivity_url(String activity_url) { + this.activity_url = activity_url; + } + + public String getRule_url() { + return rule_url; + } + + public void setRule_url(String rule_url) { + this.rule_url = rule_url; + } + + public List getPrize_detail() { + return prize_detail; + } + + public void setPrize_detail(List prize_detail) { + this.prize_detail = prize_detail; + } + + public int getSurplus_num() { + return surplus_num; + } + + public void setSurplus_num(int surplus_num) { + this.surplus_num = surplus_num; + } + + public String getBg() { + return bg; + } + + public void setBg(String bg) { + this.bg = bg; + } + + public String getPrize_id() { + return prize_id; + } + + public void setPrize_id(String prize_id) { + this.prize_id = prize_id; + } + + public String getPrize_name() { + return prize_name; + } + + public void setPrize_name(String prize_name) { + this.prize_name = prize_name; + } + + public String getPrize_url() { + return prize_url; + } + + public void setPrize_url(String prize_url) { + this.prize_url = prize_url; + } + + public int getPrize_type() { + return prize_type; + } + + public void setPrize_type(int prize_type) { + this.prize_type = prize_type; + } + + public class Prize { + private String prize_id; + private String prize_name; + private String prize_url; + + public String getPrize_id() { + return prize_id; + } + + public void setPrize_id(String prize_id) { + this.prize_id = prize_id; + } + + public String getPrize_name() { + return prize_name; + } + + public void setPrize_name(String prize_name) { + this.prize_name = prize_name; + } + + public String getPrize_url() { + return prize_url; + } + + public void setPrize_url(String prize_url) { + this.prize_url = prize_url; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/RankBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/RankBean.java new file mode 100644 index 0000000..00f67ec --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/RankBean.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.List; + +public class RankBean { + private List love_rank; + private List wealth_rank; + + public List getLove_rank() { + return love_rank; + } + + public void setLove_rank(List love_rank) { + this.love_rank = love_rank; + } + + public List getWealth_rank() { + return wealth_rank; + } + + public void setWealth_rank(List wealth_rank) { + this.wealth_rank = wealth_rank; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/RankUserBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/RankUserBean.java new file mode 100644 index 0000000..cdb4a57 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/RankUserBean.java @@ -0,0 +1,50 @@ +package com.fengliyan.tianlesue.model.main; + +public class RankUserBean { + private int no; + + private int userid; + private String usercode; + private String nickname; + private String avatar; + + public int getNo() { + return no; + } + + public void setNo(int no) { + this.no = no; + } + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/RedEnvelopesBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/RedEnvelopesBean.java new file mode 100644 index 0000000..281c8e8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/RedEnvelopesBean.java @@ -0,0 +1,46 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.List; + +/** + * ying 2021/1/28 + * Describe :红包详情 + */ + +public class RedEnvelopesBean { + + /** + * rpData : [{"reward":42,"create_time":"16小时前","user_id":"1041","usercode":"1001041","nickname":"用户1001041","avatar":"images/avatar/woman.png"},{"reward":12,"create_time":"16分钟前","user_id":"38","usercode":"1000038","nickname":"38师妹","avatar":"images/avatar/woman.png"},{"reward":2,"create_time":"18小时前","user_id":"23","usercode":"1000023","nickname":"23师兄","avatar":"images/avatar/man.png"}] + * meReward : 12 + * page : 1 + * total : 3 + * totalPage : 1 + * tips : 10个红包,共计100金币 + */ + + public String meReward; + public int page; + public int total; + public int totalPage; + public String tips; + public List rpData; + + public static class RpDataBean { + /** + * reward : 42 + * create_time : 16小时前 + * user_id : 1041 + * usercode : 1001041 + * nickname : 用户1001041 + * avatar : images/avatar/woman.png + */ + + public int bestLuck; + public String reward; + public String create_time; + public String user_id; + public String usercode; + public String nickname; + public String avatar; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/RedEnvlopesRedwarsBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/RedEnvlopesRedwarsBean.java new file mode 100644 index 0000000..aa88103 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/RedEnvlopesRedwarsBean.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * ying 2021/2/2 + * Describe : + */ + +public class RedEnvlopesRedwarsBean { + + /** + * status : 1 + */ + + public int status; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/RoomInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/RoomInfoBean.java new file mode 100644 index 0000000..be3f52f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/RoomInfoBean.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.model.main; + +public class RoomInfoBean { + private int room_id; + private int from_uid; + private String from_nickname; + private String from_avatar; + private int to_uid; + private String to_nickname; + private String to_avatar; + private String socket_url; + private SkillBean skill; + + public int getRoom_id() { + return room_id; + } + + public void setRoom_id(int room_id) { + this.room_id = room_id; + } + + public int getFrom_uid() { + return from_uid; + } + + public void setFrom_uid(int from_uid) { + this.from_uid = from_uid; + } + + public String getFrom_nickname() { + return from_nickname; + } + + public void setFrom_nickname(String from_nickname) { + this.from_nickname = from_nickname; + } + + public String getFrom_avatar() { + return from_avatar; + } + + public void setFrom_avatar(String from_avatar) { + this.from_avatar = from_avatar; + } + + public int getTo_uid() { + return to_uid; + } + + public void setTo_uid(int to_uid) { + this.to_uid = to_uid; + } + + public String getTo_nickname() { + return to_nickname; + } + + public void setTo_nickname(String to_nickname) { + this.to_nickname = to_nickname; + } + + public String getTo_avatar() { + return to_avatar; + } + + public void setTo_avatar(String to_avatar) { + this.to_avatar = to_avatar; + } + + public String getSocket_url() { + return socket_url; + } + + public void setSocket_url(String socket_url) { + this.socket_url = socket_url; + } + + public SkillBean getSkill() { + return skill; + } + + public void setSkill(SkillBean skill) { + this.skill = skill; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/SearchBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/SearchBean.java new file mode 100644 index 0000000..98d542a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/SearchBean.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.model.main; + +public class SearchBean { + private int userid; + private String usercode; + private String nickname; + private String avatar; + private int gender; + private int age; + private String city; + private String dateline; + private int vip = 2; + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getDateline() { + return dateline; + } + + public void setDateline(String dateline) { + this.dateline = dateline; + } + + public int getVip() { + return vip; + } + + public void setVip(int vip) { + this.vip = vip; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/SearchListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/SearchListBean.java new file mode 100644 index 0000000..67c20d8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/SearchListBean.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.model.main; + +import java.util.ArrayList; +import java.util.List; + +public class SearchListBean { + private int total; + private int page; + private List list = new ArrayList<>(); + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/SkillAnchorBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/SkillAnchorBean.java new file mode 100644 index 0000000..55bc822 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/SkillAnchorBean.java @@ -0,0 +1,60 @@ +package com.fengliyan.tianlesue.model.main; + +public class SkillAnchorBean { + private int id; + private String name; + private String icon; + private int status; + private int is_add; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public int getIs_add() { + return is_add; + } + + public void setIs_add(int is_add) { + this.is_add = is_add; + } + + @Override + public String toString() { + return "SkillAnchorBean{" + + "id=" + id + + ", name='" + name + '\'' + + ", icon='" + icon + '\'' + + ", status=" + status + + ", is_add=" + is_add + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/SkillBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/SkillBean.java new file mode 100644 index 0000000..c390298 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/SkillBean.java @@ -0,0 +1,76 @@ +package com.fengliyan.tianlesue.model.main; + +public class SkillBean { + private int id; + private String name; + private String icon; + private String price; + private String voice_price; + private String score; + private int service_count; + private int service_time; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getVoice_price() { + return voice_price; + } + + public void setVoice_price(String voice_price) { + this.voice_price = voice_price; + } + + public String getScore() { + return score; + } + + public void setScore(String score) { + this.score = score; + } + + public int getService_count() { + return service_count; + } + + public void setService_count(int service_count) { + this.service_count = service_count; + } + + public int getService_time() { + return service_time; + } + + public void setService_time(int service_time) { + this.service_time = service_time; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/SpeedInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/SpeedInfoBean.java new file mode 100644 index 0000000..c2c0eb2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/SpeedInfoBean.java @@ -0,0 +1,176 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; +import java.util.List; + +public class SpeedInfoBean implements Serializable { + private static final long serialVersionUID = -7848467141509460315L; + private String price;//定价(x金币/每分钟) + private String income_second;//通话收益必须达到的秒数 + private List speed_list;//速配成功列表 + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getIncome_second() { + return income_second; + } + + public void setIncome_second(String income_second) { + this.income_second = income_second; + } + + public List getSpeed_list() { + return speed_list; + } + + public void setSpeed_list(List speed_list) { + this.speed_list = speed_list; + } + + public class SpeedListBean implements Serializable { + + private static final long serialVersionUID = -7341257319108794192L; + private String call_amount;//收益金币数 + private String pay_avatar;//支付方头像 + private String pay_nickname;//支付方昵称 + private String income_avatar;//收益方头像 + private String income_nickname;//收益方昵称 + + private int user_id; + private String usercode; + private String nickname; + private String age; + private String city_name; + private String avatar; + private List album_list; + private int call_type;//速配类型 2.视频 3.语音 + private int countdown;//速配倒计时 + private String coin;//速配通话单价 + + public String getCall_amount() { + return call_amount; + } + + public void setCall_amount(String call_amount) { + this.call_amount = call_amount; + } + + public String getPay_avatar() { + return pay_avatar; + } + + public void setPay_avatar(String pay_avatar) { + this.pay_avatar = pay_avatar; + } + + public String getPay_nickname() { + return pay_nickname; + } + + public void setPay_nickname(String pay_nickname) { + this.pay_nickname = pay_nickname; + } + + public String getIncome_avatar() { + return income_avatar; + } + + public void setIncome_avatar(String income_avatar) { + this.income_avatar = income_avatar; + } + + public String getIncome_nickname() { + return income_nickname; + } + + public void setIncome_nickname(String income_nickname) { + this.income_nickname = income_nickname; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAge() { + return age; + } + + public void setAge(String age) { + this.age = age; + } + + public String getCity_name() { + return city_name; + } + + public void setCity_name(String city_name) { + this.city_name = city_name; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public List getAlbum_list() { + return album_list; + } + + public void setAlbum_list(List album_list) { + this.album_list = album_list; + } + + public int getCall_type() { + return call_type; + } + + public void setCall_type(int call_type) { + this.call_type = call_type; + } + + public int getCountdown() { + return countdown; + } + + public void setCountdown(int countdown) { + this.countdown = countdown; + } + + public String getCoin() { + return coin; + } + + public void setCoin(String coin) { + this.coin = coin; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/SystemVersionBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/SystemVersionBean.java new file mode 100644 index 0000000..edd5cdd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/SystemVersionBean.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.model.main; + +public class SystemVersionBean { + private int enforce; + private String version; + private int versioncode; + private String downloadurl; + private String packagesize; + private String upgradetext; + private String newversion; + + public int getEnforce() { + return enforce; + } + + public void setEnforce(int enforce) { + this.enforce = enforce; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public int getVersioncode() { + return versioncode; + } + + public void setVersioncode(int versioncode) { + this.versioncode = versioncode; + } + + public String getDownloadurl() { + return downloadurl; + } + + public void setDownloadurl(String downloadurl) { + this.downloadurl = downloadurl; + } + + public String getPackagesize() { + return packagesize; + } + + public void setPackagesize(String packagesize) { + this.packagesize = packagesize; + } + + public String getUpgradetext() { + return upgradetext; + } + + public void setUpgradetext(String upgradetext) { + this.upgradetext = upgradetext; + } + + public String getNewversion() { + return newversion; + } + + public void setNewversion(String newversion) { + this.newversion = newversion; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/UserGenderBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/UserGenderBean.java new file mode 100644 index 0000000..266f4c0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/UserGenderBean.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.model.main; + +import com.fengliyan.tianlesue.model.settings.UserInfoBean; + +import java.util.ArrayList; +import java.util.List; + +public class UserGenderBean { + private int total; + private int page; + private List list = new ArrayList<>(); + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/UserGenderListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/UserGenderListBean.java new file mode 100644 index 0000000..34c8b25 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/UserGenderListBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.main; + +public class UserGenderListBean { + private UserGenderBean list; + + public UserGenderBean getList() { + return list; + } + + public void setList(UserGenderBean list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/VersionBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/VersionBean.java new file mode 100644 index 0000000..0151d3e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/VersionBean.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.model.main; + +public class VersionBean { + private String current; + private String url; + private int level; + private String desc; + private int market_status; // 应用市场版本提审状态:0=提审中 1=已上架 + + public String getCurrent() { + return current; + } + + public void setCurrent(String current) { + this.current = current; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public int getLevel() { + return level; + } + + public void setLevel(int level) { + this.level = level; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public int getMarket_status() { + return market_status; + } + + public void setMarket_status(int market_status) { + this.market_status = market_status; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoFeeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoFeeBean.java new file mode 100644 index 0000000..a2bcad2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoFeeBean.java @@ -0,0 +1,121 @@ +package com.fengliyan.tianlesue.model.main; + +public class VideoFeeBean { + private String room_id; + private int from_uid; + private String from_nickname; + private String from_avatar; + private int to_uid; + private String to_nickname; + private String to_avatar; + private String socket_url; + private CallSkillBean skill; + private long call_time; + private String pay_money; + private double income_money; + private String remark; + + public String getRoom_id() { + return room_id; + } + + public void setRoom_id(String room_id) { + this.room_id = room_id; + } + + public int getFrom_uid() { + return from_uid; + } + + public void setFrom_uid(int from_uid) { + this.from_uid = from_uid; + } + + public String getFrom_nickname() { + return from_nickname; + } + + public void setFrom_nickname(String from_nickname) { + this.from_nickname = from_nickname; + } + + public String getFrom_avatar() { + return from_avatar; + } + + public void setFrom_avatar(String from_avatar) { + this.from_avatar = from_avatar; + } + + public int getTo_uid() { + return to_uid; + } + + public void setTo_uid(int to_uid) { + this.to_uid = to_uid; + } + + public String getTo_nickname() { + return to_nickname; + } + + public void setTo_nickname(String to_nickname) { + this.to_nickname = to_nickname; + } + + public String getTo_avatar() { + return to_avatar; + } + + public void setTo_avatar(String to_avatar) { + this.to_avatar = to_avatar; + } + + public String getSocket_url() { + return socket_url; + } + + public void setSocket_url(String socket_url) { + this.socket_url = socket_url; + } + + public CallSkillBean getSkill() { + return skill; + } + + public void setSkill(CallSkillBean skill) { + this.skill = skill; + } + + public long getCall_time() { + return call_time; + } + + public void setCall_time(long call_time) { + this.call_time = call_time; + } + + public String getPay_money() { + return pay_money; + } + + public void setPay_money(String pay_money) { + this.pay_money = pay_money; + } + + public double getIncome_money() { + return income_money; + } + + public void setIncome_money(double income_money) { + this.income_money = income_money; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoGuardBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoGuardBean.java new file mode 100644 index 0000000..7265ff8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoGuardBean.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.model.main; + +/** + * Created by zhangbin on 2020/1/9. + */ +public class VideoGuardBean { + + private int diff_num; + private int guard_price; + + public int getDiff_num() { + return diff_num; + } + + public void setDiff_num(int diff_num) { + this.diff_num = diff_num; + } + + public int getGuard_price() { + return guard_price; + } + + public void setGuard_price(int guard_price) { + this.guard_price = guard_price; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoRequestBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoRequestBean.java new file mode 100644 index 0000000..a6959c0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoRequestBean.java @@ -0,0 +1,25 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; + +public class VideoRequestBean implements Serializable { + private static final long serialVersionUID = 3896844676644484415L; + private int id; + private VideoRequestDataBean data; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public VideoRequestDataBean getData() { + return data; + } + + public void setData(VideoRequestDataBean data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoRequestDataBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoRequestDataBean.java new file mode 100644 index 0000000..aa05772 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/VideoRequestDataBean.java @@ -0,0 +1,220 @@ +package com.fengliyan.tianlesue.model.main; + +import java.io.Serializable; + +public class VideoRequestDataBean implements Serializable { + + private static final long serialVersionUID = -4413143808453667173L; + /** + * "title": "您有一个新通知", //标题 + * "content": "通知内容", //通知内容(暂时无用,备用) + * "link_type":"",//链接类型 + * "link_url":"", //链接地址 + * "type" => "customSystem" //类型 customSystem(自定义系统通知) + */ + + private String callTime; + private String roomid; + private String title; + private String content; + private int link_type; + private String link_url; + private String type; + private String nickname; + private String avatar; + private int id; + private String giftname; + private int amount; + private String tonickname; + private String toavatar; + private String giftimg; + private int gifttotal; + private int toid; + private long time; + private String prize_url; + private String rule_url; + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public int getGifttotal() { + return gifttotal; + } + + public void setGifttotal(int gifttotal) { + this.gifttotal = gifttotal; + } + + public String getGiftimg() { + return giftimg; + } + + public void setGiftimg(String giftimg) { + this.giftimg = giftimg; + } + + public String getToavatar() { + return toavatar; + } + + public void setToavatar(String toavatar) { + this.toavatar = toavatar; + } + + public String getTonickname() { + return tonickname; + } + + public void setTonickname(String tonickname) { + this.tonickname = tonickname; + } + + public String getCallTime() { + return callTime; + } + + public void setCallTime(String callTime) { + this.callTime = callTime; + } + + public String getRoomid() { + return roomid; + } + + public void setRoomid(String roomid) { + this.roomid = roomid; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public int getLink_type() { + return link_type; + } + + public void setLink_type(int link_type) { + this.link_type = link_type; + } + + public String getLink_url() { + return link_url; + } + + public void setLink_url(String link_url) { + this.link_url = link_url; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getGiftname() { + return giftname; + } + + public void setGiftname(String giftname) { + this.giftname = giftname; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public int getToid() { + return toid; + } + + public void setToid(int toid) { + this.toid = toid; + } + + public String getPrize_url() { + return prize_url; + } + + public void setPrize_url(String prize_url) { + this.prize_url = prize_url; + } + + public String getRule_url() { + return rule_url; + } + + public void setRule_url(String rule_url) { + this.rule_url = rule_url; + } + + @Override + public String toString() { + return "VideoRequestDataBean{" + + "callTime='" + callTime + '\'' + + ", roomid='" + roomid + '\'' + + ", title='" + title + '\'' + + ", content='" + content + '\'' + + ", link_type=" + link_type + + ", link_url='" + link_url + '\'' + + ", type='" + type + '\'' + + ", nickname='" + nickname + '\'' + + ", avatar='" + avatar + '\'' + + ", id=" + id + + ", giftname='" + giftname + '\'' + + ", amount=" + amount + + ", tonickname='" + tonickname + '\'' + + ", toavatar='" + toavatar + '\'' + + ", giftimg='" + giftimg + '\'' + + ", gifttotal=" + gifttotal + + ", toid=" + toid + + ", time=" + time + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/GiftBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/GiftBean.java new file mode 100644 index 0000000..0b1f244 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/GiftBean.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class GiftBean { + private String gift_id; + private int gift_count; + private int room_id; + + public String getGift_id() { + return gift_id; + } + + public void setGift_id(String gift_id) { + this.gift_id = gift_id; + } + + public int getGift_count() { + return gift_count; + } + + public void setGift_count(int gift_count) { + this.gift_count = gift_count; + } + + public int getRoom_id() { + return room_id; + } + + public void setRoom_id(int room_id) { + this.room_id = room_id; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/HangUpBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/HangUpBean.java new file mode 100644 index 0000000..7754436 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/HangUpBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class HangUpBean { + private int type; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/NoticeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/NoticeBean.java new file mode 100644 index 0000000..1134fb1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/NoticeBean.java @@ -0,0 +1,59 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class NoticeBean { + private int type; + private String content; + private String link_type; + private String link_url; + private String from_uid; + private String to_uid; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getLink_type() { + return link_type; + } + + public void setLink_type(String link_type) { + this.link_type = link_type; + } + + public String getLink_url() { + return link_url; + } + + public void setLink_url(String link_url) { + this.link_url = link_url; + } + + + public String getFrom_uid() { + return from_uid; + } + + public void setFrom_uid(String from_uid) { + this.from_uid = from_uid; + } + + public String getTo_uid() { + return to_uid; + } + + public void setTo_uid(String to_uid) { + this.to_uid = to_uid; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/NoticeGiftBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/NoticeGiftBean.java new file mode 100644 index 0000000..e636e84 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/NoticeGiftBean.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class NoticeGiftBean { + private int giftid; + private String giftname; + private String gifticon; + private String gift_effect; + + public int getGiftid() { + return giftid; + } + + public void setGiftid(int giftid) { + this.giftid = giftid; + } + + public String getGiftname() { + return giftname; + } + + public void setGiftname(String giftname) { + this.giftname = giftname; + } + + public String getGifticon() { + return gifticon; + } + + public void setGifticon(String gifticon) { + this.gifticon = gifticon; + } + + public String getGift_effect() { + return gift_effect; + } + + public void setGift_effect(String gift_effect) { + this.gift_effect = gift_effect; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/RoomIdBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/RoomIdBean.java new file mode 100644 index 0000000..781c4e1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/RoomIdBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class RoomIdBean { + private int room_id; + + public int getRoom_id() { + return room_id; + } + + public void setRoom_id(int room_id) { + this.room_id = room_id; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TextBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TextBean.java new file mode 100644 index 0000000..84f6c33 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TextBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class TextBean { + private String txt; + private int room_id; + + public String getTxt() { + return txt; + } + + public void setTxt(String txt) { + this.txt = txt; + } + + public int getRoom_id() { + return room_id; + } + + public void setRoom_id(int room_id) { + this.room_id = room_id; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TimeRemainingBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TimeRemainingBean.java new file mode 100644 index 0000000..bbdc994 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TimeRemainingBean.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +/** + * Created by zhangbin on 2019/3/16. + */ + +public class TimeRemainingBean { + + private int tip; + + public int getTip() { + return tip; + } + + public void setTip(int tip) { + this.tip = tip; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TipBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TipBean.java new file mode 100644 index 0000000..e97794b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/TipBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class TipBean { + String tip; + + public String getTip() { + return tip; + } + + public void setTip(String tip) { + this.tip = tip; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketChatBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketChatBean.java new file mode 100644 index 0000000..9994d3c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketChatBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class WebSocketChatBean { + private int type; + private T data; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketRequestBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketRequestBean.java new file mode 100644 index 0000000..b932804 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketRequestBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class WebSocketRequestBean { + private String method; + private T data; + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketResultBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketResultBean.java new file mode 100644 index 0000000..6d7430d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/main/websocket/WebSocketResultBean.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.model.main.websocket; + +public class WebSocketResultBean { + private String method; + private String code; + private String message; + private T data; + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/AddQQGroupBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/AddQQGroupBean.java new file mode 100644 index 0000000..f91bc67 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/AddQQGroupBean.java @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.model.news; + +/** + * Created by zhangbin on 2018/12/28. + */ + +public class AddQQGroupBean { + private String action; + + private AddQQGroupDataBean data; + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public AddQQGroupDataBean getData() { + return data; + } + + public void setData(AddQQGroupDataBean data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/AddQQGroupDataBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/AddQQGroupDataBean.java new file mode 100644 index 0000000..e042a2c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/AddQQGroupDataBean.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.model.news; + +/** + * Created by zhangbin on 2018/12/28. + */ + +public class AddQQGroupDataBean { + + private String androidKey; + + private String weixinId; + + public String getAndroidKey() { + return androidKey; + } + + public void setAndroidKey(String androidKey) { + this.androidKey = androidKey; + } + + public String getWeixinId() { + return weixinId; + } + + public void setWeixinId(String weixinId) { + this.weixinId = weixinId; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatBean.java new file mode 100644 index 0000000..5a46ad5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatBean.java @@ -0,0 +1,88 @@ +package com.fengliyan.tianlesue.model.news; + +import com.fengliyan.messaging.CustomAttachment; + +public class ChatBean { + private int type; + private String message; + private String datetime; + private String photoUrl; + private String imageUrl; + private String account; + private int cost; + private boolean isFromMe; + private CustomAttachment customAttachment; + + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getDatetime() { + return datetime; + } + + public void setDatetime(String datetime) { + this.datetime = datetime; + } + + public String getPhotoUrl() { + return photoUrl; + } + + public void setPhotoUrl(String photoUrl) { + this.photoUrl = photoUrl; + } + + public boolean isFromMe() { + return isFromMe; + } + + public void setFromMe(boolean fromMe) { + isFromMe = fromMe; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public CustomAttachment getCustomAttachment() { + return customAttachment; + } + + public void setCustomAttachment(CustomAttachment customAttachment) { + this.customAttachment = customAttachment; + } + + public int getCost() { + return cost; + } + + public void setCost(int cost) { + this.cost = cost; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatSettingBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatSettingBean.java new file mode 100644 index 0000000..2f036fd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatSettingBean.java @@ -0,0 +1,38 @@ +package com.fengliyan.tianlesue.model.news; + +import java.util.List; + +/** + * Created by zhangbin on 2019/2/20. + */ + +public class ChatSettingBean { + + private int is_black; + private ChatSettingInfoBean info; + private List dynamic; + + public int getIs_black() { + return is_black; + } + + public void setIs_black(int is_black) { + this.is_black = is_black; + } + + public ChatSettingInfoBean getInfo() { + return info; + } + + public void setInfo(ChatSettingInfoBean info) { + this.info = info; + } + + public List getDynamic() { + return dynamic; + } + + public void setDynamic(List dynamic) { + this.dynamic = dynamic; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatSettingInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatSettingInfoBean.java new file mode 100644 index 0000000..45e2946 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatSettingInfoBean.java @@ -0,0 +1,81 @@ +package com.fengliyan.tianlesue.model.news; + +/** + * Created by zhangbin on 2019/2/20. + */ + +public class ChatSettingInfoBean { + + /** + * "userid":99, + "nickname":"墨墨", + "age":8, + "gender":2, + "avatar":"images/avatar/woman.jpg", + "city":"北京" + */ + + private int user_id; + private String nickname; + private int age; + private int gender; + private String avatar; + private String city; + private String usercode; + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatTipBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatTipBean.java new file mode 100644 index 0000000..c279b43 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/ChatTipBean.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.model.news; + +/** + * Created by zhangbin on 2019/1/23. + */ + +public class ChatTipBean { + + String tip; + + public String getTip() { + return tip; + } + + public void setTip(String tip) { + this.tip = tip; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomBean.java new file mode 100644 index 0000000..1c6cfc8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.news; + +public class CustomBean { + private int type; + private String data; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomGiftDataBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomGiftDataBean.java new file mode 100644 index 0000000..31ca22b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomGiftDataBean.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.model.news; + +public class CustomGiftDataBean { + private int gift_id; + private String gift_name; + private String gift_url; + private String gift_count; + private int link_type; + private String link_url; + + public int getGift_id() { + return gift_id; + } + + public void setGift_id(int gift_id) { + this.gift_id = gift_id; + } + + public String getGift_name() { + return gift_name; + } + + public void setGift_name(String gift_name) { + this.gift_name = gift_name; + } + + public String getGift_url() { + return gift_url; + } + + public void setGift_url(String gift_url) { + this.gift_url = gift_url; + } + + public String getGift_count() { + return gift_count; + } + + public void setGift_count(String gift_count) { + this.gift_count = gift_count; + } + + public int getLink_type() { + return link_type; + } + + public void setLink_type(int link_type) { + this.link_type = link_type; + } + + public String getLink_url() { + return link_url; + } + + public void setLink_url(String link_url) { + this.link_url = link_url; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomMultiImageBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomMultiImageBean.java new file mode 100644 index 0000000..f1a95f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomMultiImageBean.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.model.news; + +public class CustomMultiImageBean { + private int gift_id; + private String gift_name; + private String gift_url; + private int gift_count; + private int link_type; + private String link_url; + + public int getGift_id() { + return gift_id; + } + + public void setGift_id(int gift_id) { + this.gift_id = gift_id; + } + + public String getGift_name() { + return gift_name; + } + + public void setGift_name(String gift_name) { + this.gift_name = gift_name; + } + + public String getGift_url() { + return gift_url; + } + + public void setGift_url(String gift_url) { + this.gift_url = gift_url; + } + + public int getGift_count() { + return gift_count; + } + + public void setGift_count(int gift_count) { + this.gift_count = gift_count; + } + + public int getLink_type() { + return link_type; + } + + public void setLink_type(int link_type) { + this.link_type = link_type; + } + + public String getLink_url() { + return link_url; + } + + public void setLink_url(String link_url) { + this.link_url = link_url; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomRemarkBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomRemarkBean.java new file mode 100644 index 0000000..ae9bfab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomRemarkBean.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.model.news; + +public class CustomRemarkBean { + + /** + * remark : 123 + */ + + private String remark; + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomSingleImageBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomSingleImageBean.java new file mode 100644 index 0000000..6bbd65c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/CustomSingleImageBean.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.model.news; + +public class CustomSingleImageBean { + private int act_type; + private String act_string; + private String image; + private String title; + private String txt; + private int link_type; + private String link_url; + + public int getAct_type() { + return act_type; + } + + public void setAct_type(int act_type) { + this.act_type = act_type; + } + + public String getAct_string() { + return act_string; + } + + public void setAct_string(String act_string) { + this.act_string = act_string; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getTxt() { + return txt; + } + + public void setTxt(String txt) { + this.txt = txt; + } + + public int getLink_type() { + return link_type; + } + + public void setLink_type(int link_type) { + this.link_type = link_type; + } + + public String getLink_url() { + return link_url; + } + + public void setLink_url(String link_url) { + this.link_url = link_url; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/IMCostBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/IMCostBean.java new file mode 100644 index 0000000..bba5270 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/IMCostBean.java @@ -0,0 +1,114 @@ +package com.fengliyan.tianlesue.model.news; + +import com.fengliyan.tianlesue.model.chat.ChatCardRewardBean; + +public class IMCostBean { + private int is_cut; + private int cut_coin; + private int coin; + private int filter; + private String content; + private int use_chat_card;//是否使用聊天券:1 = 是、0 = 否 + private ChatCardRewardBean chat_card; + private int income_coin; + private int is_greet; + private String type; + private int from_risk_status; // 自己风险用户 0否1是 + private int to_risk_status;// 对方风险用户 0否1是 + + public int getIs_cut() { + return is_cut; + } + + public void setIs_cut(int is_cut) { + this.is_cut = is_cut; + } + + public int getCut_coin() { + return cut_coin; + } + + public void setCut_coin(int cut_coin) { + this.cut_coin = cut_coin; + } + + public int getCoin() { + return coin; + } + + public void setCoin(int coin) { + this.coin = coin; + } + + public int getFilter() { + return filter; + } + + public void setFilter(int filter) { + this.filter = filter; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public int getUse_chat_card() { + return use_chat_card; + } + + public void setUse_chat_card(int use_chat_card) { + this.use_chat_card = use_chat_card; + } + + public ChatCardRewardBean getChat_card() { + return chat_card; + } + + public void setChat_card(ChatCardRewardBean chat_card) { + this.chat_card = chat_card; + } + + public int getIncome_coin() { + return income_coin; + } + + public void setIncome_coin(int income_coin) { + this.income_coin = income_coin; + } + + public int getIs_greet() { + return is_greet; + } + + public void setIs_greet(int is_greet) { + this.is_greet = is_greet; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getFrom_risk_status() { + return from_risk_status; + } + + public void setFrom_risk_status(int from_risk_status) { + this.from_risk_status = from_risk_status; + } + + public int getTo_risk_status() { + return to_risk_status; + } + + public void setTo_risk_status(int to_risk_status) { + this.to_risk_status = to_risk_status; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/news/RecentContactBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/news/RecentContactBean.java new file mode 100644 index 0000000..04e46e9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/news/RecentContactBean.java @@ -0,0 +1,112 @@ +package com.fengliyan.tianlesue.model.news; + +import android.os.Parcel; +import android.os.Parcelable; + +public class RecentContactBean implements Parcelable{ + private String photoUrl; + private String name; + private String recentMessage; + private int uncheckedMessageCount; + private String date; + private String account; + private String uncheckedMessageId; + + public RecentContactBean(){ + + } + + protected RecentContactBean(Parcel in) { + photoUrl = in.readString(); + name = in.readString(); + recentMessage = in.readString(); + uncheckedMessageCount = in.readInt(); + date = in.readString(); + account = in.readString(); + uncheckedMessageId = in.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(photoUrl); + dest.writeString(name); + dest.writeString(recentMessage); + dest.writeInt(uncheckedMessageCount); + dest.writeString(date); + dest.writeString(account); + dest.writeString(uncheckedMessageId); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public RecentContactBean createFromParcel(Parcel in) { + return new RecentContactBean(in); + } + + @Override + public RecentContactBean[] newArray(int size) { + return new RecentContactBean[size]; + } + }; + + public String getPhotoUrl() { + return photoUrl; + } + + public void setPhotoUrl(String photoUrl) { + this.photoUrl = photoUrl; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRecentMessage() { + return recentMessage; + } + + public void setRecentMessage(String recentMessage) { + this.recentMessage = recentMessage; + } + + public int getUncheckedMessageCount() { + return uncheckedMessageCount; + } + + public void setUncheckedMessageCount(int uncheckedMessageCount) { + this.uncheckedMessageCount = uncheckedMessageCount; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getUncheckedMessageId() { + return uncheckedMessageId; + } + + public void setUncheckedMessageId(String uncheckedMessageId) { + this.uncheckedMessageId = uncheckedMessageId; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/AccountBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/AccountBean.java new file mode 100644 index 0000000..0610e2f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/AccountBean.java @@ -0,0 +1,41 @@ +package com.fengliyan.tianlesue.model.settings; + +public class AccountBean { + private String card_name; + private String card_account; + private String card; + private String mobile; + + public String getCard() { + return card; + } + + public void setCard(String card) { + this.card = card; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + + public String getCard_name() { + return card_name; + } + + public void setCard_name(String card_name) { + this.card_name = card_name; + } + + public String getCard_account() { + return card_account; + } + + public void setCard_account(String card_account) { + this.card_account = card_account; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/BackPackListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BackPackListBean.java new file mode 100644 index 0000000..a26dce3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BackPackListBean.java @@ -0,0 +1,149 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.io.Serializable; +import java.util.List; + +public class BackPackListBean implements Serializable { + private static final long serialVersionUID = -8076339359301517020L; + + private List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public class BackPackBean implements Serializable { + private static final long serialVersionUID = 2429237272494636523L; + private String title;//免费视频卡 + private String use_effect;// 使用效果:视频第1分钟免费 + private String use_range;//使用范围:一对一视频 + private String valid_time;//有效期限:截止2023年04月04日 + private String num; + private String item_type;//1.视频券 2.聊天券 + + private String prize_name;//奖品名称 + private String prize_url;// 奖品地址 + private String expire_date_desc;// 过期时间 + private String user_btn;// 是否显示去使用按钮 0否 1是 + private String surplus_num_desc;// 剩余量 + private String surplus_desc;// 剩余可用 + private String prize_type;// 奖品类型0=谢谢参与1=文字2金币3普通会员4超级会员5免费视频6充值立减 + private String surplus_num;// 剩余数量 + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getUse_effect() { + return use_effect; + } + + public void setUse_effect(String use_effect) { + this.use_effect = use_effect; + } + + public String getUse_range() { + return use_range; + } + + public void setUse_range(String use_range) { + this.use_range = use_range; + } + + public String getValid_time() { + return valid_time; + } + + public void setValid_time(String valid_time) { + this.valid_time = valid_time; + } + + public String getNum() { + return num; + } + + public void setNum(String num) { + this.num = num; + } + + public String getItem_type() { + return item_type; + } + + public void setItem_type(String item_type) { + this.item_type = item_type; + } + + public String getPrize_name() { + return prize_name; + } + + public void setPrize_name(String prize_name) { + this.prize_name = prize_name; + } + + public String getPrize_url() { + return prize_url; + } + + public void setPrize_url(String prize_url) { + this.prize_url = prize_url; + } + + public String getExpire_date_desc() { + return expire_date_desc; + } + + public void setExpire_date_desc(String expire_date_desc) { + this.expire_date_desc = expire_date_desc; + } + + public String getUser_btn() { + return user_btn; + } + + public void setUser_btn(String user_btn) { + this.user_btn = user_btn; + } + + public String getSurplus_num_desc() { + return surplus_num_desc; + } + + public void setSurplus_num_desc(String surplus_num_desc) { + this.surplus_num_desc = surplus_num_desc; + } + + public String getSurplus_desc() { + return surplus_desc; + } + + public void setSurplus_desc(String surplus_desc) { + this.surplus_desc = surplus_desc; + } + + public String getPrize_type() { + return prize_type; + } + + public void setPrize_type(String prize_type) { + this.prize_type = prize_type; + } + + public String getSurplus_num() { + return surplus_num; + } + + public void setSurplus_num(String surplus_num) { + this.surplus_num = surplus_num; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/BankInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BankInfoBean.java new file mode 100644 index 0000000..85d142d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BankInfoBean.java @@ -0,0 +1,62 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.List; + +public class BankInfoBean { + + public String getCard_name() { + return card_name; + } + + public void setCard_name(String card_name) { + this.card_name = card_name; + } + + public String getCard_account() { + return card_account; + } + + public void setCard_account(String card_account) { + this.card_account = card_account; + } + + public String getBank() { + return bank; + } + + public void setBank(String bank) { + this.bank = bank; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public List getDescribe() { + return describe; + } + + public void setDescribe(List describe) { + this.describe = describe; + } + + private String card_name; + private String card_account; + private String bank; + private String mobile; + + public String getCard() { + return card; + } + + public void setCard(String card) { + this.card = card; + } + + private String card; + private List describe; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/BeAnchorStatusBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BeAnchorStatusBean.java new file mode 100644 index 0000000..94d403b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BeAnchorStatusBean.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.model.settings; + +public class BeAnchorStatusBean { + private int anchor_status; + private int apply_status; + private int agree_protocol; + private int finish_status; + private int photo_status; + private int skill_status; + private int camera_status; + private int audit_status; + private String tip; + + public int getAudit_status() { + return audit_status; + } + + public void setAudit_status(int audit_status) { + this.audit_status = audit_status; + } + + public String getTip() { + return tip; + } + + public void setTip(String tip) { + this.tip = tip; + } + + public int getCamera_status() { + return camera_status; + } + + public void setCamera_status(int camera_status) { + this.camera_status = camera_status; + } + + public int getAnchor_status() { + return anchor_status; + } + + public void setAnchor_status(int anchor_status) { + this.anchor_status = anchor_status; + } + + public int getApply_status() { + return apply_status; + } + + public void setApply_status(int apply_status) { + this.apply_status = apply_status; + } + + public int getAgree_protocol() { + return agree_protocol; + } + + public void setAgree_protocol(int agree_protocol) { + this.agree_protocol = agree_protocol; + } + + public int getFinish_status() { + return finish_status; + } + + public void setFinish_status(int finish_status) { + this.finish_status = finish_status; + } + + public int getPhoto_status() { + return photo_status; + } + + public void setPhoto_status(int photo_status) { + this.photo_status = photo_status; + } + + public int getSkill_status() { + return skill_status; + } + + public void setSkill_status(int skill_status) { + this.skill_status = skill_status; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/BillBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BillBean.java new file mode 100644 index 0000000..01885d2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BillBean.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.model.settings; + +public class BillBean { + private int id; + private int type; + private String icon; + private String from_username; + private int account_type; + private String change_value; + private String system_str; + private String create_time; + private int track_user_id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getFrom_username() { + return from_username; + } + + public void setFrom_username(String from_username) { + this.from_username = from_username; + } + + public int getAccount_type() { + return account_type; + } + + public void setAccount_type(int account_type) { + this.account_type = account_type; + } + + public String getChange_value() { + return change_value; + } + + public void setChange_value(String change_value) { + this.change_value = change_value; + } + + public String getSystem_str() { + return system_str; + } + + public void setSystem_str(String system_str) { + this.system_str = system_str; + } + + public String getCreate_time() { + return create_time; + } + + public void setCreate_time(String create_time) { + this.create_time = create_time; + } + + public int getTrack_user_id() { + return track_user_id; + } + + public void setTrack_user_id(int track_user_id) { + this.track_user_id = track_user_id; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/BillListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BillListBean.java new file mode 100644 index 0000000..13c2c5d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BillListBean.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.ArrayList; +import java.util.List; + +public class BillListBean { + private int total; + private int page; + private int total_page; + private List list = new ArrayList<>(); + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } + + public int getTotal_page() { + return total_page; + } + + public void setTotal_page(int total_page) { + this.total_page = total_page; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/BindInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BindInfoBean.java new file mode 100644 index 0000000..2eca157 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/BindInfoBean.java @@ -0,0 +1,77 @@ +package com.fengliyan.tianlesue.model.settings; + +public class BindInfoBean { + private String mobile; + private String origin_mobile; + private String is_set_pwd;//是否设置过密码:1=是、0=否 + private String qq; + private String wechat; + private String weibo; + private String real_name_status;//实名认证 0.未认证,1.已认证 + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getQq() { + return qq; + } + + public void setQq(String qq) { + this.qq = qq; + } + + public String getWechat() { + return wechat; + } + + public void setWechat(String wechat) { + this.wechat = wechat; + } + + public String getWeibo() { + return weibo; + } + + public void setWeibo(String weibo) { + this.weibo = weibo; + } + + public String getReal_name_status() { + return real_name_status; + } + + public void setReal_name_status(String real_name_status) { + this.real_name_status = real_name_status; + } + + public String getOrigin_mobile() { + return origin_mobile; + } + + public void setOrigin_mobile(String origin_mobile) { + this.origin_mobile = origin_mobile; + } + + public String getIs_set_pwd() { + return is_set_pwd; + } + + public void setIs_set_pwd(String is_set_pwd) { + this.is_set_pwd = is_set_pwd; + } + + @Override + public String toString() { + return "BindInfoBean{" + + "mobile='" + mobile + '\'' + + ", qq='" + qq + '\'' + + ", wechat='" + wechat + '\'' + + ", weibo='" + weibo + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/CancellationBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/CancellationBean.java new file mode 100644 index 0000000..f631414 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/CancellationBean.java @@ -0,0 +1,14 @@ +package com.fengliyan.tianlesue.model.settings; + +public class CancellationBean { + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + private int status; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/ChatPriceBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/ChatPriceBean.java new file mode 100644 index 0000000..82bc27a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/ChatPriceBean.java @@ -0,0 +1,134 @@ +package com.fengliyan.tianlesue.model.settings; + +public class ChatPriceBean { + private int video_price;//视频价格 + private int voice_price;//语音价格 + private int open_video_status;//开启视频接听状态:0 = 未开启、1 = 已开启 + private int open_voice_status;//开启语音接听状态:0 = 未开启、1 = 已开启 + private int price_desc_display;//价格说明是否显示1显示0不显示 + private int wx_desc_display;//查看微信说明说明是否显示1显示0不显示 + private PriceChildBean price_desc; + private PriceChildBean wx_desc; + private int max_video_price; + private int min_video_price; + private int max_voice_price; + private int min_voice_price; + + public int getVideo_price() { + return video_price; + } + + public void setVideo_price(int video_price) { + this.video_price = video_price; + } + + public int getVoice_price() { + return voice_price; + } + + public void setVoice_price(int voice_price) { + this.voice_price = voice_price; + } + + public int getOpen_video_status() { + return open_video_status; + } + + public void setOpen_video_status(int open_video_status) { + this.open_video_status = open_video_status; + } + + public int getOpen_voice_status() { + return open_voice_status; + } + + public void setOpen_voice_status(int open_voice_status) { + this.open_voice_status = open_voice_status; + } + + public int getPrice_desc_display() { + return price_desc_display; + } + + public void setPrice_desc_display(int price_desc_display) { + this.price_desc_display = price_desc_display; + } + + public int getWx_desc_display() { + return wx_desc_display; + } + + public void setWx_desc_display(int wx_desc_display) { + this.wx_desc_display = wx_desc_display; + } + + public PriceChildBean getPrice_desc() { + return price_desc; + } + + public void setPrice_desc(PriceChildBean price_desc) { + this.price_desc = price_desc; + } + + public PriceChildBean getWx_desc() { + return wx_desc; + } + + public void setWx_desc(PriceChildBean wx_desc) { + this.wx_desc = wx_desc; + } + + public int getMax_video_price() { + return max_video_price; + } + + public void setMax_video_price(int max_video_price) { + this.max_video_price = max_video_price; + } + + public int getMin_video_price() { + return min_video_price; + } + + public void setMin_video_price(int min_video_price) { + this.min_video_price = min_video_price; + } + + public int getMax_voice_price() { + return max_voice_price; + } + + public void setMax_voice_price(int max_voice_price) { + this.max_voice_price = max_voice_price; + } + + public int getMin_voice_price() { + return min_voice_price; + } + + public void setMin_voice_price(int min_voice_price) { + this.min_voice_price = min_voice_price; + } + + public class PriceChildBean { + private String title; + private String content; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/GoddessPrivilegeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/GoddessPrivilegeBean.java new file mode 100644 index 0000000..4abe4f3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/GoddessPrivilegeBean.java @@ -0,0 +1,312 @@ +package com.fengliyan.tianlesue.model.settings; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +/** + * ying 2020/7/7 + * Describe :女神特权 + */ + +public class GoddessPrivilegeBean { + + private AnchorBean anchor; + @SerializedName("long") + private int longX; + private String member_time; + private List memberPrice; + + public AnchorBean getAnchor() { + return anchor; + } + + public void setAnchor(AnchorBean anchor) { + this.anchor = anchor; + } + + public int getLongX() { + return longX; + } + + public void setLongX(int longX) { + this.longX = longX; + } + + public String getMember_time() { + return member_time; + } + + public void setMember_time(String member_time) { + this.member_time = member_time; + } + + public List getMemberPrice() { + return memberPrice; + } + + public void setMemberPrice(List memberPrice) { + this.memberPrice = memberPrice; + } + + public static class AnchorBean { + /** + * hide_rank : 1 + * hide_greet : 1 + * hide_dynamic : 1 + * hide_gift : 1 + * hide_fans : 1 + * hide_service_num : 0 + * hide_guard : 1 + * hide_chat : 1 + * hide_avatar : 1 + */ + + private int hide_rank; + private int hide_greet; + private int hide_dynamic; + private int hide_gift; + private int hide_fans; + private int hide_service_num; + private int hide_guard; + private int hide_chat; + private int hide_avatar; + private int hide_read_msg; + + public int getHide_rank() { + return hide_rank; + } + + public void setHide_rank(int hide_rank) { + this.hide_rank = hide_rank; + } + + public int getHide_greet() { + return hide_greet; + } + + public void setHide_greet(int hide_greet) { + this.hide_greet = hide_greet; + } + + public int getHide_dynamic() { + return hide_dynamic; + } + + public void setHide_dynamic(int hide_dynamic) { + this.hide_dynamic = hide_dynamic; + } + + public int getHide_gift() { + return hide_gift; + } + + public void setHide_gift(int hide_gift) { + this.hide_gift = hide_gift; + } + + public int getHide_fans() { + return hide_fans; + } + + public void setHide_fans(int hide_fans) { + this.hide_fans = hide_fans; + } + + public int getHide_service_num() { + return hide_service_num; + } + + public void setHide_service_num(int hide_service_num) { + this.hide_service_num = hide_service_num; + } + + public int getHide_guard() { + return hide_guard; + } + + public void setHide_guard(int hide_guard) { + this.hide_guard = hide_guard; + } + + public int getHide_chat() { + return hide_chat; + } + + public void setHide_chat(int hide_chat) { + this.hide_chat = hide_chat; + } + + public int getHide_avatar() { + return hide_avatar; + } + + public void setHide_avatar(int hide_avatar) { + this.hide_avatar = hide_avatar; + } + + public int getHide_read_msg() { + return hide_read_msg; + } + + public void setHide_read_msg(int hide_read_msg) { + this.hide_read_msg = hide_read_msg; + } + } + + public static class MemberPriceBean { + /** + * id : 7 + * type : 1 + * member_type : 3 + * account_type : 1 + * gender : 1 + * name : 永久会员 + * price : 99.00 + * img : + * desc : + * expires : 3650 + * reward : 0 + * status : 0 + * recommend : 0 + * per : 0.01 + * longs : 1 + */ + + private int id; + private int type; + private int member_type; + private int account_type; + private int gender; + private String name; + private String price; + private String img; + private String desc; + private int expires; + private int reward; + private int status; + private int recommend; + private String per; + private int longs; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getMember_type() { + return member_type; + } + + public void setMember_type(int member_type) { + this.member_type = member_type; + } + + public int getAccount_type() { + return account_type; + } + + public void setAccount_type(int account_type) { + this.account_type = account_type; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public int getExpires() { + return expires; + } + + public void setExpires(int expires) { + this.expires = expires; + } + + public int getReward() { + return reward; + } + + public void setReward(int reward) { + this.reward = reward; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public int getRecommend() { + return recommend; + } + + public void setRecommend(int recommend) { + this.recommend = recommend; + } + + public String getPer() { + return per; + } + + public void setPer(String per) { + this.per = per; + } + + public int getLongs() { + return longs; + } + + public void setLongs(int longs) { + this.longs = longs; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/GreetingBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/GreetingBean.java new file mode 100644 index 0000000..9015df9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/GreetingBean.java @@ -0,0 +1,135 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.List; + +public class GreetingBean { + /** + * list : [{"id":3,"user_id":368,"type":0,"title":"hello1","status":0,"create_time":1547725661},{"id":1,"user_id":368,"type":0,"title":"hello","status":0,"create_time":1547725648}] + * count : 10 + * tonum : 20 + * status : 1 + */ + + private int count; + private int tonum; + private String status; + private List list; + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public int getTonum() { + return tonum; + } + + public void setTonum(int tonum) { + this.tonum = tonum; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public static class ListBean { + /** + * id : 3 + * user_id : 368 + * type : 0 + * title : hello1 + * status : 0 + * create_time : 1547725661 + */ + + private int id; + private int user_id; + private int type; + private String title; + private int status; + private int create_time; + + public boolean isPlaying() { + return isPlaying; + } + + public void setPlaying(boolean playing) { + isPlaying = playing; + } + + private boolean isPlaying; + + public int getDur() { + return dur; + } + + public void setDur(int dur) { + this.dur = dur; + } + + private int dur; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public int getCreate_time() { + return create_time; + } + + public void setCreate_time(int create_time) { + this.create_time = create_time; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationBean.java new file mode 100644 index 0000000..d8382ae --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationBean.java @@ -0,0 +1,109 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.List; + +public class InvitationBean { + private InvitationShare share; + private InvitationTop top; + private InvitationReward reward; + private InvitationTotal total; + private String qrcode; + private List reward_desc; + private int show_invite_list; + + public List getAvatar_list() { + return avatar_list; + } + + public void setAvatar_list(List avatar_list) { + this.avatar_list = avatar_list; + } + + private List avatar_list; + + public InvitationShare getShare() { + return share; + } + + public void setShare(InvitationShare share) { + this.share = share; + } + + public InvitationTop getTop() { + return top; + } + + public void setTop(InvitationTop top) { + this.top = top; + } + + public InvitationReward getReward() { + return reward; + } + + public void setReward(InvitationReward reward) { + this.reward = reward; + } + + public InvitationTotal getTotal() { + return total; + } + + public void setTotal(InvitationTotal total) { + this.total = total; + } + + public String getQrcode() { + return qrcode; + } + + public void setQrcode(String qrcode) { + this.qrcode = qrcode; + } + + public List getReward_desc() { + return reward_desc; + } + + public void setReward_desc(List reward_desc) { + this.reward_desc = reward_desc; + } + + public int getShow_invite_list() { + return show_invite_list; + } + + public void setShow_invite_list(int show_invite_list) { + this.show_invite_list = show_invite_list; + } + + public class RewardDescBean { + private String title; + private String content; + private String font_colour; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getFont_colour() { + return font_colour; + } + + public void setFont_colour(String font_colour) { + this.font_colour = font_colour; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationReward.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationReward.java new file mode 100644 index 0000000..b5f4c6b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationReward.java @@ -0,0 +1,39 @@ +package com.fengliyan.tianlesue.model.settings; + +public class InvitationReward { + private String first; + private String second; + private String third; + private String four; + + public String getFirst() { + return first; + } + + public void setFirst(String first) { + this.first = first; + } + + public String getSecond() { + return second; + } + + public void setSecond(String second) { + this.second = second; + } + + public String getThird() { + return third; + } + public void setFour(String four) { + this.four = four; + } + + public String getFour() { + return four; + } + + public void setThird(String third) { + this.third = third; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationShare.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationShare.java new file mode 100644 index 0000000..182c01d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationShare.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.model.settings; + +public class InvitationShare { + private String title; + private String content; + private String url; + private String image_url; + private String url_wechat; + private String wxShareConfig;//1复制 ;2分享 + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getImage_url() { + return image_url; + } + + public void setImage_url(String image_url) { + this.image_url = image_url; + } + + public String getUrl_wechat() { + return url_wechat; + } + + public void setUrl_wechat(String url_wechat) { + this.url_wechat = url_wechat; + } + + public String getWxShareConfig() { + return wxShareConfig; + } + + public void setWxShareConfig(String wxShareConfig) { + this.wxShareConfig = wxShareConfig; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationTop.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationTop.java new file mode 100644 index 0000000..e75c170 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationTop.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.model.settings; + +public class InvitationTop { + private int userid; + private String nickname; + private String avatar; + private String total_reward; + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getTotal_reward() { + return total_reward; + } + + public void setTotal_reward(String total_reward) { + this.total_reward = total_reward; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationTotal.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationTotal.java new file mode 100644 index 0000000..b66ec0b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InvitationTotal.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.model.settings; + +public class InvitationTotal { + private int total_reward; + private int total_invite; + private int total_commission; + private int recharge_count; + private int auth_count; + + public int getTotal_commission() { + return total_commission; + } + + public void setTotal_commission(int total_commission) { + this.total_commission = total_commission; + } + + public int getTotal_reward() { + return total_reward; + } + + public void setTotal_reward(int total_reward) { + this.total_reward = total_reward; + } + + public int getTotal_invite() { + return total_invite; + } + + public void setTotal_invite(int total_invite) { + this.total_invite = total_invite; + } + + public int getRecharge_count() { + return recharge_count; + } + + public void setRecharge_count(int recharge_count) { + this.recharge_count = recharge_count; + } + + public int getAuth_count() { + return auth_count; + } + + public void setAuth_count(int auth_count) { + this.auth_count = auth_count; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/InviteDataListBean.kt b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InviteDataListBean.kt new file mode 100644 index 0000000..8c94571 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/InviteDataListBean.kt @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.model.settings + +import java.io.Serializable + +class InviteDataListBean : Serializable { + var list: List? = null + var income: IncomeListBean? = null + + class InviteListBean : Serializable { + var user_id = 0 + var invite_user_id = 0 + var nickname: String? = null + var usercode: String? = null + var avatar: String? = null + var invite_usercode: String? = null + var invite_nickname: String? = null + var amount: String? = null + var divide_amount: String? = null + var recharge_type = 0//充值类型1=金币2=会员3=视频4=礼物 + var create_at: String? = null + } + + class IncomeListBean : Serializable { + var direct: IncomeBean? = null + var indirect: IncomeBean? = null + var all_income: String? = null + } + + class IncomeBean : Serializable { + var user_count: String? = null + var gold_amount: String? = null + var vip_amount: String? = null + var divide_amount: String? = null + var revenue_amount: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberBannerInfo.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberBannerInfo.java new file mode 100644 index 0000000..c6596d2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberBannerInfo.java @@ -0,0 +1,20 @@ +package com.fengliyan.tianlesue.model.settings; + +/** + * Created by zhangbin on 2019/5/16. + */ + +public class MemberBannerInfo { + + private String pic; + + public String getPic() { + return pic; + } + + public void setPic(String pic) { + this.pic = pic; + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberBean.java new file mode 100644 index 0000000..1833725 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberBean.java @@ -0,0 +1,101 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.List; + +/** + * Created by zhangbin on 2019/5/16. + */ + +public class MemberBean { + private MemberInfo info; + private MemberBannerInfo banner; + private MemberOperationInfo operation; + private FreeBean free; + private List privilege; + private List privileges; + + public List getPrivilege() { + return privilege; + } + + public void setPrivilege(List privilege) { + this.privilege = privilege; + } + + public MemberInfo getInfo() { + return info; + } + + public void setInfo(MemberInfo info) { + this.info = info; + } + + public MemberBannerInfo getBanner() { + return banner; + } + + public void setBanner(MemberBannerInfo banner) { + this.banner = banner; + } + + public MemberOperationInfo getOperation() { + return operation; + } + + public void setOperation(MemberOperationInfo operation) { + this.operation = operation; + } + + public List getPrivileges() { + return privileges; + } + + public void setPrivileges(List privileges) { + this.privileges = privileges; + } + + public FreeBean getFree() { + return free; + } + + public void setFree(FreeBean free) { + this.free = free; + } + + @Override + public String toString() { + return "MemberBean{" + + "info=" + info + + ", banner=" + banner + + ", operation=" + operation + + ", privileges=" + privileges + + '}'; + } + + public static class FreeBean { + /** + * free_num : 1 + * total_num : 3 + */ + + private String free_num; + private String total_num; + + public String getFree_num() { + return free_num; + } + + public void setFree_num(String free_num) { + this.free_num = free_num; + } + + public String getTotal_num() { + return total_num; + } + + public void setTotal_num(String total_num) { + this.total_num = total_num; + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberInfo.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberInfo.java new file mode 100644 index 0000000..58886e6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberInfo.java @@ -0,0 +1,115 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.List; + +/** + * Created by zhangbin on 2019/5/16. + */ + +public class MemberInfo { + + private int id; + private String nickname; + private String avatar; + private int on; //是否开通了会员 + private int surplus; //剩余天数 + private int longs; + private String expire_date; //到期日 + private String expire_date_new; + private List list; + private String vip_day_free_send; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getOn() { + return on; + } + + public void setOn(int on) { + this.on = on; + } + + public int getSurplus() { + return surplus; + } + + public void setSurplus(int surplus) { + this.surplus = surplus; + } + + public int getLongs() { + return longs; + } + + public void setLongs(int longs) { + this.longs = longs; + } + + public String getExpire_date() { + return expire_date; + } + + public void setExpire_date(String expire_date) { + this.expire_date = expire_date; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public String getExpire_date_new() { + return expire_date_new; + } + + public void setExpire_date_new(String expire_date_new) { + this.expire_date_new = expire_date_new; + } + + public String getVip_day_free_send() { + return vip_day_free_send; + } + + public void setVip_day_free_send(String vip_day_free_send) { + this.vip_day_free_send = vip_day_free_send; + } + + @Override + public String toString() { + return "MemberInfo{" + + "id=" + id + + ", nickname='" + nickname + '\'' + + ", avatar='" + avatar + '\'' + + ", on=" + on + + ", surplus=" + surplus + + ", longs=" + longs + + ", expire_date='" + expire_date + '\'' + + ", list=" + list + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberInfoList.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberInfoList.java new file mode 100644 index 0000000..e4ac589 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberInfoList.java @@ -0,0 +1,93 @@ +package com.fengliyan.tianlesue.model.settings; + +/** + * Created by zhangbin on 2019/5/16. + */ + +public class MemberInfoList { + + private int id; + private String name; + private String price; + private String origin_price; + private String img; + private String per; + private int on; + private String expires_title; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getOrigin_price() { + return origin_price; + } + + public void setOrigin_price(String origin_price) { + this.origin_price = origin_price; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public String getPer() { + return per; + } + + public void setPer(String per) { + this.per = per; + } + + public int getOn() { + return on; + } + + public void setOn(int on) { + this.on = on; + } + + public String getExpires_title() { + return expires_title; + } + + public void setExpires_title(String expires_title) { + this.expires_title = expires_title; + } + + @Override + public String toString() { + return "MemberInfoList{" + + "id=" + id + + ", name='" + name + '\'' + + ", price='" + price + '\'' + + ", img='" + img + '\'' + + ", per='" + per + '\'' + + ", on=" + on + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberOperationInfo.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberOperationInfo.java new file mode 100644 index 0000000..a6c7bd2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberOperationInfo.java @@ -0,0 +1,117 @@ +package com.fengliyan.tianlesue.model.settings; + +/** + * Created by zhangbin on 2019/5/16. + */ + +public class MemberOperationInfo { + + private int rank_hide; + private int no_greet; + private int rechange_hide; + private int login_notice_hide; + private int login_time_hide; + private int greet_hide; + private int visitor_hide; + private int speed_hide; + private int avatar_hide; + private int hide_read_msg; + private int hide_fans; + + public int getRechange_hide() { + return rechange_hide; + } + + public void setRechange_hide(int rechange_hide) { + this.rechange_hide = rechange_hide; + } + + + public int getRank_hide() { + return rank_hide; + } + + public void setRank_hide(int rank_hide) { + this.rank_hide = rank_hide; + } + + public int getNo_greet() { + return no_greet; + } + + public void setNo_greet(int no_greet) { + this.no_greet = no_greet; + } + + public int getLogin_notice_hide() { + return login_notice_hide; + } + + public void setLogin_notice_hide(int login_notice_hide) { + this.login_notice_hide = login_notice_hide; + } + + public int getLogin_time_hide() { + return login_time_hide; + } + + public void setLogin_time_hide(int login_time_hide) { + this.login_time_hide = login_time_hide; + } + + public int getGreet_hide() { + return greet_hide; + } + + public void setGreet_hide(int greet_hide) { + this.greet_hide = greet_hide; + } + + public int getVisitor_hide() { + return visitor_hide; + } + + public void setVisitor_hide(int visitor_hide) { + this.visitor_hide = visitor_hide; + } + + public int getSpeed_hide() { + return speed_hide; + } + + public void setSpeed_hide(int speed_hide) { + this.speed_hide = speed_hide; + } + + public int getAvatar_hide() { + return avatar_hide; + } + + public void setAvatar_hide(int avatar_hide) { + this.avatar_hide = avatar_hide; + } + + public int getHide_read_msg() { + return hide_read_msg; + } + + public void setHide_read_msg(int hide_read_msg) { + this.hide_read_msg = hide_read_msg; + } + + public int getHide_fans() { + return hide_fans; + } + + public void setHide_fans(int hide_fans) { + this.hide_fans = hide_fans; + } + + @Override + public String toString() { + return "MemberOperationInfo{" + + "rank_hide=" + rank_hide + + ", no_greet=" + no_greet + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberPrivilegesInfo.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberPrivilegesInfo.java new file mode 100644 index 0000000..8b29412 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MemberPrivilegesInfo.java @@ -0,0 +1,55 @@ +package com.fengliyan.tianlesue.model.settings; + +/** + * Created by zhangbin on 2019/5/16. + */ + +public class MemberPrivilegesInfo { + + private int id; + private String name; + private String desc; + private String icon; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + @Override + public String toString() { + return "MemberPrivilegesInfo{" + + "id=" + id + + ", name='" + name + '\'' + + ", desc='" + desc + '\'' + + ", icon='" + icon + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MenuBean.kt b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MenuBean.kt new file mode 100644 index 0000000..0f68fe1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MenuBean.kt @@ -0,0 +1,38 @@ +package com.fengliyan.tianlesue.model.settings + +import com.fengliyan.tianlesue.R + +data class MenuBean( + var name: String, + var desc: String, + var image: Int, + var status: Int, + var type:String +) { + companion object { + fun girlPrivileges(): List { + var result = mutableListOf() + result.add(MenuBean("聊天效果框","开启后聊天对话框展示动画效果", + R.mipmap.privilege_chat,0,"chat")) + result.add(MenuBean("头像效果框","开启后个人头像展示动画效果", + R.mipmap.privilege_border,0,"avatar")) + result.add(MenuBean("隐藏活跃时间","开启后个人主页不展示活跃时间", + R.mipmap.privilege_date,0,"greet")) + result.add(MenuBean("消息读取状态","可查看是否已读", + R.mipmap.privilege_read,0,"read_msg")) + result.add(MenuBean("榜单隐藏","开启后榜单列表匿名显示", + R.mipmap.privilege_rank,0,"rank")) + result.add(MenuBean("隐藏动态","开启后个人主页不展示发布的动态", + R.mipmap.privilege_feed,0,"dynamic")) + result.add(MenuBean("隐藏礼物","开启后个人主页不展示收到的礼物", + R.mipmap.privilege_gift,0,"gift")) + result.add(MenuBean("隐藏守护","开启后个人主页不展示收到的守护", + R.mipmap.privilege_protecte,0,"guard")) + result.add(MenuBean("隐藏粉丝数","开启后个人主页不展示关注、粉丝、来访人数", + R.mipmap.privilege_fans,0,"fans")) + result.add(MenuBean("隐藏接通次数","开启后个人主页不展示接通次数", + R.mipmap.privilge_call,0,"service_num")) + return result + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MissionBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MissionBean.java new file mode 100644 index 0000000..7ebf99a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MissionBean.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.model.settings; + +public class MissionBean { + private int id; + private String task_name; + private String task_reward; + private int is_finish; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTask_name() { + return task_name; + } + + public void setTask_name(String task_name) { + this.task_name = task_name; + } + + public String getTask_reward() { + return task_reward; + } + + public void setTask_reward(String task_reward) { + this.task_reward = task_reward; + } + + public int getIs_finish() { + return is_finish; + } + + public void setIs_finish(int is_finish) { + this.is_finish = is_finish; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/MissionListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MissionListBean.java new file mode 100644 index 0000000..9f41477 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/MissionListBean.java @@ -0,0 +1,25 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.ArrayList; +import java.util.List; + +public class MissionListBean { + private List list = new ArrayList<>(); + private ShareBean share; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public ShareBean getShare() { + return share; + } + + public void setShare(ShareBean share) { + this.share = share; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/NewRankBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/NewRankBean.java new file mode 100644 index 0000000..bf4a6f4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/NewRankBean.java @@ -0,0 +1,79 @@ +package com.fengliyan.tianlesue.model.settings; + +public class NewRankBean { + private int no; + private int user_id; + private String usercode; + private String nickname; + private String avatar; + private double totalMoney; + private String gap; + + public int getNo() { + return no; + } + + public void setNo(int no) { + this.no = no; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public double getTotalMoney() { + return totalMoney; + } + + public void setTotalMoney(double totalMoney) { + this.totalMoney = totalMoney; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getGap() { + return gap; + } + + public void setGap(String gap) { + this.gap = gap; + } + + @Override + public String toString() { + return "RankBean{" + + "no=" + no + + ", user_id=" + user_id + + ", usercode='" + usercode + '\'' + + ", nickname='" + nickname + '\'' + + ", avatar='" + avatar + '\'' + + ", totalMoney=" + totalMoney + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/OrderBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/OrderBean.java new file mode 100644 index 0000000..75f21d0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/OrderBean.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.model.settings; + +public class OrderBean { + private String order_no; + private int recharge_type; + private int platform_type; + private String platform_name; + private String recharge_money; + + public String getOrder_no() { + return order_no; + } + + public void setOrder_no(String order_no) { + this.order_no = order_no; + } + + public int getRecharge_type() { + return recharge_type; + } + + public void setRecharge_type(int recharge_type) { + this.recharge_type = recharge_type; + } + + public int getPlatform_type() { + return platform_type; + } + + public void setPlatform_type(int platform_type) { + this.platform_type = platform_type; + } + + public String getPlatform_name() { + return platform_name; + } + + public void setPlatform_name(String platform_name) { + this.platform_name = platform_name; + } + + public String getRecharge_money() { + return recharge_money; + } + + public void setRecharge_money(String recharge_money) { + this.recharge_money = recharge_money; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/PayBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/PayBean.java new file mode 100644 index 0000000..44219e0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/PayBean.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.io.Serializable; + +public class PayBean { + private String payinfo; + private String kqPayInfo; + private OrderBean order; + private WeChatPayInfoBean wechatpayinfo; + private Sandpayinfo sandpayinfo; + + public int getPay_platform_type() { + return pay_platform_type; + } + + public void setPay_platform_type(int pay_platform_type) { + this.pay_platform_type = pay_platform_type; + } + + private int pay_platform_type; + + public String getPayinfo() { + return payinfo; + } + + public void setPayinfo(String payinfo) { + this.payinfo = payinfo; + } + + public String getKqPayInfo() { + return kqPayInfo; + } + + public void setKqPayInfo(String kqPayInfo) { + this.kqPayInfo = kqPayInfo; + } + + public OrderBean getOrder() { + return order; + } + + public void setOrder(OrderBean order) { + this.order = order; + } + + public WeChatPayInfoBean getWechatpayinfo() { + return wechatpayinfo; + } + + public void setWechatpayinfo(WeChatPayInfoBean wechatpayinfo) { + this.wechatpayinfo = wechatpayinfo; + } + + public Sandpayinfo getSandpayinfo() { + return sandpayinfo; + } + + public void setSandpayinfo(Sandpayinfo sandpayinfo) { + this.sandpayinfo = sandpayinfo; + } + + public class Sandpayinfo implements Serializable { + + private String cashierUrl; + + public String getCashierUrl() { + return cashierUrl; + } + + public void setCashierUrl(String cashierUrl) { + this.cashierUrl = cashierUrl; + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/PayConfigBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/PayConfigBean.java new file mode 100644 index 0000000..73d0626 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/PayConfigBean.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.model.settings; + +public class PayConfigBean { + + /** + * wechat_switch : 2 + * alipay_switch : 1 + */ + + private String wechat_switch; + private String alipay_switch; + + public String getWechat_switch() { + return wechat_switch; + } + + public void setWechat_switch(String wechat_switch) { + this.wechat_switch = wechat_switch; + } + + public String getAlipay_switch() { + return alipay_switch; + } + + public void setAlipay_switch(String alipay_switch) { + this.alipay_switch = alipay_switch; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/RankAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RankAdapter.java new file mode 100644 index 0000000..678bb21 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RankAdapter.java @@ -0,0 +1,116 @@ +package com.fengliyan.tianlesue.model.settings; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +public class RankAdapter extends BaseAdapter { + private List mRankBeans = new ArrayList<>(); + private Context mContext; + + public RankAdapter(Context context) { + mContext = context; + } + + public void setRankBeans(List list) { + mRankBeans = list; + } + + @Override + public int getCount() { + return mRankBeans.size(); + } + + @Override + public Object getItem(int i) { + return mRankBeans.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Holder holder = null; + final NewRankBean bean = mRankBeans.get(i); + if (null == view) { + view = View.inflate(mContext, R.layout.item_daka_rank, null); + holder = initView(view); + } else { + holder = (Holder) view.getTag(); + } + if (i == 0) { + holder.daka_rank_line.setVisibility(View.GONE); + } else { + holder.daka_rank_line.setVisibility(View.VISIBLE); + } + holder.photo.setImageURI(StrU.getResourcePath(bean.getAvatar(), mContext)); + holder.name.setText(bean.getNickname()); + holder.number.setText(bean.getNo() + ""); + setTextMoney(holder.cost, bean.getGap()); +// holder.cost.setText(String.format("%.0f", bean.getTotalMoney())); + view.setTag(holder); + + holder.rlAllItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (bean.getUser_id() != 0) { + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", bean.getUser_id()); + mContext.startActivity(intent); + } + } + }); + return view; + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, String totalMoney) { +// if (totalMoney >= 10000) { +// double money = totalMoney / 10000; +// view.setText(String.format("%.1f", money) + "万"); +// }else { +// view.setText(String.format("%.0f", totalMoney)); +// } + view.setText(totalMoney); + } + + private Holder initView(View v) { + Holder holder = new Holder(); + holder.photo = v.findViewById(R.id.daka_rank_other_photo); + holder.name = v.findViewById(R.id.daka_rank_other_name); + holder.number = v.findViewById(R.id.daka_rank_other_number); + holder.cost = v.findViewById(R.id.daka_rank_other_cost); + holder.rlAllItem = v.findViewById(R.id.rl_all_item); + holder.daka_rank_line = v.findViewById(R.id.daka_rank_line); + return holder; + } + + class Holder { + private TextView number; + private SimpleDraweeView photo; + private TextView name; + private TextView cost; + private RelativeLayout rlAllItem; + private View daka_rank_line; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/RankListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RankListBean.java new file mode 100644 index 0000000..a366438 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RankListBean.java @@ -0,0 +1,33 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.ArrayList; +import java.util.List; + +public class RankListBean { + private List list = new ArrayList<>(); + private NewRankBean myrank; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public NewRankBean getMyrank() { + return myrank; + } + + public void setMyrank(NewRankBean myrank) { + this.myrank = myrank; + } + + @Override + public String toString() { + return "RankListBean{" + + "list=" + list + + ", myrank=" + myrank + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/RechargeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RechargeBean.java new file mode 100644 index 0000000..5c82d36 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RechargeBean.java @@ -0,0 +1,95 @@ +package com.fengliyan.tianlesue.model.settings; + +public class RechargeBean { + private int id; + private String name; + private String price; + private int amount; + private int reward; + private String remark; + private int svip_show_reward;//超级会员界面开通后充值将会赠送的金币数 + private String discount_desc; + private String discount_price; + + public int getFirst_rechange_reward() { + return first_rechange_reward; + } + + public void setFirst_rechange_reward(int first_rechange_reward) { + this.first_rechange_reward = first_rechange_reward; + } + + private int first_rechange_reward; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public int getReward() { + return reward; + } + + public void setReward(int reward) { + this.reward = reward; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public int getSvip_show_reward() { + return svip_show_reward; + } + + public void setSvip_show_reward(int svip_show_reward) { + this.svip_show_reward = svip_show_reward; + } + + public String getDiscount_desc() { + return discount_desc; + } + + public void setDiscount_desc(String discount_desc) { + this.discount_desc = discount_desc; + } + + public String getDiscount_price() { + return discount_price; + } + + public void setDiscount_price(String discount_price) { + this.discount_price = discount_price; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/RechargeListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RechargeListBean.java new file mode 100644 index 0000000..2e33aca --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/RechargeListBean.java @@ -0,0 +1,229 @@ +package com.fengliyan.tianlesue.model.settings; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +public class RechargeListBean { + private String money; + private String income_money; + private int coin; + private int income_coin; + private String chongzhi_bg; + private int wechat_pay_status; + private int is_first_recharge;// 1=已经首充过、0=没有首充过 + private int selected_id;//默认选择金额下标 + private List gift_bag_list; + private int show_wx_pay_type = 1;//显示微信支付 1显示0不显示 + private int show_alipay_pay_type = 1;// 显示支付宝支付 1显示0不显示 + + public int getWechat_pay_status() { + return wechat_pay_status; + } + + public void setWechat_pay_status(int wechat_pay_status) { + this.wechat_pay_status = wechat_pay_status; + } + + public String getChongzhi_bg() { + return chongzhi_bg; + } + + public void setChongzhi_bg(String chongzhi_bg) { + this.chongzhi_bg = chongzhi_bg; + } + + private List list; + + public String getMoney() { + return money; + } + + public void setMoney(String money) { + this.money = money; + } + + public String getIncome_money() { + return income_money; + } + + public void setIncome_money(String income_money) { + this.income_money = income_money; + } + + public int getCoin() { + return coin; + } + + public void setCoin(int coin) { + this.coin = coin; + } + + public int getIncome_coin() { + return income_coin; + } + + public void setIncome_coin(int income_coin) { + this.income_coin = income_coin; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public int getIs_first_recharge() { + return is_first_recharge; + } + + public void setIs_first_recharge(int is_first_recharge) { + this.is_first_recharge = is_first_recharge; + } + + public List getGift_bag_list() { + return gift_bag_list; + } + + public void setGift_bag_list(List gift_bag_list) { + this.gift_bag_list = gift_bag_list; + } + + public int getShow_wx_pay_type() { + return show_wx_pay_type; + } + + public void setShow_wx_pay_type(int show_wx_pay_type) { + this.show_wx_pay_type = show_wx_pay_type; + } + + public int getShow_alipay_pay_type() { + return show_alipay_pay_type; + } + + public void setShow_alipay_pay_type(int show_alipay_pay_type) { + this.show_alipay_pay_type = show_alipay_pay_type; + } + + public int getSelected_id() { + return selected_id; + } + + public void setSelected_id(int selected_id) { + this.selected_id = selected_id; + } + + public static class GiftBagListBean { + /** + * commodity_id : 1 + * commodity_name : 8元好礼 + * publicize_text : 总价值28元 + * extend : [{"give":"80金币","title":"价值8元","is_limit_time":1},{"give":"3天会员","title":"5折聊天","is_limit_time":1},{"give":"1张视频卡","title":"免费聊天","is_limit_time":1}] + */ + + private int id; + private String name; + private String publicize_text; + private String extend; + private int give_video_card; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPublicize_text() { + return publicize_text; + } + + public void setPublicize_text(String publicize_text) { + this.publicize_text = publicize_text; + } + + public List getExtend() { + return getExtendList(extend); + } + + public void setExtend(String extend) { + this.extend = extend; + } + + private List getExtendList(String extend) { + Gson gson = new Gson(); + Type type = new TypeToken>() { + }.getType(); + List list = gson.fromJson(extend, type); + return list; + } + + public int getGive_video_card() { + return give_video_card; + } + + public void setGive_video_card(int give_video_card) { + this.give_video_card = give_video_card; + } + } + + public static class GiftExtendBean { + /** + * give : 280金币 + * title : 价值28元 + * is_limit_time : 1 + */ + + private int is_limit_time; + private String give; + private String title; + private String give_new; + + public int getIs_limit_time() { + return is_limit_time; + } + + public void setIs_limit_time(int is_limit_time) { + this.is_limit_time = is_limit_time; + } + + public String getGive() { + return give; + } + + public void setGive(String give) { + this.give = give; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getGive_new() { + return give_new; + } + + public void setGive_new(String give_new) { + this.give_new = give_new; + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDPayBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDPayBean.java new file mode 100644 index 0000000..75ff966 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDPayBean.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.model.settings; + +public class SDPayBean { + public String getWechatpayinfo() { + return wechatpayinfo; + } + + public void setWechatpayinfo(String wechatpayinfo) { + this.wechatpayinfo = wechatpayinfo; + } + + public String getPayinfo() { + return payinfo; + } + + public void setPayinfo(String payinfo) { + this.payinfo = payinfo; + } + + private String wechatpayinfo; + private String payinfo; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDWXPayExtra.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDWXPayExtra.java new file mode 100644 index 0000000..617f02b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDWXPayExtra.java @@ -0,0 +1,48 @@ +package com.fengliyan.tianlesue.model.settings; + +public class SDWXPayExtra { + + /** + * wx_app_id : wxe05c450bb96f4a73 + * gh_ori_id : gh_31bc6d22894d + * path_url : pages/zf/index? + * miniProgramType : 0 + */ + + private String wx_app_id; + private String gh_ori_id; + private String path_url; + private String miniProgramType; + + public String getWx_app_id() { + return wx_app_id; + } + + public void setWx_app_id(String wx_app_id) { + this.wx_app_id = wx_app_id; + } + + public String getGh_ori_id() { + return gh_ori_id; + } + + public void setGh_ori_id(String gh_ori_id) { + this.gh_ori_id = gh_ori_id; + } + + public String getPath_url() { + return path_url; + } + + public void setPath_url(String path_url) { + this.path_url = path_url; + } + + public String getMiniProgramType() { + return miniProgramType; + } + + public void setMiniProgramType(String miniProgramType) { + this.miniProgramType = miniProgramType; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDWXPayInfo.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDWXPayInfo.java new file mode 100644 index 0000000..4e560da --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SDWXPayInfo.java @@ -0,0 +1,218 @@ +package com.fengliyan.tianlesue.model.settings; + +public class SDWXPayInfo { + + /** + * version : 10 + * mer_no : 6888806116928 + * mer_key : xlbkETtrviadpNYfh62TKZZXNoqmGJrrSlEF\/fXOtFwqjfX0WyqqPBQbmEeYfKx3P6rYGmSqYto= + * mer_order_no : 09261045238906 + * create_time : 20220926104514 + * order_amt : 0.01 + * notify_url : https:\/\/www.xiayue.online\/api\/callback\/sand_notify + * return_url : qingyu:\/\/back + * create_ip : 110_184_10_86 + * pay_extra : "{"wx_app_id":"wxe05c450bb96f4a73","gh_ori_id": "gh_31bc6d22894d","path_url":"pages\/zf\/index?","miniProgramType":"0"}" + * accsplit_flag : NO + * sign_type : MD5 + * store_id : 000000 + * extend : {"order_no":"09261045238906"} + * expire_time : 20220926111514 + * goods_name : 600金币 + * product_code : 02010005 + * clear_cycle : 3 + * sign : 088E676E80579DEB0C2B3D13DEBBBB08 + * jump_scheme : sandcash:\/\/scpay + * meta_option : [{"s":"Android","n":"","id":"","sc":""},{"s":"IOS","n":"","id":"","sc":""}] + */ + + private String version; + private String mer_no; + private String mer_key; + private String mer_order_no; + private String create_time; + private double order_amt; + private String notify_url; + private String return_url; + private String create_ip; + private String pay_extra; + private String accsplit_flag; + private String sign_type; + private String store_id; + private String extend; + private String expire_time; + private String goods_name; + private String product_code; + private String clear_cycle; + private String sign; + private String jump_scheme; + private String meta_option; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getMer_no() { + return mer_no; + } + + public void setMer_no(String mer_no) { + this.mer_no = mer_no; + } + + public String getMer_key() { + return mer_key; + } + + public void setMer_key(String mer_key) { + this.mer_key = mer_key; + } + + public String getMer_order_no() { + return mer_order_no; + } + + public void setMer_order_no(String mer_order_no) { + this.mer_order_no = mer_order_no; + } + + public String getCreate_time() { + return create_time; + } + + public void setCreate_time(String create_time) { + this.create_time = create_time; + } + + public double getOrder_amt() { + return order_amt; + } + + public void setOrder_amt(double order_amt) { + this.order_amt = order_amt; + } + + public String getNotify_url() { + return notify_url; + } + + public void setNotify_url(String notify_url) { + this.notify_url = notify_url; + } + + public String getReturn_url() { + return return_url; + } + + public void setReturn_url(String return_url) { + this.return_url = return_url; + } + + public String getCreate_ip() { + return create_ip; + } + + public void setCreate_ip(String create_ip) { + this.create_ip = create_ip; + } + + public String getPay_extra() { + return pay_extra; + } + + public void setPay_extra(String pay_extra) { + this.pay_extra = pay_extra; + } + + public String getAccsplit_flag() { + return accsplit_flag; + } + + public void setAccsplit_flag(String accsplit_flag) { + this.accsplit_flag = accsplit_flag; + } + + public String getSign_type() { + return sign_type; + } + + public void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public String getStore_id() { + return store_id; + } + + public void setStore_id(String store_id) { + this.store_id = store_id; + } + + public String getExtend() { + return extend; + } + + public void setExtend(String extend) { + this.extend = extend; + } + + public String getExpire_time() { + return expire_time; + } + + public void setExpire_time(String expire_time) { + this.expire_time = expire_time; + } + + public String getGoods_name() { + return goods_name; + } + + public void setGoods_name(String goods_name) { + this.goods_name = goods_name; + } + + public String getProduct_code() { + return product_code; + } + + public void setProduct_code(String product_code) { + this.product_code = product_code; + } + + public String getClear_cycle() { + return clear_cycle; + } + + public void setClear_cycle(String clear_cycle) { + this.clear_cycle = clear_cycle; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getJump_scheme() { + return jump_scheme; + } + + public void setJump_scheme(String jump_scheme) { + this.jump_scheme = jump_scheme; + } + + public String getMeta_option() { + return meta_option; + } + + public void setMeta_option(String meta_option) { + this.meta_option = meta_option; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SelfieExampleBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SelfieExampleBean.java new file mode 100644 index 0000000..41465c7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SelfieExampleBean.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.model.settings; + +public class SelfieExampleBean { + private int action_type; + private String action_image; + private int audit_status;//状态 审核状态 0未提交 1审核中 2 审核通过 3 审核不通过 + private String audit_remark; + private String certify_id; + private String face_status;//人脸认证-1未认证0认证中1认证成功2认证失败 + private String face_desc;//人脸认证备注 + + public int getAction_type() { + return action_type; + } + + public void setAction_type(int action_type) { + this.action_type = action_type; + } + + public String getAction_image() { + return action_image; + } + + public void setAction_image(String action_image) { + this.action_image = action_image; + } + + public int getAudit_status() { + return audit_status; + } + + public void setAudit_status(int audit_status) { + this.audit_status = audit_status; + } + + public String getAudit_remark() { + return audit_remark; + } + + public void setAudit_remark(String audit_remark) { + this.audit_remark = audit_remark; + } + + public String getCertify_id() { + return certify_id; + } + + public void setCertify_id(String certify_id) { + this.certify_id = certify_id; + } + + public String getFace_status() { + return face_status; + } + + public void setFace_status(String face_status) { + this.face_status = face_status; + } + + public String getFace_desc() { + return face_desc; + } + + public void setFace_desc(String face_desc) { + this.face_desc = face_desc; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SettingBrandBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SettingBrandBean.java new file mode 100644 index 0000000..a4bae9c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SettingBrandBean.java @@ -0,0 +1,51 @@ +package com.fengliyan.tianlesue.model.settings; + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class SettingBrandBean { + + /** + * "name": "美图", + "icon_url": "images/help/ic_meitu.png", + "image_url": "images/help/meitu.png" + */ + + private String name; + private String icon_url; + private String image_url; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon_url() { + return icon_url; + } + + public void setIcon_url(String icon_url) { + this.icon_url = icon_url; + } + + public String getImage_url() { + return image_url; + } + + public void setImage_url(String image_url) { + this.image_url = image_url; + } + + @Override + public String toString() { + return "SettingBrandBean{" + + "name='" + name + '\'' + + ", icon_url='" + icon_url + '\'' + + ", image_url='" + image_url + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/ShareBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/ShareBean.java new file mode 100644 index 0000000..bb1918f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/ShareBean.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.model.settings; + +public class ShareBean { + private String title; + private String content; + private String url; + private String image_url; + private String url_wechat; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getImage_url() { + return image_url; + } + + public void setImage_url(String image_url) { + this.image_url = image_url; + } + + public String getUrl_wechat() { + return url_wechat; + } + + public void setUrl_wechat(String url_wechat) { + this.url_wechat = url_wechat; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SignDataListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SignDataListBean.java new file mode 100644 index 0000000..03c6aaa --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SignDataListBean.java @@ -0,0 +1,100 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.ArrayList; +import java.util.List; + +public class SignDataListBean { + private int button_status;//按钮状态0去充值1立即签到2已签到 + private String sign_day;//连续签到天数 + private List sign_info = new ArrayList<>(); + + public int getButton_status() { + return button_status; + } + + public void setButton_status(int button_status) { + this.button_status = button_status; + } + + public String getSign_day() { + return sign_day; + } + + public void setSign_day(String sign_day) { + this.sign_day = sign_day; + } + + public List getSign_info() { + return sign_info; + } + + public void setSign_info(List sign_info) { + this.sign_info = sign_info; + } + + public class SignListBean { + private String day; + private String title;//标题 + private String reward;//奖励金币描述 + private String gold_coin;//金币 + private String gold_coin_pic;//金币图片url + private int is_check;//是否勾选0不管1打勾2打叉 + private int is_selected;//是否选中0未选中1选中 + + public String getDay() { + return day; + } + + public void setDay(String day) { + this.day = day; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getReward() { + return reward; + } + + public void setReward(String reward) { + this.reward = reward; + } + + public String getGold_coin() { + return gold_coin; + } + + public void setGold_coin(String gold_coin) { + this.gold_coin = gold_coin; + } + + public String getGold_coin_pic() { + return gold_coin_pic; + } + + public void setGold_coin_pic(String gold_coin_pic) { + this.gold_coin_pic = gold_coin_pic; + } + + public int getIs_check() { + return is_check; + } + + public void setIs_check(int is_check) { + this.is_check = is_check; + } + + public int getIs_selected() { + return is_selected; + } + + public void setIs_selected(int is_selected) { + this.is_selected = is_selected; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SkillIdListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SkillIdListBean.java new file mode 100644 index 0000000..c5ac35b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SkillIdListBean.java @@ -0,0 +1,16 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.ArrayList; +import java.util.List; + +public class SkillIdListBean { + private List skill = new ArrayList<>(); + + public List getSkill() { + return skill; + } + + public void setSkill(List skill) { + this.skill = skill; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SkillSettingBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SkillSettingBean.java new file mode 100644 index 0000000..d249565 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SkillSettingBean.java @@ -0,0 +1,76 @@ +package com.fengliyan.tianlesue.model.settings; + +public class SkillSettingBean { + private int id; + private int skill_id; + private String name; + private String icon; + private String price; + private String score; + private int service_count; + private int service_time; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getSkill_id() { + return skill_id; + } + + public void setSkill_id(int skill_id) { + this.skill_id = skill_id; + } + + public String getSkill_name() { + return name; + } + + public void setSkill_name(String skill_name) { + this.name = skill_name; + } + + public String getSkill_icon() { + return icon; + } + + public void setSkill_icon(String skill_icon) { + this.icon = skill_icon; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getScore() { + return score; + } + + public void setScore(String score) { + this.score = score; + } + + public int getService_count() { + return service_count; + } + + public void setService_count(int service_count) { + this.service_count = service_count; + } + + public int getService_time() { + return service_time; + } + + public void setService_time(int service_time) { + this.service_time = service_time; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SocialBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SocialBean.java new file mode 100644 index 0000000..94cdaa4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SocialBean.java @@ -0,0 +1,140 @@ +package com.fengliyan.tianlesue.model.settings; + +public class SocialBean { + private int userid; + private String usercode; + private String nickname; + private String avatar; + private int gender; + private int age; + private int is_follow = 1; + private int is_fans; + private String add_time; + private String create_time; + private String city; + private int is_watch = 1; + private int vip = 2; + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getIs_follow() { + return is_follow; + } + + public void setIs_follow(int is_follow) { + this.is_follow = is_follow; + } + + public String getAdd_time() { + return add_time; + } + + public void setAdd_time(String add_time) { + this.add_time = add_time; + } + + public int getIs_watch() { + return is_watch; + } + + public void setIs_watch(int is_watch) { + this.is_watch = is_watch; + } + + public int getIs_fans() { + return is_fans; + } + + public void setIs_fans(int is_fans) { + this.is_fans = is_fans; + } + + public String getCreate_time() { + return create_time; + } + + public void setCreate_time(String create_time) { + this.create_time = create_time; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public int getVip() { + return vip; + } + + public void setVip(int vip) { + this.vip = vip; + } + + @Override + public String toString() { + return "SocialBean{" + + "userid=" + userid + + ", usercode='" + usercode + '\'' + + ", nickname='" + nickname + '\'' + + ", avatar='" + avatar + '\'' + + ", gender=" + gender + + ", age=" + age + + ", is_follow=" + is_follow + + ", is_fans=" + is_fans + + ", add_time='" + add_time + '\'' + + ", create_time='" + create_time + '\'' + + ", city='" + city + '\'' + + ", is_watch=" + is_watch + + ", vip=" + vip + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/SocialListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SocialListBean.java new file mode 100644 index 0000000..dfb7504 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/SocialListBean.java @@ -0,0 +1,25 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.ArrayList; +import java.util.List; + +public class SocialListBean { + private List list = new ArrayList<>(); + private int total; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserCountBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserCountBean.java new file mode 100644 index 0000000..5a696e1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserCountBean.java @@ -0,0 +1,58 @@ +package com.fengliyan.tianlesue.model.settings; + +public class UserCountBean { + private int fans_count; + private int new_fans_count; + private int follow_count; + private String visitor_count; + private int new_visitor_count; + private String footprint_count; + + public int getFans_count() { + return fans_count; + } + + public void setFans_count(int fans_count) { + this.fans_count = fans_count; + } + + public int getNew_fans_count() { + return new_fans_count; + } + + public void setNew_fans_count(int new_fans_count) { + this.new_fans_count = new_fans_count; + } + + public int getFollow_count() { + return follow_count; + } + + public void setFollow_count(int follow_count) { + this.follow_count = follow_count; + } + + public String getVisitor_count() { + return visitor_count; + } + + public void setVisitor_count(String visitor_count) { + this.visitor_count = visitor_count; + } + + public int getNew_visitor_count() { + return new_visitor_count; + } + + public void setNew_visitor_count(int new_visitor_count) { + this.new_visitor_count = new_visitor_count; + } + + public String getFootprint_count() { + return footprint_count; + } + + public void setFootprint_count(String footprint_count) { + this.footprint_count = footprint_count; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserFrameBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserFrameBean.java new file mode 100644 index 0000000..6d1110c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserFrameBean.java @@ -0,0 +1,52 @@ +package com.fengliyan.tianlesue.model.settings; + +public class UserFrameBean { + private Bean profile_frame;// 头像框 + private Bean bubble_frame;// 气泡框 + + public Bean getProfile_frame() { + return profile_frame; + } + + public void setProfile_frame(Bean profile_frame) { + this.profile_frame = profile_frame; + } + + public Bean getBubble_frame() { + return bubble_frame; + } + + public void setBubble_frame(Bean bubble_frame) { + this.bubble_frame = bubble_frame; + } + + public class Bean { + private String img;// 图片地址 + private String effect;// 特效地址 + private String to_img;//接受者图片 + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public String getTo_img() { + return to_img; + } + + public void setTo_img(String to_img) { + this.to_img = to_img; + } + + public String getEffect() { + return effect; + } + + public void setEffect(String effect) { + this.effect = effect; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserHomeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserHomeBean.java new file mode 100644 index 0000000..9a7535b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserHomeBean.java @@ -0,0 +1,135 @@ +package com.fengliyan.tianlesue.model.settings; + +import com.google.gson.annotations.SerializedName; +import com.fengliyan.tianlesue.model.main.BannerBean; + +import java.io.Serializable; +import java.util.List; + +public class UserHomeBean { + private String tip; + private String hide_read_msg; + private UserInfoBean userinfo; + private UserCountBean usercount; + /** + * switch : {"open_video_status":0,"hide_service_num":1} + */ + + @SerializedName("switch") + private SwitchBean switchX; + private IpInfo ip_info; + private List banner; + + public String getTip() { + return tip; + } + + public void setTip(String tip) { + this.tip = tip; + } + + public String getHide_read_msg() { + return hide_read_msg; + } + + public void setHide_read_msg(String hide_read_msg) { + this.hide_read_msg = hide_read_msg; + } + + public UserInfoBean getUserinfo() { + return userinfo; + } + + public void setUserinfo(UserInfoBean userinfo) { + this.userinfo = userinfo; + } + + public UserCountBean getUsercount() { + return usercount; + } + + public void setUsercount(UserCountBean usercount) { + this.usercount = usercount; + } + + public SwitchBean getSwitchX() { + return switchX; + } + + public void setSwitchX(SwitchBean switchX) { + this.switchX = switchX; + } + + public IpInfo getIp_info() { + return ip_info; + } + + public void setIp_info(IpInfo ip_info) { + this.ip_info = ip_info; + } + + public List getBanner() { + return banner; + } + + public void setBanner(List banner) { + this.banner = banner; + } + + public static class SwitchBean { + /** + * open_video_status : 0 + * hide_service_num : 1 + */ + + private int open_video_status; + private int hide_service_num; + + public int getOpen_video_status() { + return open_video_status; + } + + public void setOpen_video_status(int open_video_status) { + this.open_video_status = open_video_status; + } + + public int getHide_service_num() { + return hide_service_num; + } + + public void setHide_service_num(int hide_service_num) { + this.hide_service_num = hide_service_num; + } + } + + public class IpInfo implements Serializable { + + private String province; + private String city; + private String city_id; + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCity_id() { + return city_id; + } + + public void setCity_id(String city_id) { + this.city_id = city_id; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserInfoBean.java new file mode 100644 index 0000000..0cff658 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/UserInfoBean.java @@ -0,0 +1,359 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.List; + +public class UserInfoBean { + private String usercode; + private String nickname; + private int type; + private String mobile; + private String avatar; + private int gender; + private int age; + private String birthday; + private String city; + private int finish_status; + private String im_token; + private int is_anchor; + private int is_face_status;// 人脸认证 0未认证 1认证 + private String token; + private int user_id; + private int userid; + private long createtime; + private long expiretime; + private long expires_in; + private String dateline; + private int vip = 2; + private List album_list; + private int video_status;//0 未审核、1=审核通过、2=审核未通过 + private String video_url; + private String video_cover_url; + + private String edit_nickname_tip; + private String nickname_tip; + private int mark;//0无标识1真人标识 2新人标识 + private int is_mobile;//1手机号为空 2存在手机号 + private int real_name_status; + private int avatar_hide;//男生vip是否显示头像框 0.显示 1.隐藏 + private int newer_win_status;//新用户弹窗标识:1=新用户、0=旧用户 + private String job; + private String signature; + private UserFrameBean user_frame; + private int user_type; + + public int getUser_type() { + return user_type; + } + + public void setUser_type(int user_type) { + this.user_type = user_type; + } + + public int getMark() { + return mark; + } + + public void setMark(int mark) { + this.mark = mark; + } + + public int getIs_mobile() { + return is_mobile; + } + + public void setIs_mobile(int is_mobile) { + this.is_mobile = is_mobile; + } + + public String getEdit_nickname_tip() { + return edit_nickname_tip; + } + + public void setEdit_nickname_tip(String edit_nickname_tip) { + this.edit_nickname_tip = edit_nickname_tip; + } + + public String getNickname_tip() { + return nickname_tip; + } + + public void setNickname_tip(String nickname_tip) { + this.nickname_tip = nickname_tip; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getBirthday() { + return birthday; + } + + public void setBirthday(String birthday) { + this.birthday = birthday; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public int getFinish_status() { + return finish_status; + } + + public void setFinish_status(int finish_status) { + this.finish_status = finish_status; + } + + public String getIm_token() { + return im_token; + } + + public void setIm_token(String im_token) { + this.im_token = im_token; + } + + public int getIs_anchor() { + return is_anchor; + } + + public void setIs_anchor(int is_anchor) { + this.is_anchor = is_anchor; + } + + public int getIs_face_status() { + return is_face_status; + } + + public void setIs_face_status(int is_face_status) { + this.is_face_status = is_face_status; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public long getCreatetime() { + return createtime; + } + + public void setCreatetime(long createtime) { + this.createtime = createtime; + } + + public long getExpiretime() { + return expiretime; + } + + public void setExpiretime(long expiretime) { + this.expiretime = expiretime; + } + + public long getExpires_in() { + return expires_in; + } + + public void setExpires_in(long expires_in) { + this.expires_in = expires_in; + } + + public List getAlbum_list() { + return album_list; + } + + public void setAlbum_list(List album_list) { + this.album_list = album_list; + } + + public String getDateline() { + return dateline; + } + + public void setDateline(String dateline) { + this.dateline = dateline; + } + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public int getVip() { + return vip; + } + + public void setVip(int vip) { + this.vip = vip; + } + + public int getVideo_status() { + return video_status; + } + + public void setVideo_status(int video_status) { + this.video_status = video_status; + } + + public String getVideo_url() { + return video_url; + } + + public void setVideo_url(String video_url) { + this.video_url = video_url; + } + + public String getVideo_cover_url() { + return video_cover_url; + } + + public void setVideo_cover_url(String video_cover_url) { + this.video_cover_url = video_cover_url; + } + + public int getReal_name_status() { + return real_name_status; + } + + public void setReal_name_status(int real_name_status) { + this.real_name_status = real_name_status; + } + + public int getAvatar_hide() { + return avatar_hide; + } + + public void setAvatar_hide(int avatar_hide) { + this.avatar_hide = avatar_hide; + } + + public int getNewer_win_status() { + return newer_win_status; + } + + public void setNewer_win_status(int newer_win_status) { + this.newer_win_status = newer_win_status; + } + + public String getJob() { + return job; + } + + public void setJob(String job) { + this.job = job; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public UserFrameBean getUser_frame() { + return user_frame; + } + + public void setUser_frame(UserFrameBean user_frame) { + this.user_frame = user_frame; + } + + @Override + public String toString() { + return "UserInfoBean{" + + "usercode='" + usercode + '\'' + + ", nickname='" + nickname + '\'' + + ", type=" + type + + ", mobile='" + mobile + '\'' + + ", avatar='" + avatar + '\'' + + ", gender=" + gender + + ", age=" + age + + ", birthday='" + birthday + '\'' + + ", city='" + city + '\'' + + ", finish_status=" + finish_status + + ", im_token='" + im_token + '\'' + + ", is_anchor=" + is_anchor + + ", token='" + token + '\'' + + ", user_id=" + user_id + + ", userid=" + userid + + ", createtime=" + createtime + + ", expiretime=" + expiretime + + ", expires_in=" + expires_in + + ", dateline='" + dateline + '\'' + + ", vip=" + vip + + ", album_list=" + album_list + + '}'; + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/VideoRecordBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/VideoRecordBean.java new file mode 100644 index 0000000..a0dcb94 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/VideoRecordBean.java @@ -0,0 +1,21 @@ +package com.fengliyan.tianlesue.model.settings; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/22. + */ + +public class VideoRecordBean { + + private List list = new ArrayList<>(); + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/VideoRecordListBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/VideoRecordListBean.java new file mode 100644 index 0000000..a23b529 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/VideoRecordListBean.java @@ -0,0 +1,223 @@ +package com.fengliyan.tianlesue.model.settings; + +import com.fengliyan.tianlesue.model.main.SkillBean; + +/** + * Created by zhangbin on 2019/2/22. + */ + +public class VideoRecordListBean { + + /** + "id":4480, + "type":1, + "otherType":0, + "calltype":1, + "status":4, + "status_txt":"已接通", + "call_time":118, + "call_amount":"100.00", + "call_income":"70.00", + "skill":{ + "id":5, + "name":"看相占卜", + "icon":"images/skill/5.png", + "status":0 + }, + "userid":200, + "usercode":"106884", + "nickname":"私语106884", + "avatar":"uploads/album/201812/11/6aa0cd16cf54fe44329ca61e5548ac1e.jpg", + "gender":1, + "age":19, + "city":"深圳", + "create_time":"2019-02-21 20:10:01" + */ + + private int id; + private int type; //类型 1 主打者 2 被打者 + private int otherType; + private int calltype; //拨打类型: 1 视频 2 语音 + private int status; //状态:1 取消 2 拒绝 3 超时 4 已接通 + private String status_txt; + private int call_time; + private String call_amount; + private String call_income; + private SkillBean skill; + private int userid; + private String usercode; + private String nickname; + private String avatar; + private int gender; + private int age; + private String city; + private String create_time; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getOtherType() { + return otherType; + } + + public void setOtherType(int otherType) { + this.otherType = otherType; + } + + public int getCalltype() { + return calltype; + } + + public void setCalltype(int calltype) { + this.calltype = calltype; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getStatus_txt() { + return status_txt; + } + + public void setStatus_txt(String status_txt) { + this.status_txt = status_txt; + } + + public int getCall_time() { + return call_time; + } + + public void setCall_time(int call_time) { + this.call_time = call_time; + } + + public String getCall_amount() { + return call_amount; + } + + public void setCall_amount(String call_amount) { + this.call_amount = call_amount; + } + + public String getCall_income() { + return call_income; + } + + public void setCall_income(String call_income) { + this.call_income = call_income; + } + + public SkillBean getSkill() { + return skill; + } + + public void setSkill(SkillBean skill) { + this.skill = skill; + } + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCreate_time() { + return create_time; + } + + public void setCreate_time(String create_time) { + this.create_time = create_time; + } + + @Override + public String toString() { + return "VideoRecordListBean{" + + "id=" + id + + ", type=" + type + + ", otherType=" + otherType + + ", calltype=" + calltype + + ", status=" + status + + ", status_txt='" + status_txt + '\'' + + ", call_time=" + call_time + + ", call_amount='" + call_amount + '\'' + + ", call_income='" + call_income + '\'' + + ", skill=" + skill + + ", userid=" + userid + + ", usercode='" + usercode + '\'' + + ", nickname='" + nickname + '\'' + + ", avatar='" + avatar + '\'' + + ", gender=" + gender + + ", age=" + age + + ", city='" + city + '\'' + + ", create_time='" + create_time + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/WXAccountStatusBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WXAccountStatusBean.java new file mode 100644 index 0000000..5d6fe0a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WXAccountStatusBean.java @@ -0,0 +1,100 @@ +package com.fengliyan.tianlesue.model.settings; + +import android.os.Parcel; +import android.os.Parcelable; + +public class WXAccountStatusBean implements Parcelable { + private String content; + private String image; + private int state; + private String price; + private int up_status; + + public String getUp_price_time() { + return up_price_time; + } + + public void setUp_price_time(String up_price_time) { + this.up_price_time = up_price_time; + } + + private String up_price_time; + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public int getState() { + return state; + } + + public void setState(int state) { + this.state = state; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public int getUp_status() { + return up_status; + } + + public void setUp_status(int up_status) { + this.up_status = up_status; + } + + public WXAccountStatusBean() { + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.content); + dest.writeString(this.image); + dest.writeInt(this.state); + dest.writeString(this.price); + dest.writeInt(this.up_status); + dest.writeString(this.up_price_time); + } + + protected WXAccountStatusBean(Parcel in) { + this.content = in.readString(); + this.image = in.readString(); + this.state = in.readInt(); + this.price = in.readString(); + this.up_status = in.readInt(); + this.up_price_time = in.readString(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public WXAccountStatusBean createFromParcel(Parcel source) { + return new WXAccountStatusBean(source); + } + + @Override + public WXAccountStatusBean[] newArray(int size) { + return new WXAccountStatusBean[size]; + } + }; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/WXPayTypeBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WXPayTypeBean.java new file mode 100644 index 0000000..9c553f4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WXPayTypeBean.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.model.settings; + +public class WXPayTypeBean { + private int wechat_type; //type=3 //汇付小程序 + + private String gh_ori_id;//小程序原始id + private int mini_program_type;//0-正式版 1-开发版 2-体验版 + + public int getWechat_type() { + return wechat_type; + } + + public void setWechat_type(int wechat_type) { + this.wechat_type = wechat_type; + } + + public String getGh_ori_id() { + return gh_ori_id; + } + + public void setGh_ori_id(String gh_ori_id) { + this.gh_ori_id = gh_ori_id; + } + + public int getMini_program_type() { + return mini_program_type; + } + + public void setMini_program_type(int mini_program_type) { + this.mini_program_type = mini_program_type; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/WalletDataBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WalletDataBean.java new file mode 100644 index 0000000..a64efa4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WalletDataBean.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.model.settings; + +public class WalletDataBean { + private String money; + private String income_money; + private int coin; + private int income_coin; + private String total_buy_money; + private int total_buy_coin; + private int status; + + public String getMoney() { + return money; + } + + public void setMoney(String money) { + this.money = money; + } + + public String getIncome_money() { + return income_money; + } + + public void setIncome_money(String income_money) { + this.income_money = income_money; + } + + public int getCoin() { + return coin; + } + + public void setCoin(int coin) { + this.coin = coin; + } + + public int getIncome_coin() { + return income_coin; + } + + public void setIncome_coin(int income_coin) { + this.income_coin = income_coin; + } + + public String getTotal_buy_money() { + return total_buy_money; + } + + public void setTotal_buy_money(String total_buy_money) { + this.total_buy_money = total_buy_money; + } + + public int getTotal_buy_coin() { + return total_buy_coin; + } + + public void setTotal_buy_coin(int total_buy_coin) { + this.total_buy_coin = total_buy_coin; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/WalletIndexBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WalletIndexBean.java new file mode 100644 index 0000000..fea8481 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WalletIndexBean.java @@ -0,0 +1,13 @@ +package com.fengliyan.tianlesue.model.settings; + +public class WalletIndexBean { + private WalletDataBean account; + + public WalletDataBean getAccount() { + return account; + } + + public void setAccount(WalletDataBean account) { + this.account = account; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/WeChatPayInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WeChatPayInfoBean.java new file mode 100644 index 0000000..35c0b46 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WeChatPayInfoBean.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.model.settings; + +/** + * Created by zhangbin on 2018/12/19. + */ + +public class WeChatPayInfoBean { + + private String appid; //appid + private String mch_id; //商户号 + private String nonce_str; //随机字符串 + private String paySign; //签名 + private String prepay_id; //预付款id + private long timestamp; + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getPaySign() { + return paySign; + } + + public void setPaySign(String paySign) { + this.paySign = paySign; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public String toString() { + return "WeChatPayInfoBean{" + + "appid='" + appid + '\'' + + ", mch_id='" + mch_id + '\'' + + ", nonce_str='" + nonce_str + '\'' + + ", paySign='" + paySign + '\'' + + ", prepay_id='" + prepay_id + '\'' + + ", timestamp=" + timestamp + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/settings/WithdrawInfoBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WithdrawInfoBean.java new file mode 100644 index 0000000..867691c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/settings/WithdrawInfoBean.java @@ -0,0 +1,110 @@ +package com.fengliyan.tianlesue.model.settings; + +import android.text.TextUtils; + +import java.util.List; + +public class WithdrawInfoBean { + private double money; + private double income_money; + private int max_money; + private String alipay_account; + private int alipay_status; + private int min_money; + + public String getWithdraw_alipay_rate() { + if (TextUtils.isEmpty(withdraw_alipay_rate)){ + return ""; + } + return withdraw_alipay_rate; + } + + public void setWithdraw_alipay_rate(String withdraw_alipay_rate) { + this.withdraw_alipay_rate = withdraw_alipay_rate; + } + + public String getWithdraw_bank_rate() { + if (TextUtils.isEmpty(withdraw_bank_rate)){ + return ""; + } + return withdraw_bank_rate; + } + + public void setWithdraw_bank_rate(String withdraw_bank_rate) { + this.withdraw_bank_rate = withdraw_bank_rate; + } + + private String withdraw_alipay_rate; + private String withdraw_bank_rate; + + List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public int getMin_money() { + return min_money; + } + + public void setMin_money(int min_money) { + this.min_money = min_money; + } + + public double getMoney() { + return money; + } + + public void setMoney(double money) { + this.money = money; + } + + public double getIncome_money() { + return income_money; + } + + public void setIncome_money(double income_money) { + this.income_money = income_money; + } + + public int getMax_money() { + return max_money; + } + + public void setMax_money(int max_money) { + this.max_money = max_money; + } + + public String getAlipay_account() { + return alipay_account; + } + + public void setAlipay_account(String alipay_account) { + this.alipay_account = alipay_account; + } + + public int getAlipay_status() { + return alipay_status; + } + + public void setAlipay_status(int alipay_status) { + this.alipay_status = alipay_status; + } + + @Override + public String toString() { + return "WithdrawInfoBean{" + + "money=" + money + + ", income_money=" + income_money + + ", max_money=" + max_money + + ", alipay_account='" + alipay_account + '\'' + + ", alipay_status=" + alipay_status + + ", min_money=" + min_money + + ", list=" + list + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/user/bean/BaseUserInfo.java b/app/src/main/java/com/fengliyan/tianlesue/model/user/bean/BaseUserInfo.java new file mode 100644 index 0000000..2b0c8a3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/user/bean/BaseUserInfo.java @@ -0,0 +1,248 @@ +package com.fengliyan.tianlesue.model.user.bean; + +/** + * Created by abby on 2018/4/7. + */ + +public class BaseUserInfo { + + /** + * "usercode":"101223", + * "nickname":"111111", + * "type":0, + * "mobile":"130****1017", + * "avatar":"uploads/album/201809/02/b38a3845d6291fbe869d63b42134e642.jpg", + * "gender":2, + * "age":6, + * "birthday":"2012-01-01", + * "city":"北京", + * "finish_status":1, + * "im_token":"8144d5aa-389d-48d2-acda-b2cf8a27115d", + * "is_anchor":0, + * "invite_code":"105647", + * "token":"94ea021c-6e4c-4863-827b-2487156517b6", + * "user_id":241, + * "createtime":1543907842, + * "expiretime":1546499842, + * "expires_in":2592000 + */ + + private String usercode; + private String nickname; + private int type; + private int user_type;// 用户类型: 0普通用户 1 内部用户 2 审核人员账号 + private String mobile; + private String avatar; + private int gender; //1 女 + private int age; + private String birthday; + private String city; + private int finish_status; + private String im_token; + private int is_anchor;//0-未认证,1-已认证 + private int is_face_status;// 人脸认证 0未认证 1认证 + private String invite_code; + private String token; + private int user_id; + private int createtime; + private int expiretime; + private int expires_in; + private int real_name_status; + + public String getBirthday() { + return birthday; + } + + public void setBirthday(String birthday) { + this.birthday = birthday; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getUsercode() { + return usercode; + } + + public void setUsercode(String usercode) { + this.usercode = usercode; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public int getGender() { + return gender; + } + + public boolean isWomen() { + return gender == 1; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getFinish_status() { + return finish_status; + } + + public void setFinish_status(int finish_status) { + this.finish_status = finish_status; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public int getCreatetime() { + return createtime; + } + + public void setCreatetime(int createtime) { + this.createtime = createtime; + } + + public int getExpiretime() { + return expiretime; + } + + public void setExpiretime(int expiretime) { + this.expiretime = expiretime; + } + + public int getExpires_in() { + return expires_in; + } + + public void setExpires_in(int expires_in) { + this.expires_in = expires_in; + } + + public String getIm_token() { + return im_token; + } + + public void setIm_token(String im_token) { + this.im_token = im_token; + } + + public int getIs_anchor() { + return is_anchor; + } + + public void setIs_anchor(int is_anchor) { + this.is_anchor = is_anchor; + } + + public int getIs_face_status() { + return is_face_status; + } + + public void setIs_face_status(int is_face_status) { + this.is_face_status = is_face_status; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getUser_type() { + return user_type; + } + + public void setUser_type(int user_type) { + this.user_type = user_type; + } + + public String getInvite_code() { + return invite_code; + } + + public void setInvite_code(String invite_code) { + this.invite_code = invite_code; + } + + public int getReal_name_status() { + return real_name_status; + } + + public void setReal_name_status(int real_name_status) { + this.real_name_status = real_name_status; + } + + @Override + public String toString() { + return "BaseUserInfo{" + + "usercode='" + usercode + '\'' + + ", nickname='" + nickname + '\'' + + ", type=" + type + + ", mobile='" + mobile + '\'' + + ", avatar='" + avatar + '\'' + + ", gender=" + gender + + ", age=" + age + + ", birthday='" + birthday + '\'' + + ", city='" + city + '\'' + + ", finish_status=" + finish_status + + ", im_token='" + im_token + '\'' + + ", is_anchor=" + is_anchor + + ", invite_code='" + invite_code + '\'' + + ", token='" + token + '\'' + + ", user_id='" + user_id + '\'' + + ", createtime='" + createtime + '\'' + + ", expiretime='" + expiretime + '\'' + + ", expires_in='" + expires_in + '\'' + + '}'; + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/user/bean/UserLiteBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/user/bean/UserLiteBean.java new file mode 100644 index 0000000..fd8a5fe --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/user/bean/UserLiteBean.java @@ -0,0 +1,128 @@ +package com.fengliyan.tianlesue.model.user.bean; + +/** + * Created by zhangbin on 2019/3/21. + */ + +public class UserLiteBean { + + /** + * "userid":259, + "nickname":"私语哈", + "age":18, + "gender":2, + "avatar":"uploads/album/201902/16/d4265cc7689c4057b6e011227b8c2973_.pic.jpg", + "city":"深圳", + "love_value":0, + "wealth_value":32820, + "account_value":298644, + "is_anchor":0 + */ + + private int userid; + private String nickname; + private int age; + private int gender; + private String avatar; + private String city; + private int love_value; + private int wealth_value; + private int account_value; + private int is_anchor; + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public int getLove_value() { + return love_value; + } + + public void setLove_value(int love_value) { + this.love_value = love_value; + } + + public int getWealth_value() { + return wealth_value; + } + + public void setWealth_value(int wealth_value) { + this.wealth_value = wealth_value; + } + + public int getAccount_value() { + return account_value; + } + + public void setAccount_value(int account_value) { + this.account_value = account_value; + } + + public int getIs_anchor() { + return is_anchor; + } + + public void setIs_anchor(int is_anchor) { + this.is_anchor = is_anchor; + } + + @Override + public String toString() { + return "UserLiteBean{" + + "userid=" + userid + + ", nickname='" + nickname + '\'' + + ", age=" + age + + ", gender=" + gender + + ", avatar='" + avatar + '\'' + + ", city='" + city + '\'' + + ", love_value=" + love_value + + ", wealth_value=" + wealth_value + + ", account_value=" + account_value + + ", is_anchor=" + is_anchor + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/model/webSocket/RedEnvelopesSocketBean.java b/app/src/main/java/com/fengliyan/tianlesue/model/webSocket/RedEnvelopesSocketBean.java new file mode 100644 index 0000000..aad7d5c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/model/webSocket/RedEnvelopesSocketBean.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.model.webSocket; + +/** + * ying 2021/1/27 + * Describe :红包bean + */ + +public class RedEnvelopesSocketBean { + + /**红包id + * rpId : 1 + */ + + public String rpId; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/receiver/NotificationReceiver.java b/app/src/main/java/com/fengliyan/tianlesue/receiver/NotificationReceiver.java new file mode 100644 index 0000000..fa46b08 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/receiver/NotificationReceiver.java @@ -0,0 +1,28 @@ +package com.fengliyan.tianlesue.receiver; + +import android.app.NotificationManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import com.fengliyan.tianlesue.utils.RTCMediaUtils; + + +public class NotificationReceiver extends BroadcastReceiver { + public static final String TYPE = "notification_type"; + + @Override + public final void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + int type = intent.getIntExtra(TYPE, -1); + if (type != -1) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(type); + Log.e("lidz", "type !=" + type); + } + if (action.equals("notification_cancelled")) { + RTCMediaUtils.stopNotificationMusic(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/service/CallService.java b/app/src/main/java/com/fengliyan/tianlesue/service/CallService.java new file mode 100644 index 0000000..7002bdf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/service/CallService.java @@ -0,0 +1,132 @@ +package com.fengliyan.tianlesue.service; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.IBinder; + +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.view.main.AgoraWithFUVideoActivity; + +/** + * ying 2020/6/29 + * Describe :电话服务 + */ + +public class CallService extends Service { + public static void getInstance(Context context, CallBean result) { + Intent intent = new Intent(context, CallService.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + + intent.putExtra("isCaller", true); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + if (result.getGuard() != null) { + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + } + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + // context.startActivity(intent); + context.startService(intent); + } + + public static void getInstanceNo(Context context, Intent intent) { + String myChannelId = "iot"; + String myChannelName = "告警通知服务"; + NotificationManager manager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); + Notification notification = null; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(myChannelId, myChannelName, + NotificationManager.IMPORTANCE_LOW); + manager.createNotificationChannel(channel); + notification = new NotificationCompat.Builder(context, myChannelId) + .setContentTitle("测试") + .setContentText("一个新消息") + .setWhen(System.currentTimeMillis()) + .setShowWhen(true) + .setSmallIcon(R.mipmap.ic_launcher) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setCategory(NotificationCompat.CATEGORY_CALL) + .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher)) + .setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)) + .setAutoCancel(true) + .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE) + .build(); + + } else { + notification = new NotificationCompat.Builder(context, myChannelId) + .setContentTitle("This is a title") + .setContentText("This is a context") + .setWhen(System.currentTimeMillis()) + .setSmallIcon(R.mipmap.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher)) + .build(); + } + manager.notify(1, notification); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Intent fullScreenIntent = new Intent(this, AgoraWithFUVideoActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Constant.SOCKET_URL, intent.getStringExtra(Constant.SOCKET_URL)); + + intent.putExtra("isCaller", true); + intent.putExtra("roomId", intent.getIntExtra("roomId", 0)); + intent.putExtra("avatar", intent.getStringExtra("avatar")); + intent.putExtra("nickName", intent.getStringExtra("nickName")); + intent.putExtra("price", intent.getStringExtra("price")); + intent.putExtra("toUid", intent.getIntExtra("toUid", 0)); + intent.putExtra("porn_check_bean_v2", intent.getSerializableExtra("porn_check_bean_v2")); + + if (intent.getIntExtra("diff_num", 0) != 0) { + intent.putExtra("diff_num", intent.getIntExtra("diff_num", 0)); + intent.putExtra("guard_price", intent.getIntExtra("guard_price", 0)); + } + PendingIntent fullScreenPendingIntent = PendingIntent.getActivity( + this, 0, + fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT + ); + + Notification notificationBuilder = new NotificationCompat.Builder(this, "channelId") + .setSmallIcon(R.mipmap.ic_launcher_round) + .setContentTitle(getString(R.string.app_name)) + .setContentText("启动BackgroundActivity") + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setCategory(NotificationCompat.CATEGORY_CALL) + +// Use a full-screen intent only for the highest-priority alerts where you +// have an associated activity that you would like to launch after the user +// interacts with the notification. Also, if your app targets Android Q, you +// need to request the USE_FULL_SCREEN_INTENT permission in order for the +// platform to invoke this notification. + .setFullScreenIntent(fullScreenPendingIntent, true) + .build(); + +// The integer ID that you give to startForeground() must not be 0. + startForeground(1, notificationBuilder); + return super.onStartCommand(intent, flags, startId); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/service/HwService.java b/app/src/main/java/com/fengliyan/tianlesue/service/HwService.java new file mode 100644 index 0000000..936bde4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/service/HwService.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.service; + +import com.huawei.hms.push.RemoteMessage; +import com.netease.nimlib.mixpush.hw.HWPushService; + +/** + * ying 2020/7/16 + * Describe :华为推送测试 + */ + +public class HwService extends HWPushService { + private static final String TAG = "PushDemoLog"; + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + super.onMessageReceived(remoteMessage); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/service/LocalService.java b/app/src/main/java/com/fengliyan/tianlesue/service/LocalService.java new file mode 100644 index 0000000..aa7be6b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/service/LocalService.java @@ -0,0 +1,91 @@ +package com.fengliyan.tianlesue.service; + +import android.app.Notification; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Build; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.fengliyan.tianlesue.aidl.IMyAidlInterface; + + +/** + * Created by zhangbin on 2018/12/11. + */ + +public class LocalService extends Service { + + private MyBinder mBinder; + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); + try { + Log.i("LocalService", "connected with " + iMyAidlInterface.getServiceName()); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { +// Toast.makeText(LocalService.this,"链接断开,重新启动 RemoteService",Toast.LENGTH_LONG).show(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(new Intent(LocalService.this,RemoteService.class)); + } else { + // Pre-O behavior. + startService(new Intent(LocalService.this,RemoteService.class)); + } +// startService(new Intent(LocalService.this,RemoteService.class)); + bindService(new Intent(LocalService.this,RemoteService.class),connection, Context.BIND_IMPORTANT); + } + }; + + public LocalService() { + } + +// @Override +// public void onCreate() { +// super.onCreate(); +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +// startForeground(666,new Notification()); //这个id不要和应用内的其他同志id一样,不行就写 int.maxValue() //context.startForeground(SERVICE_ID, builder.getNotification()); +// } +// } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { +// Toast.makeText(this,"LocalService 启动",Toast.LENGTH_LONG).show(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(new Intent(LocalService.this,RemoteService.class)); + startForeground(666,new Notification()); //这个id不要和应用内的其他同志id一样,不行就写 int.maxValue() + } else { + // Pre-O behavior. + startService(new Intent(LocalService.this,RemoteService.class)); + } + bindService(new Intent(this,RemoteService.class),connection, Context.BIND_IMPORTANT); + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + mBinder = new MyBinder(); + return mBinder; + } + + private class MyBinder extends IMyAidlInterface.Stub{ + + @Override + public String getServiceName() throws RemoteException { + return LocalService.class.getName(); + } + + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/service/RemoteService.java b/app/src/main/java/com/fengliyan/tianlesue/service/RemoteService.java new file mode 100644 index 0000000..37db9ad --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/service/RemoteService.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.service; + +import android.app.Notification; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Build; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.fengliyan.tianlesue.aidl.IMyAidlInterface; + +/** + * Created by zhangbin on 2018/12/11. + */ + +public class RemoteService extends Service { + + private MyBinder mBinder; + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); + try { + Log.i("RemoteService", "connected with " + iMyAidlInterface.getServiceName()); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { +// Toast.makeText(RemoteService.this,"链接断开,重新启动 LocalService",Toast.LENGTH_LONG).show(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(new Intent(RemoteService.this,LocalService.class)); + } else { + // Pre-O behavior. + startService(new Intent(RemoteService.this,LocalService.class)); + } +// startService(new Intent(RemoteService.this,LocalService.class)); + bindService(new Intent(RemoteService.this,LocalService.class),connection, Context.BIND_IMPORTANT); + } + }; + + public RemoteService() { + } + +// @Override +// public void onCreate() { +// super.onCreate(); +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +// startForeground(777,new Notification()); //这个id不要和应用内的其他同志id一样,不行就写 int.maxValue() //context.startForeground(SERVICE_ID, builder.getNotification()); +// } +// } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { +// Toast.makeText(this,"RemoteService 启动",Toast.LENGTH_LONG).show(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForeground(777, new Notification()); //这个id不要和应用内的其他同志id一样,不行就写 int.maxValue() //context.startForeground(SERVICE_ID, builder.getNotification()); + } + bindService(new Intent(this,LocalService.class),connection,Context.BIND_IMPORTANT); + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + mBinder = new MyBinder(); + return mBinder; + } + + private class MyBinder extends IMyAidlInterface.Stub{ + + @Override + public String getServiceName() throws RemoteException { + return RemoteService.class.getName(); + } + + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/AESUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/AESUtils.java new file mode 100644 index 0000000..6a01671 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/AESUtils.java @@ -0,0 +1,90 @@ +package com.fengliyan.tianlesue.utils; + +import android.text.TextUtils; +import android.util.Base64; + +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +/** + * Created by zhangbin on 2019/1/23. + */ + +public class AESUtils { + + private static final String CBC_PKCS5_PADDING = "AES/ECB/PKCS7Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式 + private static final String AES = "AES";//AES 加密 + + /** + * 加密 + * + * @param content 需要加密的内容 + * @param password 加密密码 + * @return + */ + public static String encrypt(String password, String content) { + if (TextUtils.isEmpty(content)) { + return content; + } + try { + SecretKeySpec key = new SecretKeySpec(password.getBytes(), AES); + Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING); + byte[] byteContent = content.getBytes("utf-8"); + cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化 + byte[] result = cipher.doFinal(byteContent); + return new String(Base64.encode(result, Base64.DEFAULT)); // 加密 + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 解密 + * + * @param content 待解密内容 + * @param password 解密密钥 + * @return + */ + public static String decrypt(String password, String content) { + if (TextUtils.isEmpty(content)) { + return content; + } + try { + byte[] enc = Base64.decode(content, Base64.DEFAULT); + SecretKeySpec key = new SecretKeySpec(password.getBytes(), AES); + Cipher cipher = Cipher.getInstance(AES);// 创建密码器 + cipher.init(Cipher.DECRYPT_MODE, key);// 初始化 + byte[] result = cipher.doFinal(enc); + return new String(result); // 加密 + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/AnimUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/AnimUtils.java new file mode 100644 index 0000000..dd0d39a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/AnimUtils.java @@ -0,0 +1,42 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.res.TypedArray; +import android.widget.ImageView; + +import com.fengliyan.tianlesue.R; + +public class AnimUtils { + + public static FrameAnimation startGuardAnimation(Context context, ImageView imageView) { + return startGuardAnimation_(context,imageView,R.array.c); + } + + public static FrameAnimation startGuardAnimation_(Context context,ImageView imageView,int id){ + FrameAnimation frameAnimation = new FrameAnimation(imageView, getRes(context,id), 30, true); + frameAnimation.setAnimationListener(new FrameAnimation.AnimationListener() { + @Override + public void onAnimationStart() { + } + + @Override + public void onAnimationEnd() { + } + + @Override + public void onAnimationRepeat() { + } + }); + return frameAnimation; + } + private static int[] getRes(Context context,int id) { + TypedArray typedArray = context.getResources().obtainTypedArray(id); + int len = typedArray.length(); + int[] resId = new int[len]; + for (int i = 0; i < len; i++) { + resId[i] = typedArray.getResourceId(i, -1); + } + typedArray.recycle(); + return resId; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/AppBarStateChangeListener.java b/app/src/main/java/com/fengliyan/tianlesue/utils/AppBarStateChangeListener.java new file mode 100644 index 0000000..b2c4930 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/AppBarStateChangeListener.java @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.utils; + + +import com.google.android.material.appbar.AppBarLayout; + +public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { + public enum State { + EXPANDED, + COLLAPSED, + IDLE + } + + private State mCurrentState = State.IDLE; + + @Override + public final void onOffsetChanged(AppBarLayout appBarLayout, int i) { + if (i == 0) { + if (mCurrentState != State.EXPANDED) { + onStateChanged(appBarLayout, State.EXPANDED); + } + mCurrentState = State.EXPANDED; + } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) { + if (mCurrentState != State.COLLAPSED) { + onStateChanged(appBarLayout, State.COLLAPSED); + } + mCurrentState = State.COLLAPSED; + } else { + if (mCurrentState != State.IDLE) { + onStateChanged(appBarLayout, State.IDLE); + } + mCurrentState = State.IDLE; + } + } + + public abstract void onStateChanged(AppBarLayout appBarLayout, State state); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/AutoPollRecyclerView.java b/app/src/main/java/com/fengliyan/tianlesue/utils/AutoPollRecyclerView.java new file mode 100644 index 0000000..6187331 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/AutoPollRecyclerView.java @@ -0,0 +1,70 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import java.lang.ref.WeakReference; + +public class AutoPollRecyclerView extends RecyclerView { + + private static final long TIME_AUTO_POLL = 30; + AutoPollTask autoPollTask; + private boolean running;//标识是否正在自动轮询 + private boolean canRun;//标识是否可以自动轮询,可在不需要时置false + + public AutoPollRecyclerView(@NonNull Context context, AttributeSet attrs) { + super(context, attrs); + autoPollTask = new AutoPollTask(this); + } + + static class AutoPollTask implements Runnable { + private final WeakReference mReference; + + public AutoPollTask(AutoPollRecyclerView reference) { + this.mReference = new WeakReference(reference); + } + + @Override + public void run() { + AutoPollRecyclerView recyclerView = mReference.get(); + if (recyclerView != null && recyclerView.running && recyclerView.canRun) { + recyclerView.scrollBy(2, 2); + recyclerView.postDelayed(recyclerView.autoPollTask, recyclerView.TIME_AUTO_POLL); + } + } + } + + public void start() { + if (running) + stop(); + + canRun = true; + running = true; + postDelayed(autoPollTask, TIME_AUTO_POLL); + } + + public void stop() { + running = false; + removeCallbacks(autoPollTask); + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: + if (running) + stop(); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_OUTSIDE: + if (canRun) + start(); + break; + } + return super.onTouchEvent(e); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/BaseUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/BaseUtils.java new file mode 100644 index 0000000..6d951c5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/BaseUtils.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.utils; + +import android.widget.RelativeLayout; + +import com.fengliyan.uikit.emoji.utils.ScreenUtil; +import com.youth.banner.Banner; + +/** + * ying 2020/11/30 + * Describe : + */ +public class BaseUtils { + public static Banner setBannerLayoutParams(Banner banner) { + int displayWidth = ScreenUtil.getDisplayWidth() - ScreenUtil.dip2px(12); + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(displayWidth, displayWidth / 3); + banner.setLayoutParams(params); + return banner; + } + public static String setTextMoney(double totalMoney) { + String value = ""; + if (totalMoney >= 10000) { + double money = totalMoney / 10000; + value = String.format("%.1f", money - 0.05) + "万"; + } else { + value = String.format("%.0f", totalMoney); + } + return value; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/BeautySPUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/BeautySPUtils.java new file mode 100644 index 0000000..c30bdd7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/BeautySPUtils.java @@ -0,0 +1,74 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.fengliyan.tianlesue.view.base.BaseApplication; + +/** + * Created by zhangbin on 2019/1/19. + */ + +public class BeautySPUtils { + + private final static String name = "beauty_config"; + private final static int mode = Context.MODE_PRIVATE; + /** + * 保存首选项 + * @param key + * @param value + */ + public static void saveBoolean(String key, boolean value){ + + SharedPreferences sp = BaseApplication.getInstance().getApplicationContext().getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putBoolean(key, value); + edit.commit(); + } + + public static void saveFloat(String key, Float value) { + SharedPreferences sp = BaseApplication.getInstance().getApplicationContext().getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putFloat(key, value); + edit.commit(); + } + + public static void saveString(String key, String value){ + SharedPreferences sp = BaseApplication.getInstance().getApplicationContext().getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putString(key, value); + edit.commit(); + } + + /** + * 获取首选项 + * @param key + * @return + */ + public static boolean getBoolean(String key){ + SharedPreferences sp = BaseApplication.getInstance().getApplicationContext().getSharedPreferences(name, mode); + return sp.getBoolean(key, false); + } + + public static Float getFloat(String key) { + SharedPreferences sp = BaseApplication.getInstance().getApplicationContext().getSharedPreferences(name, mode); + return sp.getFloat(key, 0); + } + + public static String getString(String key) { + SharedPreferences sp = BaseApplication.getInstance().getApplicationContext().getSharedPreferences(name, mode); + return sp.getString(key, ""); + } + + + + /** + * 清除保存 + */ + public static void clear(){ + SharedPreferences sp = BaseApplication.getInstance().getApplicationContext().getSharedPreferences(name, mode); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + editor.commit(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/BitmapLruCache.java b/app/src/main/java/com/fengliyan/tianlesue/utils/BitmapLruCache.java new file mode 100644 index 0000000..1e10f5f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/BitmapLruCache.java @@ -0,0 +1,46 @@ +package com.fengliyan.tianlesue.utils; + + +import android.graphics.Bitmap; +import android.util.LruCache; + +/** + * Created by dmw on 2023/10/30 + * Desc: 内存缓存,存储bitmap + * key:bitmap对应的文件路径 + */ +public class BitmapLruCache { + + private static final String TAG = "BitmapLruCache"; + + private LruCache cache; + + public BitmapLruCache() { + // Calculate the maximum memory available to the cache + int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); + + // Set the cache size to be a fraction of the available memory + int cacheSize = maxMemory / 8; + + // Initialize the LruCache with the calculated cache size + cache = new LruCache(cacheSize) { + @Override + protected int sizeOf(String key, Bitmap bitmap) { + // Return the size of the bitmap in kilobytes + return bitmap.getByteCount() / 1024; + } + }; + } + + public void putBitmap(String key, Bitmap bitmap) { + cache.put(key, bitmap); + } + + public Bitmap getBitmap(String key) { + return cache.get(key); + } + + public void clearCache() { + cache.evictAll(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/BuriedPointUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/BuriedPointUtils.java new file mode 100644 index 0000000..da16b75 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/BuriedPointUtils.java @@ -0,0 +1,64 @@ +package com.fengliyan.tianlesue.utils; + +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.TType; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpRequest; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.task.HttpWithUiTask; + +/** + * 埋点工具类 + */ +public class BuriedPointUtils { + + /** + * 1=礼包弹出 + */ + public static final String BURIED1 = "1"; + /** + * 2=点击了充值的人 + */ + public static final String BURIED2 = "2"; + /** + * 3=充值8元的人、3=充值18元的人、3=充值28元的人 + */ + public static final String BURIED3 = "3"; + + + //用户行为数据埋点 + public static void buriedPoint(BaseActivity activity, String type_id) { + HttpWithUiTask task = new HttpWithUiTask(activity, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }) { + @Override + protected HttpResult run() throws Exception { + final String url = ConstUrl.FIRST_RECHARGE_BURIED_POINT; + HttpRequest.Builder builder = new HttpRequest.Builder() + .setResultType(new TType>() { + }).setHttpMethod(HttpMethod.POST) + .addParam("type_id", type_id) + .setUrl(url); + + HttpRequest request = builder.build(); + return request.request(); + } + }; + task.start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/CaptchaInputView.java b/app/src/main/java/com/fengliyan/tianlesue/utils/CaptchaInputView.java new file mode 100644 index 0000000..11354a3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/CaptchaInputView.java @@ -0,0 +1,330 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.os.Handler; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.widget.EditText; + +import com.fengliyan.tianlesue.R; + +import java.util.ArrayList; +import java.util.List; + +import static android.graphics.Paint.ANTI_ALIAS_FLAG; + +/** + * @author luchao + */ +public class CaptchaInputView extends EditText { + private int borderColor; + private float borderWidth; + private float borderRadius; + + private int passwordLength = 4; + private int passwordColor; + private float passwordWidth; + private float passwordRadius; + + private Paint passwordPaint = new Paint(ANTI_ALIAS_FLAG); + private Paint borderPaint = new Paint(ANTI_ALIAS_FLAG); + private Paint linePaint = new Paint(ANTI_ALIAS_FLAG); + + + private final int defaultContMargin = 5; + private final int defaultSplitLineWidth = 3; + + private TextChangeListener mTextChangeListener; + private float mDefaultInputViewTextSize, mDefaultInputViewPadding, mDefaultInputTextSize; + private float mCursorWidth; + private int mCursorHeight; + private float mDefalutMargin = 10; + private boolean mPwdVisiable = true; + private String mInputText; + private List rectList; + private Context mContext; + private int mSelectIndex = 0; + private Handler mCursorHandler; + private CursorRunnable mCursorRunnable; + static final int CURSOR_DELAY_TIME = 500; + + public CaptchaInputView(Context context, AttributeSet attrs) { + super(context, attrs); + this.mContext = context; + final Resources res = getResources(); + final int defaultBorderColor = res.getColor(R.color.default_ev_border_color); + final float defaultBorderWidth = res.getDimension(R.dimen.dp1); + final float defaultBorderRadius = res.getDimension(R.dimen.dp3); + final int defaultPasswordLength = 4; + final int defaultPasswordColor = res.getColor(R.color.default_ev_password_color); + final float defaultPasswordWidth = res.getDimension(R.dimen.dp10); + final float defaultPasswordRadius = res.getDimension(R.dimen.dp3); + final float defaultInputViewTextSize = res.getDimension(R.dimen.dp60); + final float defaultInputViewPadding = res.getDimension(R.dimen.dp12); + final float defaultInputTextSize = res.getDimension(R.dimen.dp22); + + TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordInputView, 0, 0); + try { + borderColor = a.getColor(R.styleable.PasswordInputView_captchaBorderColor, defaultBorderColor); + borderWidth = a.getDimension(R.styleable.PasswordInputView_captchaBorderWidth, defaultBorderWidth); + borderRadius = a.getDimension(R.styleable.PasswordInputView_captchaBorderRadius, defaultBorderRadius); + passwordLength = a.getInt(R.styleable.PasswordInputView_captchaLength, defaultPasswordLength); + passwordColor = a.getColor(R.styleable.PasswordInputView_captchaColor, defaultPasswordColor); + passwordWidth = a.getDimension(R.styleable.PasswordInputView_captchaWidth, defaultPasswordWidth); + passwordRadius = a.getDimension(R.styleable.PasswordInputView_captchaRadius, defaultPasswordRadius); + mDefaultInputViewTextSize = a.getDimension(R.styleable.PasswordInputView_captchaViewSize, defaultInputViewTextSize); + mDefaultInputViewPadding = a.getDimension(R.styleable.PasswordInputView_captchaViewSize, defaultInputViewPadding); + mDefaultInputTextSize = a.getDimension(R.styleable.PasswordInputView_captchaTextSize, defaultInputTextSize); + } finally { + a.recycle(); + } + + mCursorWidth = mContext.getResources().getDimension(R.dimen.dp1); + mCursorHeight = (int) mContext.getResources().getDimension(R.dimen.dp30); + + borderPaint.setStrokeWidth(borderWidth); + borderPaint.setColor(borderColor); + linePaint.setColor(getResources().getColor(R.color.select_border_color)); + linePaint.setStrokeWidth(mCursorWidth); //绘制直线 + + borderPaint.setStyle(Paint.Style.FILL); + borderPaint.setAntiAlias(true); + + passwordPaint.setColor(passwordColor); + passwordPaint.setTextSize(mDefaultInputTextSize); + rectList = new ArrayList<>(); + + mCursorHandler = new Handler(); + mCursorRunnable = new CursorRunnable(); + mCursorHandler.post(mCursorRunnable); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = passwordLength * (int)mDefaultInputViewTextSize + (int)mDefaultInputViewPadding * 3 + (int)mDefalutMargin*2; + int height = (int)mDefaultInputViewTextSize + (int)mDefalutMargin*2; + setMeasuredDimension(width, height); + } + + private class CursorRunnable implements Runnable { + private boolean mCancelled = false; + private boolean mCursorVisible = false; + @Override + public void run() { + if (mCancelled) { + return; + } + postInvalidate(); + postDelayed(this, CURSOR_DELAY_TIME); + } + + void cancel() { + if (!mCancelled) { + mCursorHandler.removeCallbacks(this); + mCancelled = true; + } + } + + public boolean getCursorVisiable() { + return mCursorVisible = !mCursorVisible; + } + } + + + public void stopCursor() { + if(mCursorRunnable != null && mCursorHandler != null) { + mCursorRunnable.cancel(); + } + } + +// 点击事件的处理 +// @Override +// public boolean onTouchEvent(MotionEvent event) { +// float x = event.getX(); +// float y = event.getY(); +// switch (event.getAction()) { +// case MotionEvent.ACTION_DOWN: +// for(int i = 0; i< rectList.size(); i++) { +// RectF rectF = rectList.get(i); +// if(rectF.contains(x, y)) { +// mSelectIndex = i; +// postInvalidate(); +// +// Log.d("draw", "index="+i); +// break; +// } +// } +// break; +// } +// return super.onTouchEvent(event); +// } + + @Override + protected void onDraw(Canvas canvas) { + rectList.clear(); + //边框 + int left = (int)mDefalutMargin; + int top = (int)mDefalutMargin; + for(int i = 0; i < passwordLength; i++) { + if(i < mSelectIndex) { + //彩色边框 + borderPaint.setColor(getResources().getColor(R.color.select_border_color)); + } else { + //灰色边框 + borderPaint.setColor(borderColor); + } + RectF rectF = new RectF(left, top, mDefaultInputViewTextSize + left, mDefaultInputViewTextSize + top); + rectList.add(rectF); + canvas.drawRoundRect(rectF, 24, 24, borderPaint); + left+= mDefaultInputViewPadding + mDefaultInputViewTextSize; + } + + //内容,密码可见 + int textLeft = (int)mDefalutMargin + (int)mDefaultInputViewTextSize/2; + if(mPwdVisiable) { + for(int i = 0; i < mInputText.length(); i++) { + String text = mInputText.substring(i, i + 1); + int textWidth = !TextUtils.isEmpty(text) ? getTextWidth(passwordPaint, text)/2 : 0; + canvas.drawText(text, textLeft - textWidth, mDefaultInputViewTextSize/2 + mDefaultInputTextSize/2, passwordPaint); + textLeft+= mDefaultInputViewPadding + mDefaultInputViewTextSize; + } + } else { + for(int i = 0; i < mInputText.length(); i++) { + String text = mInputText.substring(i, i + 1); + int textWidth = !TextUtils.isEmpty(text) ? getTextWidth(passwordPaint, "*")/2 : 0; + canvas.drawText("*", textLeft - textWidth, mDefaultInputViewTextSize/2 + mDefaultInputTextSize/2 + 5, passwordPaint); + textLeft+= mDefaultInputViewPadding + mDefaultInputViewTextSize; + } + } + + //光标 + if(mSelectIndex < passwordLength && mCursorRunnable.getCursorVisiable()) { + int cursorLeft = (int) mDefalutMargin; + int cursorTop = (int) mDefalutMargin + ((int) mDefaultInputViewTextSize - mCursorHeight) / 2; + int startX = cursorLeft + (int) mDefaultInputViewTextSize / 2 + mSelectIndex * (int) mDefaultInputViewTextSize + mSelectIndex * (int) mDefaultInputViewPadding; + int stopX = startX; + int startY = cursorTop; + int stopY = startY + mCursorHeight; + canvas.drawLine(startX, startY, stopX, stopY, linePaint); + } + + } + + public int getTextWidth(Paint paint, String str) { + int iRet = 0; + if (str != null && str.length() > 0) { + int len = str.length(); + float[] widths = new float[len]; + paint.getTextWidths(str, widths); + for (int j = 0; j < len; j++) { + iRet += (int) Math.ceil(widths[j]); + } + } + return iRet; + } + + @Override + protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + super.onTextChanged(text, start, lengthBefore, lengthAfter); + if (mTextChangeListener != null) { + mTextChangeListener.onTextChanged(text, start, lengthBefore, lengthAfter); + } + mInputText = text.toString(); + if(mInputText.length() > 0) { + mSelectIndex = mInputText.length(); + } else { + mSelectIndex = 0; + } + postInvalidate(); + } + + public void setPwdVisiable(boolean pwdVisiable) { + this.mPwdVisiable = pwdVisiable; + } + + public void setTextLength(int length) { + this.passwordLength = length; + postInvalidate(); + } + + public int getBorderColor() { + return borderColor; + } + + public void setBorderColor(int borderColor) { + this.borderColor = borderColor; + borderPaint.setColor(borderColor); + invalidate(); + } + + public float getBorderWidth() { + return borderWidth; + } + + public void setBorderWidth(float borderWidth) { + this.borderWidth = borderWidth; + borderPaint.setStrokeWidth(borderWidth); + invalidate(); + } + + public float getBorderRadius() { + return borderRadius; + } + + public void setBorderRadius(float borderRadius) { + this.borderRadius = borderRadius; + invalidate(); + } + + public int getPasswordLength() { + return passwordLength; + } + + public void setPasswordLength(int passwordLength) { + this.passwordLength = passwordLength; + invalidate(); + } + + public int getPasswordColor() { + return passwordColor; + } + + public void setPasswordColor(int passwordColor) { + this.passwordColor = passwordColor; + passwordPaint.setColor(passwordColor); + invalidate(); + } + + public float getPasswordWidth() { + return passwordWidth; + } + + public void setPasswordWidth(float passwordWidth) { + this.passwordWidth = passwordWidth; + passwordPaint.setStrokeWidth(passwordWidth); + invalidate(); + } + + public float getPasswordRadius() { + return passwordRadius; + } + + public void setPasswordRadius(float passwordRadius) { + this.passwordRadius = passwordRadius; + invalidate(); + } + + public void setTextChangeListener(TextChangeListener mTextChangeListener) { + this.mTextChangeListener = mTextChangeListener; + } + + public interface TextChangeListener { + void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/CitySPUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/CitySPUtils.java new file mode 100644 index 0000000..211f840 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/CitySPUtils.java @@ -0,0 +1,83 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +/** + * Created by zhangbin on 2019/1/10. + */ + +public class CitySPUtils { + + private final static String name = "city_config"; + private final static int mode = Context.MODE_PRIVATE; + + /** + * 保存首选项 + * @param context + * @param key + * @param value + */ + public static void saveBoolean(Context context, String key, boolean value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putBoolean(key, value); + edit.commit(); + } + public static void saveInt(Context context, String key, int value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putInt(key, value); + edit.commit(); + } + public static void saveString(Context context, String key, String value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putString(key, value); + edit.commit(); + } + + + /** + * 获取首选项 + * @param context + * @param key + * @param defValue + * @return + */ + public static boolean getBoolean(Context context, String key, boolean defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getBoolean(key, defValue); + } + + public static int getInt(Context context, String key, int defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, defValue); + } + + public static int getInt(Context context, String key){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, 0); + } + + public static String getString(Context context, String key, String defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, defValue); + } + + public static String getString(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, ""); + } + + /** + * 清除保存 + * @param context + */ + public static void clear(Context context){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + editor.commit(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/CodeUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/CodeUtils.java new file mode 100644 index 0000000..1c8b672 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/CodeUtils.java @@ -0,0 +1,156 @@ +package com.fengliyan.tianlesue.utils; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; + +import java.util.Random; + +/** + * Created by ekikousei易皇星 on 16/11/21. + * E-mail:13764664731@163.com + * Signature:缘分是本书,翻的不经意会错过,读的太认真会流泪!! + *

+ * 类描述: 用于图形验证码的工具类 + */ +public class CodeUtils { + +// private static final char[] CHARS = { +// '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', +// 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', +// 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', +// 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', +// 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' +// }; + +// private static final char[] CHARS = { +// +// 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', +// 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', +// +// }; + + private static CodeUtils mCodeUtils; + private int mPaddingLeft, mPaddingTop; + private StringBuilder mBuilder = new StringBuilder(); + private Random mRandom = new Random(); + + //Default Settings +// private static final int DEFAULT_CODE_LENGTH = 6;//验证码的长度 这里是6位 + private static final int DEFAULT_CODE_LENGTH = 4;//验证码的长度 这里是4位 + private static final int DEFAULT_FONT_SIZE = 60;//字体大小 + private static final int DEFAULT_LINE_NUMBER = 3;//多少条干扰线 + private static final int BASE_PADDING_LEFT = 40; //左边距 + private static final int RANGE_PADDING_LEFT = 30;//左边距范围值 + private static final int BASE_PADDING_TOP = 70;//上边距 + private static final int RANGE_PADDING_TOP = 15;//上边距范围值 + private static final int DEFAULT_WIDTH = 300;//默认宽度.图片的总宽 + private static final int DEFAULT_HEIGHT = 100;//默认高度.图片的总高 + private static final int DEFAULT_COLOR = 0xDF;//默认背景颜色值 + + private String code; + + public static CodeUtils getInstance() { + if (mCodeUtils == null) { + mCodeUtils = new CodeUtils(); + } + return mCodeUtils; + } + + //生成验证码图片 返回类型为bitmap 直接用imageview.setbitmap()即可 + public Bitmap createBitmap(String mCode) { + mPaddingLeft = 0; //每次生成验证码图片时初始化 + mPaddingTop = 0; + + Bitmap bitmap = Bitmap.createBitmap(DEFAULT_WIDTH, DEFAULT_HEIGHT, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + + code = mCode; + + canvas.drawColor(Color.rgb(DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_COLOR)); + Paint paint = new Paint(); + paint.setTextSize(DEFAULT_FONT_SIZE); + + for (int i = 0; i < mCode.length(); i++) { + randomTextStyle(paint); + randomPadding(); + canvas.drawText(mCode.charAt(i) + "", mPaddingLeft, mPaddingTop, paint); + } + + //干扰线 + for (int i = 0; i < DEFAULT_LINE_NUMBER; i++) { + drawLine(canvas, paint); + } + canvas.save();//保存 + canvas.restore(); + return bitmap; + } + + /** + * 得到图片中的验证码字符串 + * + * @return + */ + public String getCode() { + return code; + } + + //生成验证码 +// public String createCode(String code) { +// mBuilder.delete(0, mBuilder.length()); //使用之前首先清空内容 +// +// for (int i = 0; i < DEFAULT_CODE_LENGTH; i++) { +// mBuilder.append(CHARS[mRandom.nextInt(CHARS.length)]); +// } +// +// return mBuilder.toString(); +// } + + //生成干扰线 + private void drawLine(Canvas canvas, Paint paint) { + int color = randomColor(); + int startX = mRandom.nextInt(DEFAULT_WIDTH); + int startY = mRandom.nextInt(DEFAULT_HEIGHT); + int stopX = mRandom.nextInt(DEFAULT_WIDTH); + int stopY = mRandom.nextInt(DEFAULT_HEIGHT); + paint.setStrokeWidth(1); + paint.setColor(color); + canvas.drawLine(startX, startY, stopX, stopY, paint); + } + + //随机颜色 + private int randomColor() { + mBuilder.delete(0, mBuilder.length()); //使用之前首先清空内容 + + String haxString; + for (int i = 0; i < 3; i++) { + haxString = Integer.toHexString(mRandom.nextInt(0xFF)); + if (haxString.length() == 1) { + haxString = "0" + haxString; + } + + mBuilder.append(haxString); + } + + return Color.parseColor("#" + mBuilder.toString()); + } + + //随机文本样式 + private void randomTextStyle(Paint paint) { + int color = randomColor(); + paint.setColor(color); + paint.setFakeBoldText(mRandom.nextBoolean()); //true为粗体,false为非粗体 + float skewX = mRandom.nextInt(11) / 10; + skewX = mRandom.nextBoolean() ? skewX : -skewX; + paint.setTextSkewX(skewX); //float类型参数,负数表示右斜,整数左斜 +// paint.setUnderlineText(true); //true为下划线,false为非下划线 +// paint.setStrikeThruText(true); //true为删除线,false为非删除线 + } + + //随机间距 + private void randomPadding() { + mPaddingLeft += BASE_PADDING_LEFT + mRandom.nextInt(RANGE_PADDING_LEFT); + mPaddingTop = BASE_PADDING_TOP + mRandom.nextInt(RANGE_PADDING_TOP); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/DemoHelper.java b/app/src/main/java/com/fengliyan/tianlesue/utils/DemoHelper.java new file mode 100644 index 0000000..941dbe4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/DemoHelper.java @@ -0,0 +1,175 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.bun.miitmdid.interfaces.IIdentifierListener; +import com.bun.miitmdid.interfaces.IdSupplier; +import com.github.gzuliyujiang.oaid.DeviceIdentifier; +import com.fengliyan.device.DeviceManager; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** +* Date: 16:27 2021/2/26 0026 + * Version: 1.0.3 +**/ +public class DemoHelper implements IIdentifierListener { + + public static final String TAG = "DemoHelper"; + public static final int HELPER_VERSION_CODE = 20210928; // DemoHelper版本号 + private final AppIdsUpdater appIdsUpdater; + private boolean isCertInit = false; + + public boolean isSDKLogOn = true; + public static final String ASSET_FILE_NAME_CERT = "com.fengliyan.tianlesue.cert.pem"; // (2)设置 asset证书文件名 + + public DemoHelper(AppIdsUpdater appIdsUpdater){ + //System.loadLibrary("nllvm1632808251147706677"); // (3)加固版本在调用前必须载入SDK安全库 + // DemoHelper版本建议与SDK版本一致 + this.appIdsUpdater = appIdsUpdater; + } + + + /** + * 获取OAID + * @param cxt + */ + public void getDeviceIds(Context cxt){ + String result = DeviceManager.getInstance().getOaid(); + if (!TextUtils.isEmpty(result)){ + appIdsUpdater.onIdsValid(result); + }else{ + String oaid = DeviceIdentifier.getOAID(cxt); + if (!TextUtils.isEmpty(oaid)){ + appIdsUpdater.onIdsValid(oaid); + return; + } + String aid = DeviceIdentifier.getAndroidID(cxt); + if (!TextUtils.isEmpty(aid)){ + appIdsUpdater.onIdsValid(aid); + return; + } + + String ids = DeviceIdentifier.getPseudoID(); + if (!TextUtils.isEmpty(ids)){ + appIdsUpdater.onIdsValid(ids); + return; + } + } + + + // (4)初始化SDK证书 +// if(!isCertInit){ // 证书只需初始化一次 +// // 证书为PEM文件中的所有文本内容(包括首尾行、换行符) +// isCertInit = MdidSdkHelper.InitCert(cxt, loadPemFromAssetFile(cxt, ASSET_FILE_NAME_CERT)); +// if(!isCertInit){ +// Log.w(TAG, "getDeviceIds: cert init failed"); +// } +// } +// +// //(可选)设置InitSDK接口回调超时时间(仅适用于接口为异步),默认值为5000ms. +// // 注:请在调用前设置一次后就不再更改,否则可能导致回调丢失、重复等问题 +// MdidSdkHelper.setGlobalTimeout(5000); +// +// // (5)调用SDK获取ID +// int code = MdidSdkHelper.InitSdk(cxt, isSDKLogOn, this); +// +// // (6)根据SDK返回的code进行不同处理 +// IdSupplierImpl unsupportedIdSupplier = new IdSupplierImpl(); +// if(code == InfoCode.INIT_ERROR_CERT_ERROR){ // 证书未初始化或证书无效,SDK内部不会回调onSupport +// // APP自定义逻辑 +// Log.w(TAG,"cert not init or check not pass"); +// onSupport(unsupportedIdSupplier); +// }else if(code == InfoCode.INIT_ERROR_DEVICE_NOSUPPORT){ // 不支持的设备, SDK内部不会回调onSupport +// // APP自定义逻辑 +// Log.w(TAG,"device not supported"); +// onSupport(unsupportedIdSupplier); +// }else if( code == InfoCode.INIT_ERROR_LOAD_CONFIGFILE){ // 加载配置文件出错, SDK内部不会回调onSupport +// // APP自定义逻辑 +// Log.w(TAG,"failed to load config file"); +// onSupport(unsupportedIdSupplier); +// }else if(code == InfoCode.INIT_ERROR_MANUFACTURER_NOSUPPORT){ // 不支持的设备厂商, SDK内部不会回调onSupport +// // APP自定义逻辑 +// Log.w(TAG,"manufacturer not supported"); +// onSupport(unsupportedIdSupplier); +// }else if(code == InfoCode.INIT_ERROR_SDK_CALL_ERROR){ // sdk调用出错, SSDK内部不会回调onSupport +// // APP自定义逻辑 +// Log.w(TAG,"sdk call error"); +// onSupport(unsupportedIdSupplier); +// } else if(code == InfoCode.INIT_INFO_RESULT_DELAY) { // 获取接口是异步的,SDK内部会回调onSupport +// Log.i(TAG, "result delay (async)"); +// }else if(code == InfoCode.INIT_INFO_RESULT_OK){ // 获取接口是同步的,SDK内部会回调onSupport +// Log.i(TAG, "result ok (sync)"); +// }else { +// // sdk版本高于DemoHelper代码版本可能出现的情况,无法确定是否调用onSupport +// // 不影响成功的OAID获取 +// Log.w(TAG,"getDeviceIds: unknown code: " + code); +// } + } + + /** + * APP自定义的getDeviceIds(Context cxt)的接口回调 + * @param supplier + */ + @Override + public void onSupport(IdSupplier supplier) { + if(supplier==null) { + Log.w(TAG, "onSupport: supplier is null"); + return; + } + if(appIdsUpdater ==null) { + Log.w(TAG, "onSupport: callbackListener is null"); + return; + } + // 获取Id信息 + // 注:IdSupplier中的内容为本次调用MdidSdkHelper.InitSdk()的结果,不会实时更新。 如需更新,需调用MdidSdkHelper.InitSdk() +// boolean isSupported = supplier.isSupported(); +// boolean isLimited = supplier.isLimited(); + String oaid=supplier.getOAID(); +// String vaid=supplier.getVAID(); +// String aaid=supplier.getAAID(); + +// String idsText= "support: " + (isSupported ? "true" : "false") + +// "\nlimit: " + (isLimited ? "true" : "false") + +// "\nOAID: " + oaid + +// "\nVAID: " + vaid + +// "\nAAID: " + aaid + "\n"; + String idsText=oaid; + + Log.d(TAG, "onSupport: ids: \n" + idsText); + appIdsUpdater.onIdsValid(idsText); + } + + public interface AppIdsUpdater{ + void onIdsValid(String ids); + } + + /** + * 从asset文件读取证书内容 + * @param context + * @param assetFileName + * @return 证书字符串 + */ + public static String loadPemFromAssetFile(Context context, String assetFileName){ + try { + InputStream is = context.getAssets().open(assetFileName); + BufferedReader in = new BufferedReader(new InputStreamReader(is)); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = in.readLine()) != null){ + builder.append(line); + builder.append('\n'); + } + return builder.toString(); + } catch (IOException e) { + Log.e(TAG, "loadPemFromAssetFile failed"); + return ""; + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/FrameAnimation.java b/app/src/main/java/com/fengliyan/tianlesue/utils/FrameAnimation.java new file mode 100644 index 0000000..ad779ac --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/FrameAnimation.java @@ -0,0 +1,321 @@ +package com.fengliyan.tianlesue.utils; + +import android.widget.ImageView; + + +public class FrameAnimation { + + private boolean mIsRepeat; + + private AnimationListener mAnimationListener; + + private ImageView mImageView; + + private int[] mFrameRess; + + /** + * 每帧动画的播放间隔数组 + */ + private int[] mDurations; + + /** + * 每帧动画的播放间隔 + */ + private int mDuration; + + /** + * 下一遍动画播放的延迟时间 + */ + private int mDelay; + + private int mLastFrame; + + private boolean mNext; + + private boolean mPause; + + private int mCurrentSelect; + + private int mCurrentFrame; + + private static final int SELECTED_A = 1; + + private static final int SELECTED_B = 2; + + private static final int SELECTED_C = 3; + + private static final int SELECTED_D = 4; + + + /** + * @param iv 播放动画的控件 + * @param frameRes 播放的图片数组 + * @param duration 每帧动画的播放间隔(毫秒) + * @param isRepeat 是否循环播放 + */ + public FrameAnimation(ImageView iv, int[] frameRes, int duration, boolean isRepeat) { + this.mImageView = iv; + this.mFrameRess = frameRes; + this.mDuration = duration; + this.mLastFrame = frameRes.length - 1; + this.mIsRepeat = isRepeat; + play(0); + } + + /** + * @param iv 播放动画的控件 + * @param frameRess 播放的图片数组 + * @param durations 每帧动画的播放间隔(毫秒) + * @param isRepeat 是否循环播放 + */ + public FrameAnimation(ImageView iv, int[] frameRess, int[] durations, boolean isRepeat) { + this.mImageView = iv; + this.mFrameRess = frameRess; + this.mDurations = durations; + this.mLastFrame = frameRess.length - 1; + this.mIsRepeat = isRepeat; + playByDurations(0); + } + + /** + * 循环播放动画 + * + * @param iv 播放动画的控件 + * @param frameRess 播放的图片数组 + * @param duration 每帧动画的播放间隔(毫秒) + * @param delay 循环播放的时间间隔 + */ + public FrameAnimation(ImageView iv, int[] frameRess, int duration, int delay) { + this.mImageView = iv; + this.mFrameRess = frameRess; + this.mDuration = duration; + this.mDelay = delay; + this.mLastFrame = frameRess.length - 1; + playAndDelay(0); + } + + /** + * 循环播放动画 + * + * @param iv 播放动画的控件 + * @param frameRess 播放的图片数组 + * @param durations 每帧动画的播放间隔(毫秒) + * @param delay 循环播放的时间间隔 + */ + public FrameAnimation(ImageView iv, int[] frameRess, int[] durations, int delay) { + this.mImageView = iv; + this.mFrameRess = frameRess; + this.mDurations = durations; + this.mDelay = delay; + this.mLastFrame = frameRess.length - 1; + playByDurationsAndDelay(0); + } + + private void playByDurationsAndDelay(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { // 暂停和播放需求 + mCurrentSelect = SELECTED_A; + mCurrentFrame = i; + return; + } + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackgroundResource(mFrameRess[i]); + if (i == mLastFrame) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + mNext = true; + playByDurationsAndDelay(0); + } else { + playByDurationsAndDelay(i + 1); + } + } + }, mNext && mDelay > 0 ? mDelay : mDurations[i]); + + } + + private void playAndDelay(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { + if (mPause) { + mCurrentSelect = SELECTED_B; + mCurrentFrame = i; + return; + } + return; + } + mNext = false; + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackgroundResource(mFrameRess[i]); + if (i == mLastFrame) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + mNext = true; + playAndDelay(0); + } else { + playAndDelay(i + 1); + } + } + }, mNext && mDelay > 0 ? mDelay : mDuration); + + } + + private void playByDurations(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { + if (mPause) { + mCurrentSelect = SELECTED_C; + mCurrentFrame = i; + return; + } + return; + } + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackgroundResource(mFrameRess[i]); + if (i == mLastFrame) { + if (mIsRepeat) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + playByDurations(0); + } else { + if (mAnimationListener != null) { + mAnimationListener.onAnimationEnd(); + } + } + } else { + + playByDurations(i + 1); + } + } + }, mDurations[i]); + + } + + private void play(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { + if (mPause) { + mCurrentSelect = SELECTED_D; + mCurrentFrame = i; + return; + } + return; + } + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackgroundResource(mFrameRess[i]); + if (i == mLastFrame) { + + if (mIsRepeat) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + play(0); + } else { + if (mAnimationListener != null) { + mAnimationListener.onAnimationEnd(); + } + } + + } else { + + play(i + 1); + } + } + }, mDuration); + } + + public static interface AnimationListener { + + /** + *

Notifies the start of the animation.

+ */ + void onAnimationStart(); + + /** + *

Notifies the end of the animation. This callback is not invoked + * for animations with repeat count set to INFINITE.

+ */ + void onAnimationEnd(); + + /** + *

Notifies the repetition of the animation.

+ */ + void onAnimationRepeat(); + } + + /** + *

Binds an animation listener to this animation. The animation listener + * is notified of animation events such as the end of the animation or the + * repetition of the animation.

+ * + * @param listener the animation listener to be notified + */ + public void setAnimationListener(AnimationListener listener) { + this.mAnimationListener = listener; + } + + public void release() { + pauseAnimation(); + } + + public void pauseAnimation() { + this.mPause = true; + } + + public boolean isPause() { + return this.mPause; + } + + public void restartAnimation() { + if (mPause) { + mPause = false; + switch (mCurrentSelect) { + case SELECTED_A: + playByDurationsAndDelay(mCurrentFrame); + break; + case SELECTED_B: + playAndDelay(mCurrentFrame); + break; + case SELECTED_C: + playByDurations(mCurrentFrame); + break; + case SELECTED_D: + play(mCurrentFrame); + break; + default: + break; + } + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/GlideEngine.java b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideEngine.java new file mode 100644 index 0000000..700cbe9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideEngine.java @@ -0,0 +1,117 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.fengliyan.tianlesue.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.utils.ActivityCompatHelper; + +/** + * @author:luck + * @date:2019-11-13 17:02 + * @describe:Glide加载引擎 + */ +public class GlideEngine implements ImageEngine { + + /** + * 加载图片 + * + * @param context 上下文 + * @param url 资源url + * @param imageView 图片承载控件 + */ + @Override + public void loadImage(Context context, String url, ImageView imageView) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return; + } + Glide.with(context) + .load(url) + .into(imageView); + } + + @Override + public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return; + } + Glide.with(context) + .load(url) + .override(maxWidth, maxHeight) + .into(imageView); + } + + /** + * 加载相册目录封面 + * + * @param context 上下文 + * @param url 图片路径 + * @param imageView 承载图片ImageView + */ + @Override + public void loadAlbumCover(Context context, String url, ImageView imageView) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return; + } + Glide.with(context) + .asBitmap() + .load(url) + .override(180, 180) + .sizeMultiplier(0.5f) + .transform(new CenterCrop(), new RoundedCorners(8)) + .placeholder(R.drawable.ps_image_placeholder) + .into(imageView); + } + + + /** + * 加载图片列表图片 + * + * @param context 上下文 + * @param url 图片路径 + * @param imageView 承载图片ImageView + */ + @Override + public void loadGridImage(Context context, String url, ImageView imageView) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return; + } + Glide.with(context) + .load(url) + .override(200, 200) + .centerCrop() + .placeholder(R.drawable.ps_image_placeholder) + .into(imageView); + } + + @Override + public void pauseRequests(Context context) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return; + } + Glide.with(context).pauseRequests(); + } + + @Override + public void resumeRequests(Context context) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return; + } + Glide.with(context).resumeRequests(); + } + + private GlideEngine() { + } + + private static final class InstanceHolder { + static final GlideEngine instance = new GlideEngine(); + } + + public static GlideEngine createGlideEngine() { + return InstanceHolder.instance; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/GlideImageLoader.java b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideImageLoader.java new file mode 100644 index 0000000..98918f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideImageLoader.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.youth.banner.loader.ImageLoader; + + +public class GlideImageLoader extends ImageLoader { + @Override + public void displayImage(Context context, Object path, ImageView imageView) { + //具体方法内容自己去选择,次方法是为了减少banner过多的依赖第三方包,所以将这个权限开放给使用者去选择 + Glide.with(context.getApplicationContext()) + .load(path) + .into(imageView); + } + +// @Override +// public ImageView createImageView(Context context) { +// //圆角 +// return new RoundAngleImageView(context); +// } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/GlideImageLoader1.java b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideImageLoader1.java new file mode 100644 index 0000000..a8493c2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideImageLoader1.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.uikit.emoji.utils.ScreenUtil; +import com.youth.banner.loader.ImageLoader; + + +public class GlideImageLoader1 extends ImageLoader { + @Override + public void displayImage(Context context, Object path, ImageView imageView) { + //具体方法内容自己去选择,次方法是为了减少banner过多的依赖第三方包,所以将这个权限开放给使用者去选择 + Glide.with(context.getApplicationContext()) + .load(((BannerBean) path).getImage()) + .into(imageView); + } + + @Override + public ImageView createImageView(Context context) { + //圆角 + RoundAngleImageView imageView = new RoundAngleImageView(context); + imageView.setType(RoundAngleImageView.TYPE_ROUND); + imageView.setRoundRadius(ScreenUtil.dip2px(12)); + return imageView; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/GlideRoundTransform2.java b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideRoundTransform2.java new file mode 100644 index 0000000..9c0376c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideRoundTransform2.java @@ -0,0 +1,81 @@ +package com.fengliyan.tianlesue.utils; + +/** + * Created by zhangbin on 2019/2/15. + */ + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; + +import java.security.MessageDigest; + +/** + * Glide 圆角 Transform + */ + +public class GlideRoundTransform2 extends BitmapTransformation { + + private static float radius = 0f; + + /** + * 构造函数 默认圆角半径 4dp + * + * @param context Context + */ + public GlideRoundTransform2(Context context) { + this(context, 4); + } + + /** + * 构造函数 + * + * @param context Context + * @param dp 圆角半径 + */ + public GlideRoundTransform2(Context context, int dp) { + super(); +// radius = Resources.getSystem().getDisplayMetrics().density * dp; + radius = dp; + } + + @Override + protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { + return roundCrop(pool, toTransform); + } + + private static Bitmap roundCrop(BitmapPool pool, Bitmap source) { + if (source == null) return null; + + Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + if (result == null) { + result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + } + + Canvas canvas = new Canvas(result); + Paint paint = new Paint(); + paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); + paint.setAntiAlias(true); + RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); + canvas.drawRoundRect(rectF, radius, radius, paint); + return result; + + + } + +// @Override +// public String getId() { +// return getClass().getName() + Math.round(radius); +// } + + @Override + public void updateDiskCacheKey(MessageDigest messageDigest) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/GlideUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideUtils.java new file mode 100644 index 0000000..3fcb4d4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/GlideUtils.java @@ -0,0 +1,263 @@ +package com.fengliyan.tianlesue.utils; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Point; +import android.graphics.drawable.Drawable; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.annotation.Nullable; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestBuilder; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.MultiTransformation; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.load.resource.gif.GifDrawable; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.target.Target; +import com.bumptech.glide.request.transition.Transition; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import jp.wasabeef.glide.transformations.BlurTransformation; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; + +/** + * Created by ying on 2020/4/11. + * Describe: + */ +public class GlideUtils { + private static final String TAG = "GlideUtils"; + + public static void loadImage(ImageView imageView, Object imgRes, int radiusPx, int placeHolderRes) { + MultiTransformation transformation = null; + if (radiusPx > 0) { + transformation = new MultiTransformation<>(new RoundedCornersTransformation(radiusPx, 0, RoundedCornersTransformation.CornerType.ALL)); + } + if (placeHolderRes == 0) { + placeHolderRes = R.drawable.avatar_bg_white; + } + RequestBuilder req = Glide.with(imageView).load(imgRes).placeholder(placeHolderRes).error(R.drawable.nim_default_img_failed); + if (transformation != null) { + req.apply(RequestOptions.bitmapTransform(transformation).dontAnimate()); + } + req.into(imageView); + } + + public static void showVideo(final ImageView imageView, String url, SimpleTarget bitmapSimpleTarget) { + Glide.with(imageView.getContext()) + .setDefaultRequestOptions( + new RequestOptions() + .frame(1000000)//单位微秒 + .centerCrop() + ) + .asBitmap() + .load(StrU.getResourcePath(url, imageView.getContext())) + .into(bitmapSimpleTarget); + } + + public static void showVideoLocal(final Activity activity, final ImageView imageView, String url) { + Glide.with(activity) + .setDefaultRequestOptions( + new RequestOptions() + .frame(1000000)//单位微秒 + .centerCrop() + ) + .asBitmap() + .load(url) + .into(new SimpleTarget() { + @Override + public void onResourceReady(Bitmap resource, Transition transition) { + imageView.setImageBitmap(resource); + } + }); + } + + public static void showVideoRvLocal(final Activity activity, final ImageView imageView, String url, final int mag) { + + Glide.with(activity) + .setDefaultRequestOptions( + new RequestOptions() + .frame(1000000)//单位微秒 + .centerCrop() + ) + .asBitmap() + .load(url) + .into(new SimpleTarget() { + @Override + public void onResourceReady(Bitmap resource, Transition transition) { + Point outSize = new Point(); + activity.getWindowManager().getDefaultDisplay().getSize(outSize); + outSize.x = (outSize.x) / 2 - mag * 2; + double i = outSize.x * 10d / resource.getWidth() / 10.00d; + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onResourceReady: " + i); + ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams(); + layoutParams.width = (int) (resource.getWidth() * i); + layoutParams.height = (int) (resource.getHeight() * i); + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "width: " + resource.getWidth() + " height " + resource.getHeight()); + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "layoutParams width: " + layoutParams.width + " height " + layoutParams.height); + imageView.setLayoutParams(layoutParams); + imageView.setImageBitmap(resource); + } + }); + } + + public static void showVideo(final Activity activity, final ImageView imageView, String url, final int mag) { + GlideUtils.showVideo(imageView, url, new SimpleTarget() { + @Override + public void onResourceReady(Bitmap resource, Transition transition) { + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "width: " + resource.getWidth() + " height " + resource.getHeight()); + Point outSize = new Point(); + activity.getWindowManager().getDefaultDisplay().getSize(outSize); + outSize.x = (outSize.x) / 2 - mag * 2; + double i = outSize.x * 10d / resource.getWidth() / 10.00d; + ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams(); + layoutParams.width = (int) (resource.getWidth() * i); + layoutParams.height = (int) (resource.getHeight() * i); + imageView.setLayoutParams(layoutParams); + imageView.setImageBitmap(resource); + } + }); + } + + public static void showVideo(final ImageView imageView, String url, final int width) { + GlideUtils.showVideo(imageView, url, new SimpleTarget() { + @Override + public void onResourceReady(Bitmap resource, Transition transition) { + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "width: " + resource.getWidth() + " height " + resource.getHeight()); + ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams(); + layoutParams.width = width; + layoutParams.height = width * resource.getHeight() / resource.getWidth(); + imageView.setLayoutParams(layoutParams); + imageView.setImageBitmap(resource); + } + }); + } + + public static void showVideo(Context context, ImageView imageView, String url) { + imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + Glide.with(context) + .setDefaultRequestOptions( + new RequestOptions() + .frame(1000000)//单位微秒 + .centerCrop() + ).load(StrU.getResourcePath(url, context)) + .into(imageView); + + } + + public static void showImageNone(Context context, ImageView imageView, String url) { + Glide.with(context) + .load(StrU.getResourcePath(url, context)) + .apply(new RequestOptions() + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE) + ) + .into(imageView); + + } + + public static void showImage(Context context, ImageView imageView, String url) { + Glide.with(context) + .load(StrU.getResourcePath(url, context)) + .into(imageView); + + } + + /** + * 高斯模糊 + * + * @param context + * @param imageView + * @param url + * @param radius + */ + public static void showImageformation(Context context, ImageView imageView, String url, int radius) { + imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + Glide.with(context) + .load(StrU.getResourcePath(url, context)) + .apply(RequestOptions.bitmapTransform(new BlurTransformation(radius)) + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE)) + .into(imageView); + + } + + public static void showGif(final Context context, final ImageView imageView, @Nullable Integer resourceId) { + imageView.setVisibility(View.VISIBLE); + imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + imageView.setVisibility(View.GONE); + } + }); + Glide.with(context).asGif().load(resourceId).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + return false; + } + + @Override + public boolean onResourceReady(final GifDrawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + try { + Field gifStateField = GifDrawable.class.getDeclaredField("state"); + gifStateField.setAccessible(true); + Class gifStateClass = Class.forName("com.bumptech.glide.load.resource.gif.GifDrawable$GifState"); + Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader"); + gifFrameLoaderField.setAccessible(true); + Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.load.resource.gif.GifFrameLoader"); + Field gifDecoderField = gifFrameLoaderClass.getDeclaredField("gifDecoder"); + gifDecoderField.setAccessible(true); + Class gifDecoderClass = Class.forName("com.bumptech.glide.gifdecoder.GifDecoder"); + Object gifDecoder = gifDecoderField.get(gifFrameLoaderField.get(gifStateField.get(resource))); + Method getDelayMethod = gifDecoderClass.getDeclaredMethod("getDelay", int.class); + getDelayMethod.setAccessible(true); + //设置只播放一次 + // resource.setLoopCount(1); + resource.start(); + //获得总帧数 + int count = resource.getFrameCount(); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onResourceReady: 总帧数 " + count); + int delay = 0; + for (int i = 0; i < count; i++) { + //计算每一帧所需要的时间进行累加 + delay += (int) getDelayMethod.invoke(gifDecoder, i); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onResourceReady: 时间 " + delay); + } + delay *= 2; + final int finalDelay = delay; + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onResourceReady: 总时间 " + delay); + imageView.postDelayed(new Runnable() { + @Override + public void run() { + resource.stop(); + // Toast.makeText(context, "播放完成 " + finalDelay, Toast.LENGTH_SHORT).show(); + // imageView.setVisibility(View.GONE); + } + }, delay); + } catch (Exception e) { + e.printStackTrace(); + } + return false; + + } + + }).into(imageView); + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/GridDecoration.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/GridDecoration.kt new file mode 100644 index 0000000..87bd4dc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/GridDecoration.kt @@ -0,0 +1,181 @@ +package com.fengliyan.tianlesue.utils +import android.graphics.Canvas +import android.graphics.Rect +import android.graphics.RectF +import android.view.View +import androidx.annotation.ColorInt +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.blankj.utilcode.util.SizeUtils +import kotlin.math.roundToInt + +class GridDecoration : LinearDecoration() { + + private var horizontalSpace: Int = 0 + private var verticalSpace: Int = 0 + + + override fun setColor(@ColorInt color: Int): GridDecoration { + super.setColor(color) + return this + } + + /** + * 左右Border只对横向滚动并且Item宽度不填充为屏幕宽度的RecyclerView使用 + * (VERTICAL方向左右border设置无效) + * VERTICAL方向请自行设置recycleview左右padding为左右border的边距解决) + */ + override fun setBorder(borderLeft: Int, borderTop: Int, borderRight: Int, borderBottom: Int): GridDecoration { + super.setBorder(borderLeft, borderTop, borderRight, borderBottom) + return this + } + + override fun setBorder(leftDp: Float, topDp: Float, rightDp: Float, bottomDp: Float): GridDecoration { + super.setBorder(leftDp, topDp, rightDp, bottomDp) + return this + } + + fun setSizeDp(horizontalSpace: Float, verticalSpace: Float): GridDecoration { + this.horizontalSpace = SizeUtils.dp2px(horizontalSpace) + this.verticalSpace = SizeUtils.dp2px(verticalSpace) + super.setSize(this.verticalSpace) + return this + } + + fun setSize(horizontalSpace: Int, verticalSpace: Int): GridDecoration { + this.horizontalSpace = horizontalSpace + this.verticalSpace = verticalSpace + super.setSize(verticalSpace) + return this + } + + private fun getGridPosition(parent: RecyclerView, view: View): Int { + return parent.getChildAdapterPosition(view) + } + + private fun getGridItemCount(parent: RecyclerView): Int { + return parent.adapter?.itemCount ?: 0 + } + + + private fun isFirstRow(isVertical: Boolean, parent: RecyclerView, view: View): Boolean { + val childAdapterPosition = getGridPosition(parent, view) + val spanCount = (parent.layoutManager as GridLayoutManager).spanCount + return if (isVertical) { + childAdapterPosition < spanCount + } else { + childAdapterPosition % spanCount == 0 + } + } + + private fun isLastRow(isVertical: Boolean, parent: RecyclerView, view: View): Boolean { + val spanCount = (parent.layoutManager as GridLayoutManager).spanCount + val childAdapterPosition = getGridPosition(parent, view) + val itemCount = getGridItemCount(parent) + return if (isVertical) { + val remainder = itemCount % spanCount + childAdapterPosition >= itemCount - if (remainder == 0) spanCount else remainder + } else { + childAdapterPosition % spanCount == spanCount - 1 + } + } + + private fun isFirstColumn(isVertical: Boolean, parent: RecyclerView, view: View): Boolean { + val childAdapterPosition = getGridPosition(parent, view) + val spanCount = (parent.layoutManager as GridLayoutManager).spanCount + return if (isVertical) { + childAdapterPosition % spanCount == 0 + } else { + childAdapterPosition < spanCount + } + } + + private fun isLastColumn(isVertical: Boolean, parent: RecyclerView, view: View): Boolean { + val spanCount = (parent.layoutManager as GridLayoutManager).spanCount + val childAdapterPosition = getGridPosition(parent, view) + val itemCount = getGridItemCount(parent) + return if (isVertical) { + childAdapterPosition % spanCount == spanCount - 1 + } else { + childAdapterPosition >= itemCount - itemCount % spanCount + } + } + + + override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val layoutManager = parent.layoutManager + if (layoutManager is GridLayoutManager && layoutManager.spanCount == 1) { + super.onDraw(c, parent, state) + return + } + for (i in 0 until parent.childCount) { + val view = parent.getChildAt(i) + val rectf = RectF() + val rect = Rect() + getItemOffsetF(rectf, view, parent, state) + getItemOffsets(rect, view, parent, state) + val left = view.left - rect.left.toFloat() + val top = view.top - rect.top.toFloat() + val right = view.right + rect.right.toFloat() + val bottom = view.bottom + rect.bottom.toFloat() + //绘制左边分割线 + c.drawRect(left, top, left + rectf.left, bottom, dividerPaint) + //绘制上分割线 + c.drawRect(left, top, right, top + rectf.top, dividerPaint) + //绘制右边分割线 + c.drawRect(right - rectf.right, top, right, bottom, dividerPaint) + //绘制下分割线 + c.drawRect(left, bottom - rectf.bottom, right, bottom, dividerPaint) + } + } + + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { + //super.getItemOffsets(outRect, view, parent, state) + //精确的GridItem需要偏移的矩阵数据 + val rectF = RectF() + getItemOffsetF(rectF, view, parent, state) + if (parent.layoutDirection == View.LAYOUT_DIRECTION_LTR) { + outRect.left = rectF.left.roundToInt() + outRect.right = rectF.right.roundToInt() + } else { + outRect.left = rectF.right.roundToInt() + outRect.right = rectF.left.roundToInt() + } + outRect.top = rectF.top.roundToInt() + outRect.bottom = rectF.bottom.roundToInt() + } + + private fun getItemOffsetF(outRect: RectF, view: View, parent: RecyclerView, state: RecyclerView.State){ + val layoutManager = parent.layoutManager + if (layoutManager !is GridLayoutManager) { + outRect.set(horizontalSpace.toFloat()/2, 0f, horizontalSpace.toFloat()/2, verticalSpace.toFloat()) + return + } + if(layoutManager.spanCount == 1){ + val rect = Rect() + super.getItemOffsets(rect, view, parent, state) + outRect.set(rect.left.toFloat(), rect.top.toFloat(), rect.right.toFloat(), rect.bottom.toFloat()) + return + } + val isVertical = layoutManager.orientation == LinearLayoutManager.VERTICAL + val spanCount = layoutManager.spanCount + if(isVertical){ + val adapterPosition = parent.getChildAdapterPosition(view) + val eachWidth = (spanCount - 1) * horizontalSpace.toFloat() / spanCount + outRect.left = adapterPosition % spanCount * (horizontalSpace - eachWidth) + outRect.right = eachWidth - outRect.left + outRect.top = 0f + outRect.bottom = verticalSpace.toFloat() + }else{ + outRect.set(0f, 0f, horizontalSpace.toFloat(), verticalSpace.toFloat()) + } + //只接受2列并且左右border间距相等的边框分割线(否则左右边界线不做偏移) + if (spanCount == 2 && borderRect.left == borderRect.right) { + if (isFirstColumn(isVertical, parent, view)) outRect.left = outRect.left + borderRect.left + if (isLastColumn(isVertical, parent, view)) outRect.right = outRect.right + borderRect.right + } + if (isFirstRow(isVertical, parent, view)) outRect.top = borderRect.top.toFloat() + if (isLastRow(isVertical, parent, view)) outRect.bottom = borderRect.bottom.toFloat() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/InviteCodeUpdateUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/InviteCodeUpdateUtils.java new file mode 100644 index 0000000..c227827 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/InviteCodeUpdateUtils.java @@ -0,0 +1,115 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.ClipboardManager; +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; + +//该类用于绑定固定邀请人id +public class InviteCodeUpdateUtils { + private static final String TAG = "InviteCodeUpdateUtils"; + + public interface CodeCallback { + void callback(String code); + } + + public static String inviteCode = ""; + // public static String inviteCode = BuildConfig.InviteCode; + private static boolean isInit = false; + + public static String getLocalInviteCode() { + if (!isInit) { + getInviteCode(); + isInit = true; + } + String localInviteCode = UserManager.getInviteCode(); + if (!TextUtils.isEmpty(localInviteCode)) { + Log.i(TAG, "getLocalInviteCode:localInviteCode ------->" + localInviteCode); + return localInviteCode; + } else { + Log.i(TAG, "getLocalInviteCode:inviteCode ------->" + inviteCode); + return inviteCode; + } + } + + public static void getOpeninstallData(Context context, final CodeCallback callback) { +// OpenInstall.getInstall(new AppInstallListener() { +// @Override +// public void onInstallFinish(AppData appData, Error error) { +// if (appData != null) { +// String bindData = appData.getData(); +// Gson gson = new Gson(); +// InviteCodeBean inviteCodeBean = gson.fromJson(bindData, InviteCodeBean.class); +// Log.i(TAG, "onInstallFinish: bindData--------->" + bindData); +// if (inviteCodeBean != null) { +// UserManager.setInviteCode(inviteCodeBean.getInvite_code()); +// } +// } +// callback.callback(getLocalInviteCode()); +// } +// }); + // 获取ClipboardManager实例 + ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + if (manager != null) { + if (manager.hasPrimaryClip() && manager.getPrimaryClip().getItemCount() > 0) { + CharSequence addedText = manager.getPrimaryClip().getItemAt(0).getText(); + String addedTextString = String.valueOf(addedText); + if (!TextUtils.isEmpty(addedTextString)) { + if (addedTextString.startsWith("#siyu#")) { + // 使用textString变量进行操作,例如显示或处理文本数据 + String code = addedTextString.substring(6); + Log.d("Clipboard", "Text from Clipboard: " + code); + Log.i(TAG, "getOpeninstallData: ------->" + code); + UserManager.setInviteCode(code); + } + } + } + } + callback.callback(getLocalInviteCode()); + } + + public static void getInviteCode() { + String market = DeviceManager.getInstance().getApplicationMarket(); + switch (market) { + case "oss": + inviteCode = ""; + break; + case "vivo": + inviteCode = "1375043"; + break; + case "oppo": + inviteCode = "1375044"; + break; + case "xiaomi": + inviteCode = "1375045"; + break; + case "yingyongbao": + inviteCode = "1375047"; + break; + case "huawei": + inviteCode = "1423191"; + break; +// case "meizu": +// inviteCode = "1426940";` +// break; + case "baiduss": + inviteCode = "1621937"; + break; + case "baiduxxl": + inviteCode = "1450565"; + break; + case "douyin": + inviteCode = "1595267"; + break; + case "kuaishou": + inviteCode = "1595264"; + break; + case "honor": + inviteCode = "1626328"; + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/LinearDecoration.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/LinearDecoration.kt new file mode 100644 index 0000000..1fa2f45 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/LinearDecoration.kt @@ -0,0 +1,165 @@ +package com.fengliyan.tianlesue.utils +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Rect +import android.view.View +import androidx.annotation.ColorInt +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.blankj.utilcode.util.SizeUtils + +open class LinearDecoration : RecyclerView.ItemDecoration() { + + internal val dividerPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + internal val borderRect = Rect() + + private var dividerSize: Int = 0 + private val bgPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private var dividerPaddingStart = 0 + private var dividerPaddingEnd = 0 + + + init { + dividerPaint.color = Color.TRANSPARENT + dividerPaint.style = Paint.Style.FILL + bgPaint.color = Color.TRANSPARENT + bgPaint.style = Paint.Style.FILL + } + + + open fun setColor(@ColorInt color: Int): LinearDecoration { + dividerPaint.color = color + return this + } + + open fun setBorder( + borderLeft: Int, + borderTop: Int = borderLeft, + borderRight: Int = borderLeft, + borderBottom: Int = borderLeft + ): LinearDecoration { + borderRect.set(borderLeft, borderTop, borderRight, borderBottom) + return this + } + + open fun setBorder( + leftDp: Float, + topDp: Float = leftDp, + rightDp: Float = leftDp, + bottomDp: Float = leftDp + ): LinearDecoration { + borderRect.set( + SizeUtils.dp2px(leftDp), + SizeUtils.dp2px(topDp), + SizeUtils.dp2px(rightDp), + SizeUtils.dp2px(bottomDp) + ) + return this + } + + + fun setSizeDp(dividerSize: Float): LinearDecoration { + this.dividerSize = SizeUtils.dp2px(dividerSize) + return this + } + + fun setSize(dividerSize: Int): LinearDecoration { + this.dividerSize = dividerSize + return this + } + + fun setDivider( + @ColorInt paddingColor: Int, + @ColorInt dividerColor: Int, + dividerSize: Int, + start: Int, + end: Int = start + ): LinearDecoration { + dividerPaddingStart = start + dividerPaddingEnd = end + setSize(dividerSize) + setColor(dividerColor) + bgPaint.color = paddingColor + return this + } + + private fun isLastItem(parent: RecyclerView, item: View): Boolean { + val childAdapterPosition = parent.getChildAdapterPosition(item) + return childAdapterPosition == parent.adapter!!.itemCount - 1 + } + + private fun isFirstItem(parent: RecyclerView, item: View): Boolean { + val childAdapterPosition = parent.getChildAdapterPosition(item) + return childAdapterPosition == 0 + } + + override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val layoutManager = parent.layoutManager + if (layoutManager == null || layoutManager !is LinearLayoutManager) { + return + } + for (i in 0 until parent.childCount) { + val view = parent.getChildAt(i) + + val dividerLeft: Float + val dividerRight: Float + val dividerTop: Float + val dividerBottom: Float + val outRect = Rect() + getOffsets(outRect, view, parent) + + if ((parent.layoutManager as LinearLayoutManager).orientation == LinearLayoutManager.VERTICAL) { + dividerTop = view.top.toFloat() - outRect.top + dividerBottom = view.top.toFloat() + dividerLeft = (view.left + dividerPaddingStart).toFloat() + dividerRight = (view.right - dividerPaddingEnd).toFloat() + c.drawRect( + view.left.toFloat(), + dividerTop, + view.right.toFloat(), + dividerBottom, + bgPaint + ) + } else { + dividerLeft = view.left.toFloat() - outRect.left + dividerRight = view.left.toFloat() + dividerTop = (view.top + dividerPaddingStart).toFloat() + dividerBottom = (view.bottom - dividerPaddingEnd).toFloat() + c.drawRect( + dividerLeft, + view.top.toFloat(), + dividerRight, + view.bottom.toFloat(), + bgPaint + ) + } + c.drawRect(dividerLeft, dividerTop, dividerRight, dividerBottom, dividerPaint) + } + } + + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + getOffsets(outRect, view, parent) + } + + private fun getOffsets(outRect: Rect, view: View, parent: RecyclerView) { + val layoutManager = parent.layoutManager + if (layoutManager == null || layoutManager !is LinearLayoutManager) { + return + } + outRect.set(borderRect) + if (layoutManager.orientation == LinearLayoutManager.HORIZONTAL) { + outRect.left = if (isFirstItem(parent, view)) borderRect.left else dividerSize + outRect.right = if (isLastItem(parent, view)) borderRect.right else 0 + } else { + outRect.top = if (isFirstItem(parent, view)) borderRect.top else dividerSize + outRect.bottom = if (isLastItem(parent, view)) borderRect.bottom else 0 + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/ListStringSPUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/ListStringSPUtils.java new file mode 100644 index 0000000..3126ac6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/ListStringSPUtils.java @@ -0,0 +1,54 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +/** + * Created by zhangbin on 2019/1/19. + */ + +public class ListStringSPUtils { + private final static String name = "listString"; + private final static int mode = Context.MODE_PRIVATE; + + /** + * 保存首选项 + * @param context + * @param key + * @param value + */ + public static void saveString(Context context, String key, String value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putString(key, value); + edit.commit(); + } + /** + * 获取首选项 + * @param context + * @param key + * @param defValue + * @return + */ + + public static String getString(Context context, String key, String defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, defValue); + } + + public static String getString(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, ""); + } + + /** + * 清除保存 + * @param context + */ + public static void clear(Context context){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + editor.commit(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/LongSpUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/LongSpUtils.java new file mode 100644 index 0000000..a19c32a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/LongSpUtils.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +/** + * Created by zhangbin on 2018/12/22. + */ + +public class LongSpUtils { + + private final static String name = "long"; + private final static int mode = Context.MODE_PRIVATE; + + public static void saveLong(Context context, String key, long value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putLong(key, value); + edit.commit(); + } + + public static long getLong(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getLong(key, 0); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/MaskImageView.java b/app/src/main/java/com/fengliyan/tianlesue/utils/MaskImageView.java new file mode 100644 index 0000000..f0a8aca --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/MaskImageView.java @@ -0,0 +1,172 @@ +package com.fengliyan.tianlesue.utils; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.os.Build; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.ScriptIntrinsicBlur; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.request.RequestOptions; + +import java.security.MessageDigest; + +/** + * 自定义MaskImageView + * + * @author ThirdGoddess + * @email ofmyhub@gmail.com + * @Github https://github.com/ThirdGoddess + * @date :2020-05-23 21:54 毛玻璃 + */ +public class MaskImageView extends AppCompatImageView { + private Context context; + + //蒙版色值 + private int color = Color.parseColor("#66000000"); + + //是否显示蒙版 + private boolean isShowMask = true; + + public MaskImageView(Context context) { + super(context); + this.context = context; + } + + public MaskImageView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.context = context; + } + + public MaskImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.context = context; + } + + @SuppressLint("DrawAllocation") + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (isShowMask) { + canvas.drawColor(color); + } + } + + /** + * 设置蒙版颜色,可以通过类似于(#81FFFFFF)来控制透明度 + */ + public MaskImageView setMaskColor(int color) { + this.color = color; + return this; + } + + /** + * 显示蒙版 + */ + public void showMask() { + isShowMask = true; + invalidate(); + } + + /** + * 关闭蒙版 + */ + public void dismissMask() { + isShowMask = false; + invalidate(); + } + + /** + * 高斯模糊处理 + * + * @param radius + * @return + */ + public Bitmap setGaussblur(int radius, Bitmap source) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + RenderScript renderScript = RenderScript.create(context); + final Allocation input = Allocation.createFromBitmap(renderScript, source); + final Allocation output = Allocation.createTyped(renderScript, input.getType()); + ScriptIntrinsicBlur scriptIntrinsicBlur; + scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript)); + scriptIntrinsicBlur.setInput(input); + scriptIntrinsicBlur.setRadius(radius); + scriptIntrinsicBlur.forEach(output); + output.copyTo(source); + renderScript.destroy(); + return source; + } else { + return source; + } + } + + /** + * 开启高斯模糊 + * + * @return + */ + public RequestOptions setGaussBlur() { + return RequestOptions.bitmapTransform(new GlideBlurTransformation(context)); + } + + /** + * 压缩Bitmap + */ + public class GlideBlurTransformation extends CenterCrop { + private Context context; + + GlideBlurTransformation(Context context) { + this.context = context; + } + + @Override + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { + Bitmap bitmap = super.transform(pool, toTransform, outWidth, outHeight); + return blurBitmap(context, bitmap, 25 , (int) (outWidth * 0.6), (int) (outHeight * 0.6)); + } + + @Override + public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { + } + } + + /** + * 模糊Bitmap处理 + * + * @param context + * @param source + * @param blurRadius + * @param outWidth + * @param outHeight + * @return + */ + public Bitmap blurBitmap(Context context, Bitmap source, float blurRadius, int outWidth, int outHeight) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + Bitmap inputBitmap = Bitmap.createScaledBitmap(source, outWidth, outHeight, false); + Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap); + RenderScript rs = RenderScript.create(context); + ScriptIntrinsicBlur blurScript; + blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); + Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); + Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); + blurScript.setRadius(blurRadius); + blurScript.setInput(tmpIn); + blurScript.forEach(tmpOut); + tmpOut.copyTo(outputBitmap); + return outputBitmap; + } else { + return source; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/MeOnPermissionDescriptionListener.java b/app/src/main/java/com/fengliyan/tianlesue/utils/MeOnPermissionDescriptionListener.java new file mode 100644 index 0000000..3851516 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/MeOnPermissionDescriptionListener.java @@ -0,0 +1,113 @@ +package com.fengliyan.tianlesue.utils; + +import android.Manifest; +import android.graphics.Color; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.AbsoluteSizeSpan; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.ConstraintSet; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; + +import com.fengliyan.tianlesue.R; +import com.luck.picture.lib.interfaces.OnPermissionDescriptionListener; +import com.luck.picture.lib.permissions.PermissionConfig; +import com.luck.picture.lib.utils.DensityUtil; +import com.luck.picture.lib.widget.MediumBoldTextView; + +/** + * 添加权限说明 + */ +public class MeOnPermissionDescriptionListener implements OnPermissionDescriptionListener { + private final static String TAG_EXPLAIN_VIEW = "TAG_EXPLAIN_VIEW"; + + @Override + public void onPermissionDescription(Fragment fragment, String[] permissionArray) { + View rootView = fragment.requireView(); + if (rootView instanceof ViewGroup) { + addPermissionDescription(false, (ViewGroup) rootView, permissionArray); + } + } + + @Override + public void onDismiss(Fragment fragment) { + removePermissionDescription((ViewGroup) fragment.requireView()); + } + + + /** + * 添加权限说明 + * + * @param viewGroup + * @param permissionArray + */ + private static void addPermissionDescription(boolean isHasSimpleXCamera, ViewGroup viewGroup, String[] permissionArray) { + int dp10 = DensityUtil.dip2px(viewGroup.getContext(), 10); + int dp15 = DensityUtil.dip2px(viewGroup.getContext(), 15); + MediumBoldTextView view = new MediumBoldTextView(viewGroup.getContext()); + view.setTag(TAG_EXPLAIN_VIEW); + view.setTextSize(14); + view.setTextColor(Color.parseColor("#333333")); + view.setPadding(dp10, dp15, dp10, dp15); + + String title; + String explain; + + if (TextUtils.equals(permissionArray[0], PermissionConfig.CAMERA[0])) { + title = "相机权限使用说明"; + explain = "相机权限使用说明\n用户app用于拍照/录视频"; + } else if (TextUtils.equals(permissionArray[0], Manifest.permission.RECORD_AUDIO)) { + if (isHasSimpleXCamera) { + title = "麦克风权限使用说明"; + explain = "麦克风权限使用说明\n用户app用于录视频时采集声音"; + } else { + title = "录音权限使用说明"; + explain = "录音权限使用说明\n用户app用于采集声音"; + } + } else { + title = "存储权限使用说明"; + explain = "存储权限使用说明\n用户app写入/下载/保存/读取/修改/删除图片、视频、文件等信息"; + } + int startIndex = 0; + int endOf = startIndex + title.length(); + SpannableStringBuilder builder = new SpannableStringBuilder(explain); + builder.setSpan(new AbsoluteSizeSpan(DensityUtil.dip2px(viewGroup.getContext(), 16)), startIndex, endOf, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + builder.setSpan(new ForegroundColorSpan(0xFF333333), startIndex, endOf, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + view.setText(builder); + view.setBackground(ContextCompat.getDrawable(viewGroup.getContext(), R.drawable.bg_vip)); + + if (isHasSimpleXCamera) { + RelativeLayout.LayoutParams layoutParams = + new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + layoutParams.topMargin = DensityUtil.getStatusBarHeight(viewGroup.getContext()); + layoutParams.leftMargin = dp10; + layoutParams.rightMargin = dp10; + viewGroup.addView(view, layoutParams); + } else { + ConstraintLayout.LayoutParams layoutParams = + new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.WRAP_CONTENT); + layoutParams.topToBottom = R.id.title_bar; + layoutParams.leftToLeft = ConstraintSet.PARENT_ID; + layoutParams.leftMargin = dp10; + layoutParams.rightMargin = dp10; + viewGroup.addView(view, layoutParams); + } + } + + /** + * 移除权限说明 + * + * @param viewGroup + */ + private static void removePermissionDescription(ViewGroup viewGroup) { + View tagExplainView = viewGroup.findViewWithTag(TAG_EXPLAIN_VIEW); + viewGroup.removeView(tagExplainView); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/MeOnResultCallbackListener.java b/app/src/main/java/com/fengliyan/tianlesue/utils/MeOnResultCallbackListener.java new file mode 100644 index 0000000..b5f5708 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/MeOnResultCallbackListener.java @@ -0,0 +1,245 @@ +package com.fengliyan.tianlesue.utils; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.Base64; +import android.util.Log; + +import com.google.gson.Gson; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.utils.ToastUtil; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.media.ImageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.string.MD5; +import com.fengliyan.tianlesue.model.chat.ImageCheckBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.settings.video.ExtractFrameWorkThread; +import com.fengliyan.tianlesue.view.settings.video.ExtractVideoInfoUtil; +import com.fengliyan.tianlesue.view.settings.video.PictureUtils; +import com.fengliyan.tianlesue.view.settings.video.VideoEditInfo; +import com.fengliyan.uikit.toast.MaleToast; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; +import com.luck.picture.lib.entity.MediaExtraInfo; +import com.luck.picture.lib.interfaces.OnResultCallbackListener; +import com.luck.picture.lib.utils.MediaUtils; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +public class MeOnResultCallbackListener implements OnResultCallbackListener { + private ExtractFrameWorkThread mExtractFrameWorkThread; + private long endPosition; + private final List pornList = new ArrayList<>(); + private int thumbnailsCount; + private String videoMd5; + private File videoFile; + private String OutPutFileDirPath; + private ExtractVideoInfoUtil mExtractVideoInfoUtil; + private Activity activity; + private String sessionId; + private SessionTypeEnum sessionType; + private SendMsgCallBack mSendMsgCallBack; + + public interface SendMsgCallBack { + void sendMsgCallBack(IMMessage message); + } + + public MeOnResultCallbackListener(Activity activity, String sessionId, SessionTypeEnum sessionType, SendMsgCallBack mSendMsgCallBack) { + this.activity = activity; + this.sessionId = sessionId; + this.sessionType = sessionType; + this.mSendMsgCallBack = mSendMsgCallBack; + } + + @Override + public void onResult(ArrayList result) { + for (LocalMedia media : result) { + if (media.getWidth() == 0 || media.getHeight() == 0) { + if (PictureMimeType.isHasImage(media.getMimeType())) { + MediaExtraInfo imageExtraInfo = MediaUtils.getImageSize(activity, media.getPath()); + media.setWidth(imageExtraInfo.getWidth()); + media.setHeight(imageExtraInfo.getHeight()); + } else if (PictureMimeType.isHasVideo(media.getMimeType())) { + MediaExtraInfo videoExtraInfo = MediaUtils.getVideoSize(activity, media.getPath()); + media.setWidth(videoExtraInfo.getWidth()); + media.setHeight(videoExtraInfo.getHeight()); + } + } + Log.i("TAG", "onResult: media------>" + media.getRealPath()); + if (PictureMimeType.isHasImage(media.getMimeType())) { + File imageFile = new File(media.getRealPath()); + String extension = FileUtil.getExtensionName(media.getRealPath()); + imageFile = ImageUtil.getScaledImageFileWithMD5(imageFile, extension); + if (imageFile != null) { + IMMessage message = MessageBuilder.createImageMessage(sessionId, sessionType, imageFile, imageFile.getName()); + if (mSendMsgCallBack != null) { + mSendMsgCallBack.sendMsgCallBack(message); + } + } else { + ToastHelper.showToast(activity, R.string.image_show_error); + } + } else if (PictureMimeType.isHasVideo(media.getMimeType())) { + videoMd5 = MD5.getStreamMD5(media.getRealPath()); + String filename = videoMd5 + "." + FileUtil.getExtensionName(media.getRealPath()); + String md5Path = StorageUtil.getWritePath(filename, StorageType.TYPE_VIDEO); + if (AttachmentStore.copy(media.getRealPath(), md5Path) != -1) { + videoFile = new File(md5Path); + pornList.clear(); + thumbnailsCount = NoClearSPUtils.getInt(activity, ConsUser.SEND_VIDEO_MAX_NUM); + int interval = NoClearSPUtils.getInt(activity, ConsUser.SEND_VIDEO_INTERVAL) * 1000; + OutPutFileDirPath = PictureUtils.getSaveEditThumbnailDir(activity); + mExtractVideoInfoUtil = new ExtractVideoInfoUtil(videoFile.getAbsolutePath()); + long duration = Long.parseLong(mExtractVideoInfoUtil.getVideoLength()); + int length = interval * thumbnailsCount; + if (length > duration) { + thumbnailsCount = (int) (duration / interval); + endPosition = (long) interval * thumbnailsCount; + if (thumbnailsCount < 1) { + thumbnailsCount = 1; + endPosition = duration; + } + } else { + endPosition = length; + } + int extractW = mExtractVideoInfoUtil.getVideoWidth(); + int extractH = mExtractVideoInfoUtil.getVideoHeight(); + mExtractFrameWorkThread = new ExtractFrameWorkThread(extractW, extractH, mUIHandler, videoFile.getAbsolutePath(), OutPutFileDirPath, 0, endPosition, thumbnailsCount); + mExtractFrameWorkThread.start(); + } else { + ToastHelper.showToast(activity, R.string.video_exception); + } + } + } + } + + @Override + public void onCancel() { + Log.i("TAG", "PictureSelector Cancel"); + } + + private Handler mUIHandler = new SafeHandler(this); + + private static class SafeHandler extends Handler { + private final WeakReference outerClassReference; + + public SafeHandler(MeOnResultCallbackListener context) { + this.outerClassReference = new WeakReference<>(context); + } + + @Override + public void handleMessage(Message msg) { + MeOnResultCallbackListener outerClass = outerClassReference.get(); + if (outerClass == null) { + return; // 外部类已经被回收 + } + + switch (msg.what) { + case ExtractFrameWorkThread.MSG_SAVE_SUCCESS: + outerClass.checkVideo(msg); + break; + default: + // 可选:记录未处理的消息类型以便调试 + // Log.d("SafeHandler", "Unhandled message: " + msg.what); + break; + } + } + } + + //视频鉴黄 + private void checkVideo(Message msg) { + VideoEditInfo info = (VideoEditInfo) msg.obj; + final Bitmap bitmap = BitmapFactory.decodeFile(info.path); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + if (bitmap != null) { + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); //参数100表示不压缩 + } + String img = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT); + pornList.add(img); + if (pornList.size() == thumbnailsCount) { + String s = new Gson().toJson(pornList); + SettingManager.videoCheck((BaseActivity) activity, s, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ImageCheckBean result, String tips) { + destroyWork(); + if (result.getIs_upload() == 1) { + MediaPlayer mediaPlayer = getVideoMediaPlayer(videoFile); + long duration = mediaPlayer == null ? 0 : mediaPlayer.getDuration(); + int height = mediaPlayer == null ? 0 : mediaPlayer.getVideoHeight(); + int width = mediaPlayer == null ? 0 : mediaPlayer.getVideoWidth(); + IMMessage message = MessageBuilder.createVideoMessage(sessionId, sessionType, videoFile, duration, width, height, videoMd5); + if (mSendMsgCallBack != null) { + mSendMsgCallBack.sendMsgCallBack(message); + } + } else { + MaleToast.showMessage(activity, "视频违规"); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + destroyWork(); + ToastUtil.showToast(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + destroyWork(); + ToastUtil.showToast(activity, "发送失败" + e.getMessage()); + } + }); + } + } + + //释放相关资源 + private void destroyWork() { + if (mExtractFrameWorkThread != null) { + mExtractFrameWorkThread.stopExtract(); + } + if (mExtractVideoInfoUtil != null) { + mExtractVideoInfoUtil.release(); + } + if (!TextUtils.isEmpty(OutPutFileDirPath)) { + PictureUtils.deleteFile(new File(OutPutFileDirPath)); + } + if (mUIHandler != null) { + mUIHandler.removeCallbacksAndMessages(null); + } + } + + /** + * 获取视频mediaPlayer + * + * @param file 视频文件 + * @return mediaPlayer + */ + private MediaPlayer getVideoMediaPlayer(File file) { + try { + return MediaPlayer.create(activity, Uri.fromFile(file)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} + + diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/NinePatchDrawableFactory.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/NinePatchDrawableFactory.kt new file mode 100644 index 0000000..a74df57 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/NinePatchDrawableFactory.kt @@ -0,0 +1,408 @@ +package com.fengliyan.tianlesue.utils + +import android.content.Context +import android.content.res.Resources +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Matrix +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.graphics.drawable.NinePatchDrawable +import android.util.DisplayMetrics +import android.util.Log +import androidx.annotation.DrawableRes +import java.io.File +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/** + * Created by p_dmweidu on 2023/11/6 + * Desc: 从文件或者资源中加载一张png,然后转化成NinePatchDrawable返回。 + */ +class NinePatchDrawableFactory(private val context: Context) { + + companion object { + + private const val TAG = "NinePatchDrawableFactor" + + //Note: 把加载过的图片缓存在内存里 + private val bitmapLruCache = BitmapLruCache() + + val NO_COLOR = 0x00000001 + val COLOR_SIZE = 9 + + /** + * 同一个路径的图片,如果需要水平镜像,保存到在LruCache的时候,key就是这个前缀+图片路径 + */ + val HORIZONTAL_MIRROR_PREFIX = "horizontal_mirror_prefix" + + } + + /** + * 文件中,原始图片的密度,这里默认是1,如果是3倍图,就是3 + * 从文件中解析出来的bitmap,需要设置inDensity,inTargetDensity,才能正确的缩放 + */ + private var bitmapMapInDensity: Int = 1 + + /** + * 是否要水平镜像,如果左右气泡都用一张图的话,需要水平镜像一下 + */ + private var horizontalMirror = false + + /** + * 图片资源id + */ + @DrawableRes + private var drawableResId: Int = 0 + + /** + * 图片文件,目前只测试了png格式 + */ + private var drawableFile: File? = null + + /** + * 原始图片宽高 + */ + private var originWidth: Int = 0 + private var originHeight: Int = 0 + + /** + * 最终使用的图片宽高 + */ + private var finalWidth: Int = 0 + private var finalHeight: Int = 0 + + private var horizontalStretchBean: PatchStretchBean? = null + private var verticalStretchBean: PatchStretchBean? = null + + private var paddingRect: Rect? = null + + private var paddingLeft: Int = 0 + private var paddingRight: Int = 0 + private var paddingTop: Int = 0 + private var paddingBottom: Int = 0 + + private var chunk: ByteArray? = null + + private var finalPaddingRect = Rect() + + /** + * 从资源文件中加载图片 + */ + fun buildFromResource(): Drawable? { + val currentTimeMillis = System.currentTimeMillis() + val ninePatchDrawable = get9PatchFromResource(context.resources, drawableResId) + Log.i( + TAG, "buildFromResource: end 耗时:${System.currentTimeMillis() - currentTimeMillis} ms" + ) + return ninePatchDrawable + } + + /** + * 从文件中加载图片 + */ + fun buildFromFile(): Drawable? { + val currentTimeMillis = System.currentTimeMillis() + val ninePatchDrawable = get9PatchFromFile(context.resources, drawableFile) + + Log.i( + TAG, + "buildFromFile: end 耗时:${System.currentTimeMillis() - currentTimeMillis} ms" + ) + return ninePatchDrawable + } + + /** + * 设置横向的拉伸线段,必须的 + * @param horizontalStretchBean 横向的拉伸线段 + */ + fun setHorizontalStretchBean(horizontalStretchBean: PatchStretchBean): NinePatchDrawableFactory { + this.horizontalStretchBean = horizontalStretchBean + return this + } + + /** + * 设置竖向的拉伸线段,必须的 + * @param verticalStretchBean 竖向的拉伸线段 + */ + fun setVerticalStretchBean(verticalStretchBean: PatchStretchBean): NinePatchDrawableFactory { + this.verticalStretchBean = verticalStretchBean + return this + } + + /** + * 设置原始图片的宽高,必须的,是不是可以从bitmap里获取?不能,因为第二次复用的时候,无法获取原始图片的宽度和高度 + * @param originWidth 原始图片的宽度 + * @param originHeight 原始图片的高度 + */ + fun setOriginSize(originWidth: Int, originHeight: Int): NinePatchDrawableFactory { + this.originWidth = originWidth + this.originHeight = originHeight + return this + } + + fun setDrawableResId(drawableResId: Int): NinePatchDrawableFactory { + this.drawableResId = drawableResId + return this + } + + fun setDrawableFile(drawableFile: File): NinePatchDrawableFactory { + this.drawableFile = drawableFile + return this + } + + fun setBitmapMapInDensity(bitmapMapInDensity: Int): NinePatchDrawableFactory { + this.bitmapMapInDensity = bitmapMapInDensity + return this + } + + /** + * 设置padding,不是必须的。 + * @param rect padding的区域 + */ + fun setPadding(rect: Rect): NinePatchDrawableFactory { + paddingRect = rect + return this + } + + /** + * 设置是否水平镜像,如果左右聊天气泡都用一张图的话,需要水平镜像一下,不是必须的 + * @param horizontalMirror 是否水平镜像 + */ + fun setHorizontalMirror(horizontalMirror: Boolean): NinePatchDrawableFactory { + this.horizontalMirror = horizontalMirror + return this + } + + /** + * @param resources + * @param resId 图片资源id + */ + private fun get9PatchFromResource(resources: Resources, resId: Int): Drawable? { + val resIdString = resId.toString() + Log.i(TAG, "setResourceData: resId = $resId") + + var bitmap = if (horizontalMirror) { + bitmapLruCache.getBitmap(HORIZONTAL_MIRROR_PREFIX + resIdString) + } else { + bitmapLruCache.getBitmap(resIdString) + } + + if (bitmap == null) { + bitmap = try { + BitmapFactory.decodeResource(resources, resId) + } catch (e: Throwable) { + e.printStackTrace() + null + } + + if (bitmap != null) { + if (horizontalMirror) { + val matrix = Matrix() + matrix.postScale(-1f, 1f) + val mirrorBitmap = Bitmap.createBitmap( + bitmap, 0, 0, bitmap.width, bitmap.height, matrix, + false + ) + bitmapLruCache.putBitmap( + HORIZONTAL_MIRROR_PREFIX + resIdString, + mirrorBitmap + ) + bitmap = mirrorBitmap + } else { + bitmapLruCache.putBitmap(resIdString, bitmap) + } + Log.i(TAG, "setResourceData: width = ${bitmap.width}, height = ${bitmap.height}") + } + } else { + Log.i(TAG, "setResourceData: 从缓存中获取bitmap != null") + } + + setFinalUsedBitmapSize(bitmap) + + return get9PatchDrawable(bitmap, resources) + } + + /** + * 设置本地文件夹中的图片 + * 从文件解析的话,需要处理缩放,density + * @param file 本地png文件路径 + */ + private fun get9PatchFromFile( + resources: Resources, + file: File? + ): Drawable? { + + if (file == null || !file.exists()) { + return null + } + + val absolutePath = file.absolutePath + + var bitmap = if (horizontalMirror) { + bitmapLruCache.getBitmap(HORIZONTAL_MIRROR_PREFIX + absolutePath) + } else { + bitmapLruCache.getBitmap(absolutePath) + } + + if (bitmap == null) { + + bitmap = try { + BitmapFactory.decodeFile(absolutePath, BitmapFactory.Options().apply { + //bitmap 原本的密度 + inDensity = bitmapMapInDensity * DisplayMetrics.DENSITY_DEFAULT + //当前设备的密度 + inTargetDensity = resources.displayMetrics.densityDpi + }) + } catch (e: Throwable) { + e.printStackTrace() + null + } + if (bitmap != null) { + + Log.i( + TAG, + "setFileData: not scale width = ${bitmap.width}, height = ${bitmap.height}" + ) + + if (horizontalMirror) { + val matrix = Matrix() + matrix.postScale(-1f, 1f) + val mirrorBitmap = + Bitmap.createBitmap( + bitmap, + 0, + 0, + bitmap.width, + bitmap.height, + matrix, + false + ) + bitmapLruCache.putBitmap( + HORIZONTAL_MIRROR_PREFIX + absolutePath, + mirrorBitmap + ) + bitmap = mirrorBitmap + } else { + bitmapLruCache.putBitmap(absolutePath, bitmap) + } + } + } + setFinalUsedBitmapSize(bitmap) + + return get9PatchDrawable(bitmap, resources) + + } + + /** + * 控制内容填充的区域 + * (注意:这里的left,top,right,bottom同xml文件中的padding意思一致,只不过这里是百分比形式) + */ + private fun buildPadding() { + if (horizontalMirror) { + finalPaddingRect.left = ((originWidth - paddingRight) * finalWidth / originWidth) + finalPaddingRect.right = ((paddingLeft * finalWidth) / originWidth) + } else { + finalPaddingRect.left = ((paddingLeft * finalWidth) / originWidth) + finalPaddingRect.right = ((originWidth - paddingRight) * finalWidth / originWidth) + } + finalPaddingRect.top = (paddingTop * finalHeight / originHeight) + finalPaddingRect.bottom = ((originHeight - paddingBottom) * finalHeight / originHeight) + + Log.i(TAG, "buildPadding: rect = $finalPaddingRect") + } + + /** + * 直接处理bitmap数据 + */ + private fun setFinalUsedBitmapSize(bitmap: Bitmap?) { + Log.i(TAG, "setBitmapData: width = ${bitmap?.width}, height = ${bitmap?.height}") + this.finalWidth = bitmap?.width ?: 0 + this.finalHeight = bitmap?.height ?: 0 + } + + private fun buildChunk(): ByteArray { + // 横向和竖向端点的数量 = 线段数量 * 2,这里只有一个线段,所以都是2 + val horizontalEndpointsSize = 2 + val verticalEndpointsSize = 2 + + //这里计算的 arraySize 是 int 值,最终占用的字节数是 arraySize * 4 + val arraySize = 1 + 2 + 4 + 1 + horizontalEndpointsSize + verticalEndpointsSize + COLOR_SIZE + //这里乘以4,是因为一个int占用4个字节 + val byteBuffer = ByteBuffer.allocate(arraySize * 4).order(ByteOrder.nativeOrder()) + + byteBuffer.put(1.toByte()) //第一个字节无意义,不等于0就行 + byteBuffer.put(horizontalEndpointsSize.toByte()) //mDivX x数组的长度 + byteBuffer.put(verticalEndpointsSize.toByte()) //mDivY y数组的长度 + byteBuffer.put(COLOR_SIZE.toByte()) //mColor数组的长度 + + // skip 8 bytes + byteBuffer.putInt(0) + byteBuffer.putInt(0) + + //Note: 等待进一步研究,这四个int值,好像都写0也可以。 + //左右padding + byteBuffer.putInt(finalPaddingRect.left) + byteBuffer.putInt(finalPaddingRect.right) + //上下padding + byteBuffer.putInt(finalPaddingRect.top) + byteBuffer.putInt(finalPaddingRect.bottom) + +// byteBuffer.putInt(0) +// byteBuffer.putInt(0) +// //上下padding +// byteBuffer.putInt(0) +// byteBuffer.putInt(0) + + +// // skip 4 bytes + byteBuffer.putInt(0) + + // regions 控制横向拉伸的线段数据 + //mDivX数组 + horizontalStretchBean?.let { + if (horizontalMirror) { + byteBuffer.putInt((originWidth - it.end) * finalWidth / originWidth) + byteBuffer.putInt((originWidth - it.start) * finalWidth / originWidth) + } else { + byteBuffer.putInt(it.start * finalWidth / originWidth) + byteBuffer.putInt(it.end * finalWidth / originWidth) + } + } + + //mDivY数组 + // regions 控制竖向拉伸的线段数据 + verticalStretchBean?.let { + byteBuffer.putInt(it.start * finalHeight / originHeight) + byteBuffer.putInt(it.end * finalHeight / originHeight) + } + + //mColor数组 + for (i in 0 until COLOR_SIZE) { + byteBuffer.putInt(NO_COLOR) + } + + return byteBuffer.array() + } + + private fun get9PatchDrawable(bitmap: Bitmap?, resources: Resources): Drawable? { + return try { + paddingRect?.let { + paddingLeft = it.left + paddingRight = it.right + paddingTop = it.top + paddingBottom = it.bottom + buildPadding() + } + if (chunk == null) { + chunk = buildChunk() + } + val ninePatchDrawable = + NinePatchDrawable(resources, bitmap, chunk, finalPaddingRect, null) + ninePatchDrawable + } catch (e: Exception) { + null + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/NoClearSPUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/NoClearSPUtils.java new file mode 100644 index 0000000..7774d78 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/NoClearSPUtils.java @@ -0,0 +1,88 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +/** + * Created by zhangbin on 2019/2/21. + */ + +public class NoClearSPUtils { + + private final static String name = "no_clear_sp"; + private final static int mode = Context.MODE_PRIVATE; + + /** + * 保存首选项 + * @param context + * @param key + * @param value + */ + public static void saveBoolean(Context context, String key, boolean value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putBoolean(key, value); + edit.commit(); + } + public static void saveInt(Context context, String key, int value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putInt(key, value); + edit.commit(); + } + public static void saveString(Context context, String key, String value){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor edit = sp.edit(); + edit.putString(key, value); + edit.commit(); + } + + + /** + * 获取首选项 + * @param context + * @param key + * @param defValue + * @return + */ + public static boolean getBoolean(Context context, String key, boolean defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getBoolean(key, defValue); + } + + public static boolean getBoolean(Context context, String key){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getBoolean(key, false); + } + + public static int getInt(Context context, String key, int defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, defValue); + } + + public static int getInt(Context context, String key){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, 0); + } + + public static String getString(Context context, String key, String defValue){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, defValue); + } + + public static String getString(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, ""); + } + + /** + * 清除保存 + * @param context + */ + public static void clear(Context context){ + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + editor.commit(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/NotificationsUpUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/NotificationsUpUtils.java new file mode 100644 index 0000000..f033bff --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/NotificationsUpUtils.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.utils; + +import android.app.NotificationManager; +import android.content.Context; +import android.content.pm.ApplicationInfo; + +import java.lang.reflect.Method; + +/** + * Created by zhangbin on 2018/12/22. + */ + +public class NotificationsUpUtils { + + public static boolean isEnableV26(Context context) { + ApplicationInfo appInfo = context.getApplicationInfo(); + String pkg = context.getApplicationContext().getPackageName(); + int uid = appInfo.uid; + try { + NotificationManager notificationManager = (NotificationManager) + context.getSystemService(Context.NOTIFICATION_SERVICE); + Method sServiceField = notificationManager.getClass().getDeclaredMethod("getService"); + sServiceField.setAccessible(true); + Object sService = sServiceField.invoke(notificationManager); + + Method method = sService.getClass().getDeclaredMethod("areNotificationsEnabledForPackage" + , String.class, Integer.TYPE); + method.setAccessible(true); + return (boolean) method.invoke(sService, pkg, uid); + } catch (Exception e) { + return true; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/NotificationsUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/NotificationsUtils.java new file mode 100644 index 0000000..a9b0820 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/NotificationsUtils.java @@ -0,0 +1,139 @@ +package com.fengliyan.tianlesue.utils; + +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.app.AppOpsManager; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.os.Build; + +import androidx.core.app.NotificationCompat; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.VideoRequestBean; +import com.fengliyan.tianlesue.receiver.NotificationReceiver; +import com.fengliyan.tianlesue.view.main.MainActivity; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; + +/** + * Created by zhangbin on 2018/12/22. + */ + +public class NotificationsUtils { + + private static final String CHECK_OP_NO_THROW = "checkOpNoThrow"; + private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION"; + + @SuppressLint("NewApi") + public static boolean isNotificationEnabled(Context context) { + + AppOpsManager mAppOps = + (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + + ApplicationInfo appInfo = context.getApplicationInfo(); + String pkg = context.getApplicationContext().getPackageName(); + int uid = appInfo.uid; + Class appOpsClass = null; + + /* Context.APP_OPS_MANAGER */ + try { + appOpsClass = Class.forName(AppOpsManager.class.getName()); + + Method checkOpNoThrowMethod = + appOpsClass.getMethod(CHECK_OP_NO_THROW, + Integer.TYPE, Integer.TYPE, String.class); + + Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION); + int value = (Integer) opPostNotificationValue.get(Integer.class); + + return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == + AppOpsManager.MODE_ALLOWED); + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + public static void sendNotification(Context context, VideoRequestBean videoRequestBaseBean) { + if (videoRequestBaseBean == null) return; + Intent intentCancel = new Intent(context, NotificationReceiver.class); + intentCancel.setAction("notification_cancelled"); + String channel_id = "CHANNEL_ID12"; + intentCancel.putExtra(NotificationReceiver.TYPE, channel_id); + PendingIntent pendingIntentCancel = PendingIntent.getBroadcast(context, 0, intentCancel, PendingIntent.FLAG_ONE_SHOT); + + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Intent intent = new Intent(context, MainActivity.class); + intent.putExtra("videoRequestBaseBean", videoRequestBaseBean); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + Notification notification; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel notificationChannel = createNotificationChannel(); + if (notificationChannel != null) { + notificationManager.createNotificationChannel(notificationChannel); + notification = new NotificationCompat.Builder(context, "私语") + .setSmallIcon(R.mipmap.ic_launcher) + .setContentTitle("您收到一条视频通话") + .setSmallIcon(R.mipmap.ic_launcher) + .setContentText("您收到一条视频通话") + .setContentIntent(pendingIntent) + .setDeleteIntent(pendingIntentCancel) + .setAutoCancel(true) + .build(); + notificationManager.notify(MainActivity.mCallID, notification); + } + } else { + notification = new NotificationCompat.Builder(context, "私语") + .setContentTitle("您收到一条视频通话") + .setContentText("您收到一条视频通话") + .setContentIntent(pendingIntent) + .setSmallIcon(R.mipmap.ic_launcher) + .setAutoCancel(true) + .setDeleteIntent(pendingIntentCancel) + .build(); + notificationManager.notify(MainActivity.mCallID, notification); + } + } + + private static NotificationChannel createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel notificationChannel = new NotificationChannel("私语", + "私语通知", NotificationManager.IMPORTANCE_HIGH); + return notificationChannel; + } + return null; + } + + public static boolean isAppOnForeground(Context context) { + ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService( + Context.ACTIVITY_SERVICE); + String packageName = context.getApplicationContext().getPackageName(); + List appProcesses = activityManager.getRunningAppProcesses(); + if (appProcesses == null) + return false; + for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { + if (appProcess.processName.equals(packageName) + && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { + return true; + } + } + return false; + } + + public static void bring2Front(Context context) { + ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List list = activityManager.getAppTasks(); + for (ActivityManager.AppTask appTask : list) { + appTask.moveToFront(); + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/PatchStretchBean.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/PatchStretchBean.kt new file mode 100644 index 0000000..9e5c343 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/PatchStretchBean.kt @@ -0,0 +1,10 @@ +package com.fengliyan.tianlesue.utils + +/** + * Created by dmw on 2023/10/23 + * Desc: 定义拉伸区域的起点和终点 + */ +data class PatchStretchBean( + val start: Int, + val end: Int +) \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/PayUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/PayUtils.java new file mode 100644 index 0000000..4c22ea9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/PayUtils.java @@ -0,0 +1,121 @@ +package com.fengliyan.tianlesue.utils; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.view.base.PayWebViewActivity; +import com.fengliyan.uikit.toast.MaleToast; +import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +import java.util.List; + +public class PayUtils { + + /** + * 汇付微信小程序支付 + * + * @param context + * @param goodsID + * @param type + * @param mini_program_type 0-正式版 1-开发版 2-体验版 + */ + public static void wxminiPay(Activity context, int goodsID, int type, String ghOriId, int mini_program_type) { + String appId = Constant.WECHAT_APP_ID; // 填应用AppId + IWXAPI api = WXAPIFactory.createWXAPI(context, appId); + boolean isWXAppInstalledAndSupported = api.isWXAppInstalled(); + if (isWXAppInstalledAndSupported) { + api.openWXApp(); + api.registerApp(appId); + String path = String.format("pages/info/index?token=%s&source_app=4&channel=wechat&goodsId=%d&type=%d&version=%s&source_id=%d", DeviceManager.getInstance().getToken(), goodsID, type, BuildConfig.VERSION_NAME, 1); + WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req(); +// req.userName = "gh_302cef1cd1e8"; // 填小程序原始id + req.userName = ghOriId; // 填小程序原始id + req.path = path; //拉起小程序页面的可带参路径,不填默认拉起小程序首页,对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar"。 + if (mini_program_type == 2) { + req.miniprogramType = WXLaunchMiniProgram.Req.MINIPROGRAM_TYPE_PREVIEW;// 可选打开 开发版,体验版和正式版 + } else if (mini_program_type == 1) { + req.miniprogramType = WXLaunchMiniProgram.Req.MINIPROGRAM_TYPE_TEST;// 可选打开 开发版,体验版和正式版 + } else { + req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;// 可选打开 开发版,体验版和正式版 + } + api.sendReq(req); + } else { + MaleToast.showMessage(context, "未安装微信,不能支付"); + } + } + + //汇付支付宝唤醒 + public static void ailWeb(String qrcodeUrl, Activity context) { + // 固定前缀 + String topic = "alipays://platformapi/startapp?saId=10000007&qrcode="; +// 从汇付正扫接口获取的参数(以下值仅为示例) + String jumpUrl = topic + qrcodeUrl; +// 按以上示例拼接得出结果 +// jumpUrl 为 alipays://platformapi/startapp?saId=10000007&qrcode=https://qr.alipay.com/bax02911brluc2xieoph6001 + + Intent intent = new Intent(); + intent.setAction("android.intent.action.VIEW"); +// jumpUrl 为先前示例中拼装的 url + Uri contentUrl = Uri.parse(jumpUrl); + intent.setData(contentUrl); + context.startActivity(intent); + } + + /** + * 商福通支付 + * + * @param context + * @param url + */ + public static void SFTPay(Activity context, String url) { + if (url.startsWith("weixin://")) { + IWXAPI api = WXAPIFactory.createWXAPI(context, null); + api.registerApp(Constant.WECHAT_APP_ID); + if (isWeChatAppInstalled(context, api)) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + context.startActivity(intent); + } else { + MaleToast.showMessage(context, "您还未安装微信客户端"); + } + } else if (url.startsWith("https://")) { + Intent intent = new Intent(context, PayWebViewActivity.class); + intent.putExtra("ClickUrl", url); + intent.putExtra("type", 5); + context.startActivity(intent); + } + } + + public static boolean isWeChatAppInstalled(Context context, IWXAPI api) { + if (api.isWXAppInstalled()) { + return true; + } else { + final PackageManager packageManager = context.getPackageManager();// 获取packagemanager + List pinfo = packageManager.getInstalledPackages(0);// 获取所有已安装程序的包信息 + if (pinfo != null) { + for (int i = 0; i < pinfo.size(); i++) { + String pn = pinfo.get(i).packageName; + if (pn.equalsIgnoreCase("com.tencent.mm")) { + return true; + } + } + } + return false; + } + } + + public static boolean parseScheme(String url) { + return url.contains("platformapi/startapp") || (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) && (url.contains("platformapi") && url.contains("startapp")); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/PermissionUtil.java b/app/src/main/java/com/fengliyan/tianlesue/utils/PermissionUtil.java new file mode 100644 index 0000000..99ed762 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/PermissionUtil.java @@ -0,0 +1,244 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.BuildConfig; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + + +public class PermissionUtil { + public static void jumpPermissionPage(Context context) { + String manufacturer = Build.MANUFACTURER.toLowerCase(); + switch (manufacturer) { + case "xiaomi": + goXiaoMiManager(context); + break; + case "huawei": + goHuaWeiManager(context); + break; + case "oppo": + goOppoManager(context); + break; + case "meizu": + goMeizuManager(context); + break; + case "samsung": + goSamsungManager(context); + break; + case "sony": + goSonyManager(context); + break; + case "lg": + goLGManager(context); + break; + case "letv": + goLetvManager(context); + break; + case "qiku": + case "360": + go360Manager(context); + break; + case "vivo": + goVivoManager(context); + break; + default: + goAppDetailSetting(context); + break; + } + } + + private static void goXiaoMiManager(Context context) { + String rom = checkMIUI(); + try{ + Intent intent =new Intent(); + if ("V5".equals(rom)) { + Uri packageURI = Uri.parse("package:" + BuildConfig.APPLICATION_ID); + intent =new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI); + } else if ("V6".equals(rom) || "V7".equals(rom)) { + intent.setAction("miui.intent.action.APP_PERM_EDITOR"); + intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity"); + intent.putExtra("extra_pkgname", BuildConfig.APPLICATION_ID); + } else if ("V8".equals(rom) || "V9".equals(rom)||"V10".equals(rom) || "V11".equals(rom)|| "V12".equals(rom)) { + intent.setAction("miui.intent.action.APP_PERM_EDITOR"); + intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity"); + intent.putExtra("extra_pkgname", BuildConfig.APPLICATION_ID); + } else { + goAppDetailSetting(context); + } + context.startActivity(intent); + }catch (Exception e) { + goAppDetailSetting(context); + } + } + + private static void goHuaWeiManager(Context context) { + try { + Intent intent =new Intent(BuildConfig.APPLICATION_ID); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity"); + intent.setComponent(comp); + context.startActivity(intent); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + + private static void goOppoManager(Context context) { + try { + Intent intent =new Intent("android.settings.APPLICATION_DETAILS_SETTINGS"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + ComponentName comp = new ComponentName("com.coloros.securitypermission", "com.coloros.securitypermission.permission.PermissionAppAllPermissionActivity"); + intent.setComponent(comp); + context.startActivity(intent); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + + private static void goMeizuManager(Context context) { + try { + Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC"); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.putExtra("packageName", BuildConfig.APPLICATION_ID); + context.startActivity(intent); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + private static void goSamsungManager(Context context) { + goAppDetailSetting(context); + } + + private static void goSonyManager(Context context) { + try { + Intent intent =new Intent(BuildConfig.APPLICATION_ID); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + ComponentName comp = new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity"); + intent.setComponent(comp); + context.startActivity(intent); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + + private static void goLGManager(Context context) { + try { + Intent intent = new Intent("android.intent.action.MAIN"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("packageName", BuildConfig.APPLICATION_ID); + ComponentName comp =new ComponentName("com.android.settings", "com.android.settings.Settings.AccessLockSummaryActivity"); + intent.setComponent(comp); + context.startActivity(intent); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + + private static void goLetvManager(Context context) { + try { + Intent intent =new Intent(); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("packageName", BuildConfig.APPLICATION_ID); + ComponentName comp =new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps"); + intent.setComponent(comp); + context.startActivity(intent); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + + private static void go360Manager(Context context) { + try { + Intent intent = new Intent("android.intent.action.MAIN"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("packageName", BuildConfig.APPLICATION_ID); + ComponentName comp =new ComponentName("com.android.settings", "com.android.settings.Settings.AccessLockSummaryActivity"); + intent.setComponent(comp); + context.startActivity(intent); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + + private static void goVivoManager(Context context) { + try { + /* Intent intent = new Intent(); + intent.setClassName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.SoftPermissionDetailActivity"); + intent.setAction("secure.intent.action.softPermissionDetail"); + intent.putExtra("packageName","BuildConfig.APPLICATION_ID"); + context.startActivity(intent);*/ + goAppDetailSetting(context); + } catch (Exception e) { + goAppDetailSetting(context); + } + } + + public static void goAppDetailSetting(Context context) { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if(Build.VERSION.SDK_INT >= 9){ + intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); + intent.setData(Uri.fromParts("package", context.getPackageName(), null)); + } else if(Build.VERSION.SDK_INT <= 8){ + intent.setAction(Intent.ACTION_VIEW); + intent.setClassName("com.android.settings","com.android.settings.InstalledAppDetails"); + intent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName()); + } + try{ + context.startActivity(intent); + }catch (Exception e) { + MaleToast.showMessage(context,"页面调转失败"); + } + } + public static void goLocationSetting(Context context) { + Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); + context.startActivity(intent); + } + + public static String checkMIUI() { + String versionCode = ""; + String manufacturer = Build.MANUFACTURER; + String model = Build.MODEL; + Log.i("PermissionUtil","Build.MANUFACTURER = " + manufacturer + " ,Build.MODEL = " + Build.MODEL); + if (!TextUtils.isEmpty(manufacturer) && manufacturer.equals("Xiaomi")) { + versionCode = getSystemProperty("ro.miui.ui.version.name"); + } + return versionCode; + } + + public static String getSystemProperty(String propName) { + String line; + BufferedReader input = null; + try { + Process p = Runtime.getRuntime().exec("getprop " + propName); + input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024); + line = input.readLine(); + input.close(); + } catch (IOException ex) { + Log.i("PermissionUtil","Unable to read sysprop " + propName, ex); + return null; + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + Log.i("PermissionUtil","Exception while closing InputStream", e); + } + } + } + return line; + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/PhoneCodeView.java b/app/src/main/java/com/fengliyan/tianlesue/utils/PhoneCodeView.java new file mode 100644 index 0000000..f560801 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/PhoneCodeView.java @@ -0,0 +1,327 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; + +import java.util.ArrayList; +import java.util.List; + + +/** + * 类:PhoneCode + * 日期:2018/3/14. + */ +public class PhoneCodeView extends RelativeLayout { + private final Context context; + private View view; + private TextView tv_code1; + private TextView tv_code2; + private TextView tv_code3; + private TextView tv_code4; + private TextView tv_code5; + private TextView tv_code6; + private View v1; + private View v2; + private View v3; + private View v4; + private View v5; + private View v6; + private EditText et_code; + private final List codes = new ArrayList<>(); + private InputMethodManager imm; + + public PhoneCodeView(Context context) { + super(context); + this.context = context; + loadView(); + } + + public PhoneCodeView(Context context, AttributeSet attrs) { + super(context, attrs); + this.context = context; + loadView(); + } + + private void loadView() { + imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + View view = LayoutInflater.from(context).inflate(R.layout.phone_code_view, this); + initView(view); + initEvent(); + showSoftInput(); + } + + private void initView(View view) { + tv_code1 = view.findViewById(R.id.tv_code1); + tv_code2 = view.findViewById(R.id.tv_code2); + tv_code3 = view.findViewById(R.id.tv_code3); + tv_code4 = view.findViewById(R.id.tv_code4); + tv_code5 = view.findViewById(R.id.tv_code5); + tv_code6 = view.findViewById(R.id.tv_code6); + et_code = view.findViewById(R.id.et_code); + v1 = view.findViewById(R.id.v1); + v2 = view.findViewById(R.id.v2); + v3 = view.findViewById(R.id.v3); + v4 = view.findViewById(R.id.v4); + v5 = view.findViewById(R.id.v5); + v6 = view.findViewById(R.id.v6); + } + + private void initEvent() { + et_code.requestFocus(); + et_code.setFocusable(true); + et_code.setFocusableInTouchMode(true); + //验证码输入 + et_code.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + if (editable != null && editable.length() > 0) { + et_code.setText(""); + if (codes.size() < 6) { + codes.add(editable.toString()); + showCode(); + } + if (codes.size() == 6 && !isFristRequest && mSetRequestListener != null) { + mSetRequestListener.setRequest(); + isFristRequest = true; + } + } + } + }); + // 监听验证码删除按键 + et_code.setOnKeyListener(new OnKeyListener() { + @Override + public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { + if (keyCode == KeyEvent.KEYCODE_DEL && keyEvent.getAction() == KeyEvent.ACTION_DOWN && codes.size() > 0) { + codes.remove(codes.size() - 1); + showCode(); + isFristRequest = false; + return true; + } + return false; + } + }); + } + + /** + * 显示输入的验证码 + */ + private void showCode() { + String code1 = ""; + String code2 = ""; + String code3 = ""; + String code4 = ""; + String code5 = ""; + String code6 = ""; + if (view != null) { + view.setEnabled(codes.size() >= 6); + } + if (codes.size() >= 1) { + code1 = codes.get(0); + } + if (codes.size() >= 2) { + code2 = codes.get(1); + } + if (codes.size() >= 3) { + code3 = codes.get(2); + } + if (codes.size() >= 4) { + code4 = codes.get(3); + } + if (codes.size() >= 5) { + code5 = codes.get(4); + } + if (codes.size() >= 6) { + code6 = codes.get(5); + } + tv_code1.setText(code1); + tv_code2.setText(code2); + tv_code3.setText(code3); + tv_code4.setText(code4); + tv_code5.setText(code5); + tv_code6.setText(code6); + setColor(); + } + + /** + * 设置高亮颜色 + */ + private void setColor() { + if (codes.size() == 0) { + tv_code1.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code2.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code3.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code4.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code5.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code6.setBackgroundResource(R.drawable.bg_password_kuang); + v1.setVisibility(VISIBLE); + v2.setVisibility(GONE); + v3.setVisibility(GONE); + v4.setVisibility(GONE); + v5.setVisibility(GONE); + v6.setVisibility(GONE); + } + if (codes.size() == 1) { + tv_code1.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code2.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code3.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code4.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code5.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code6.setBackgroundResource(R.drawable.bg_password_kuang); + v1.setVisibility(GONE); + v2.setVisibility(VISIBLE); + v3.setVisibility(GONE); + v4.setVisibility(GONE); + v5.setVisibility(GONE); + v6.setVisibility(GONE); + } + if (codes.size() == 2) { + tv_code1.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code2.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code3.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code4.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code5.setBackgroundResource(R.drawable.bg_password_kuang); + tv_code6.setBackgroundResource(R.drawable.bg_password_kuang); + v1.setVisibility(GONE); + v2.setVisibility(GONE); + v3.setVisibility(VISIBLE); + v4.setVisibility(GONE); + v5.setVisibility(GONE); + v6.setVisibility(GONE); + } + if (codes.size() == 3) { + tv_code1.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code2.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code3.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code4.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code5.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code6.setBackgroundResource(R.drawable.bg_password_kuang); + v1.setVisibility(GONE); + v2.setVisibility(GONE); + v3.setVisibility(GONE); + v4.setVisibility(VISIBLE); + v5.setVisibility(GONE); + v6.setVisibility(GONE); + } + if (codes.size() == 4) { + tv_code1.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code2.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code3.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code4.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code5.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code6.setBackgroundResource(R.drawable.bg_password_kuang); + v1.setVisibility(GONE); + v2.setVisibility(GONE); + v3.setVisibility(GONE); + v4.setVisibility(GONE); + v5.setVisibility(VISIBLE); + v6.setVisibility(GONE); + } + if (codes.size() == 5) { + tv_code1.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code2.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code3.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code4.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code5.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code6.setBackgroundResource(R.drawable.bg_password_kuang1); + v1.setVisibility(GONE); + v2.setVisibility(GONE); + v3.setVisibility(GONE); + v4.setVisibility(GONE); + v5.setVisibility(GONE); + v6.setVisibility(VISIBLE); + } + if (codes.size() > 5) { + tv_code1.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code2.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code3.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code4.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code5.setBackgroundResource(R.drawable.bg_password_kuang1); + tv_code6.setBackgroundResource(R.drawable.bg_password_kuang1); + v1.setVisibility(GONE); + v2.setVisibility(GONE); + v3.setVisibility(GONE); + v4.setVisibility(GONE); + v5.setVisibility(GONE); + v6.setVisibility(GONE); + } + if (mSetSubmitListener != null) { + mSetSubmitListener.setSubmitVisibility(codes.size() > 5); + } + } + + /** + * 显示键盘 + */ + public void showSoftInput() { + //显示软键盘 + if (imm != null && et_code != null) { + et_code.postDelayed(new Runnable() { + @Override + public void run() { + imm.showSoftInput(et_code, 0); + } + }, 200); + } + } + + /** + * 获得手机号验证码 + * + * @return 验证码 + */ + public String getPhoneCode() { + StringBuilder sb = new StringBuilder(); + for (String code : codes) { + sb.append(code); + } + return sb.toString(); + } + + + public void setVCode(String code) { + et_code.setText(code); + } + + public void setView(View view) { + this.view = view; + } + + public interface SetSubmitListener { + void setSubmitVisibility(boolean b); + } + + public void setSetSubmitListener(SetSubmitListener mSetSubmitListener) { + this.mSetSubmitListener = mSetSubmitListener; + } + + private SetSubmitListener mSetSubmitListener; + private SetRequestListener mSetRequestListener; + private boolean isFristRequest; + + public interface SetRequestListener { + void setRequest(); + } + + public void setSetRequestListener(SetRequestListener setRequestListener) { + mSetRequestListener = setRequestListener; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/ProgressView.java b/app/src/main/java/com/fengliyan/tianlesue/utils/ProgressView.java new file mode 100644 index 0000000..9a459f2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/ProgressView.java @@ -0,0 +1,167 @@ +package com.fengliyan.tianlesue.utils; + +import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.Nullable; + +public class ProgressView extends View { + float progress = 0; + float radius = 0; + long duration = 1000; + int repeatCount = 0; + int color = 0xff000000; + private Paint paint; + Context context; + private ObjectAnimator animator; + + + public ProgressView(Context context) { + super(context); + this.context = context; + initView(); + } + + + public ProgressView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.context = context; + initView(); + + } + + + public ProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.context = context; + initView(); + } + + private void initView() { + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + animator = new ObjectAnimator(); + //设置动画属性 + animator.setPropertyName("progress"); + + //设置执行动画的View + animator.setTarget(this); +// animator.setRepeatCount(ValueAnimator.INFINITE); + } + + @SuppressLint({"NewApi", "DrawAllocation"}) + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + paint.setAntiAlias(true); //设置画笔为无锯齿 + paint.setColor(color); //设置画笔颜色 + paint.setStyle(Paint.Style.FILL); + paint.setStrokeWidth(1); + int[] color = new int[]{Color.parseColor("#F34EF6"), Color.parseColor("#416AF7")}; + Shader textShader = new LinearGradient(0, 0, progress, getHeight(), color, null, Shader.TileMode.CLAMP); + paint.setShader(textShader); + RectF rectF = new RectF(0, 0, progress, getHeight()); + canvas.drawRoundRect(rectF, radius, radius, paint); + } + + + /** + * set view background color + * + * @param color + */ + public void setColor(int color) { + this.color = color; + } + + + /** + * set view round radius + * + * @param radius + */ + public void setRadius(float radius) { + this.radius = radius; + } + + /** + * set anim duration + * + * @param duration + */ + public void setDuration(long duration) { + this.duration = duration; + } + + public void setRepeatCount(int repeatCount) { + this.repeatCount = repeatCount; + } + + public float getProgress() { + return progress; + } + + /** + * set progress + * + * @param progress + */ + public void setProgress(float progress) { + this.progress = progress; + invalidate(); + } + + + /** + * 返回属性动画实例,可用于动画进度监听做后续操作 + * + * @return + */ + public ObjectAnimator getAnimator() { + return animator; + } + + public long currentPlayTime() { + return animator.getCurrentPlayTime(); + } + + public void setCurrentPlayTime(long time) { + animator.setCurrentPlayTime(time); + } + + // + public void startAnim() { + if (animator != null) { + if (animator.isRunning()) { + animator.cancel(); + } + animator = null; + } + animator = new ObjectAnimator(); + //设置动画属性 + animator.setPropertyName("progress"); + //设置执行动画的View + animator.setTarget(this); + //设置进度数组, 0 - max + animator.setFloatValues(0, progress); + //设置动画时间 + animator.setDuration(duration); + animator.setRepeatCount(repeatCount); + //动画开启 + animator.start(); + } + + public void stopAnim() { + if (animator != null && animator.isRunning()) { + animator.end(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/RTCMediaUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/RTCMediaUtils.java new file mode 100644 index 0000000..a4d7832 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/RTCMediaUtils.java @@ -0,0 +1,71 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.net.Uri; + +import com.fengliyan.tianlesue.R; + +import java.io.IOException; + +public class RTCMediaUtils { + private static MediaPlayer mMediaPlayer; + private static int loopCount = 0; + + public static void playNotificationMusic(Context context, boolean isLooping) { + if (mMediaPlayer == null) { + mMediaPlayer = new MediaPlayer(); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + } + Uri uri = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.call_bg); + try { + mMediaPlayer.reset(); + mMediaPlayer.setDataSource(context, uri); + if (mMediaPlayer != null) { + mMediaPlayer.prepareAsync(); + mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mp) { + mp.start(); + } + }); + mMediaPlayer.setLooping(isLooping); + mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { + @Override + public boolean onError(MediaPlayer mp, int what, int extra) { + return false; + } + }); + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + if (!mp.isLooping()) { + loopCount++; + if (loopCount < 5) { + mp.start(); + } else { + loopCount = 0; + } + } + } + }); + } + } catch (IOException | IllegalStateException e) { + e.printStackTrace(); + } + } + + public static void stopNotificationMusic() { + try { + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + mMediaPlayer.reset(); + mMediaPlayer = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/RoundAngleImageView.java b/app/src/main/java/com/fengliyan/tianlesue/utils/RoundAngleImageView.java new file mode 100644 index 0000000..e9787c2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/RoundAngleImageView.java @@ -0,0 +1,194 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader.TileMode; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.TypedValue; + +import androidx.appcompat.widget.AppCompatImageView; + +/** + * Created by 1 on 2017/9/20. + */ + +public class RoundAngleImageView extends AppCompatImageView { + private Paint mPaint; + + private int mWidth; + + private int mHeight; + + private int mRadius;//圆半径 + + private RectF mRect;//矩形凹行大小 + + private int mRoundRadius;// 圆角大小 + + private BitmapShader mBitmapShader;//图形渲染 + + private Matrix mMatrix; + + private int mType;// 记录是圆形还是圆角矩形 + + public static final int TYPE_CIRCLE = 0;// 圆形 + public static final int TYPE_ROUND = 1;// 圆角矩形 + public static final int TYPE_OVAL = 2;//椭圆形 + public static final int DEFAUT_ROUND_RADIUS = 10;//默认圆角大小 + + public RoundAngleImageView(Context context) { + this(context, null); + } + + public RoundAngleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RoundAngleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + } + + private void initView() { + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mMatrix = new Matrix(); + mRoundRadius = DEFAUT_ROUND_RADIUS; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + // 如果是绘制圆形,则强制宽高大小一致 + if (mType == TYPE_CIRCLE) { + mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight()); + mRadius = mWidth / 2; + setMeasuredDimension(mWidth, mWidth); + } + + } + + @Override + protected void onDraw(Canvas canvas) { + + if (null == getDrawable()) { + return; + } + setBitmapShader(); + if (mType == TYPE_CIRCLE) { + canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); + } else if (mType == TYPE_ROUND) { + mPaint.setColor(Color.RED); + canvas.drawRoundRect(mRect, mRoundRadius, mRoundRadius, mPaint); + } else if (mType == TYPE_OVAL) { + canvas.drawOval(mRect, mPaint); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mRect = new RectF(0, 0, getWidth(), getHeight()); + } + + /** + * 设置BitmapShader + */ + private void setBitmapShader() { + Drawable drawable = getDrawable(); + if (null == drawable) { + return; + } + Bitmap bitmap = drawableToBitmap(drawable); + // 将bitmap作为着色器来创建一个BitmapShader + mBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP); + float scale = 1.0f; + if (mType == TYPE_CIRCLE) { + // 拿到bitmap宽或高的小值 + int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight()); + scale = mWidth * 1.0f / bSize; + + } else if (mType == TYPE_ROUND || mType == TYPE_OVAL) { + // 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值; + scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight() * 1.0f / bitmap.getHeight()); + } + // shader的变换矩阵,我们这里主要用于放大或者缩小 + mMatrix.setScale(scale, scale); + // 设置变换矩阵 + mBitmapShader.setLocalMatrix(mMatrix); + mPaint.setShader(mBitmapShader); + + } + + /** + * drawable转bitmap + * + * @param drawable + * @return + */ + private Bitmap drawableToBitmap(Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + return bitmapDrawable.getBitmap(); + } + int w = drawable.getIntrinsicWidth(); + int h = drawable.getIntrinsicHeight(); + Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, w, h); + drawable.draw(canvas); + return bitmap; + } + + /** + * 单位dp转单位px + */ + public int dpTodx(int dp) { + + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + dp, getResources().getDisplayMetrics()); + } + + public int getType() { + return mType; + } + + /** + * 设置图片类型:圆形、圆角矩形、椭圆形 + * + * @param mType + */ + public void setType(int mType) { + if (this.mType != mType) { + this.mType = mType; + invalidate(); + } + + } + + public int getRoundRadius() { + return mRoundRadius; + } + + /** + * 设置圆角大小 + * + * @param mRoundRadius + */ + public void setRoundRadius(int mRoundRadius) { + if (this.mRoundRadius != mRoundRadius) { + this.mRoundRadius = mRoundRadius; + invalidate(); + } + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/SPUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/SPUtils.java new file mode 100644 index 0000000..adb6d59 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/SPUtils.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; + +public final class SPUtils { + + private final static String name = "config"; + private final static int mode = Context.MODE_PRIVATE; + + /** + * 保存首选项 + * + * @param context + * @param key + * @param value + */ + public static void saveBoolean(Context context, String key, boolean value) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + Editor edit = sp.edit(); + edit.putBoolean(key, value); + edit.apply(); + } + + public static void saveInt(Context context, String key, int value) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + Editor edit = sp.edit(); + edit.putInt(key, value); + edit.apply(); + } + + public static void saveString(Context context, String key, String value) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + Editor edit = sp.edit(); + edit.putString(key, value); + edit.apply(); + } + + + /** + * 获取首选项 + * + * @param context + * @param key + * @param defValue + * @return + */ + public static boolean getBoolean(Context context, String key, boolean defValue) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getBoolean(key, defValue); + } + + public static int getInt(Context context, String key, int defValue) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, defValue); + } + + public static int getInt(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getInt(key, 0); + } + + public static String getString(Context context, String key, String defValue) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, defValue); + } + + public static String getString(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + return sp.getString(key, ""); + } + + /** + * 清除保存 + * + * @param context + */ + public static void clear(Context context) { + SharedPreferences sp = context.getSharedPreferences(name, mode); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + editor.apply(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/SaveImageUtil.java b/app/src/main/java/com/fengliyan/tianlesue/utils/SaveImageUtil.java new file mode 100644 index 0000000..71974de --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/SaveImageUtil.java @@ -0,0 +1,99 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.AsyncTask; +import android.provider.MediaStore; +import android.view.View; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.uikit.toast.MaleToast; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +public class SaveImageUtil { + private View group; + private Context context; + + public SaveImageUtil(View group, Context context) { + this.group = group; + this.context = context; + } + public void start(){ + new SaveImage().execute(); + } + + class SaveImage extends AsyncTask { + @Override + protected Boolean doInBackground(Boolean... params) { + boolean result = false; + Bitmap bitmap = getCacheBitmapFromView(group); + if (bitmap != null) { + result = saveImageToGallery(getCacheBitmapFromView(group)); + } + return result; + } + + @Override + protected void onPostExecute(Boolean result) { + if (result) { + MaleToast.showMessage(context, "二维码保存成功"); + } else { + MaleToast.showMessage(context, "二维码保存失败"); + } + + } + } + + /** + * 获取一个 View 的缓存视图 * (前提是这个View已经渲染完成显示在页面上) * @param view * @return + */ + public static Bitmap getCacheBitmapFromView(View view) { + final boolean drawingCacheEnabled = true; + view.setDrawingCacheEnabled(drawingCacheEnabled); + view.buildDrawingCache(drawingCacheEnabled); + final Bitmap drawingCache = view.getDrawingCache(); + Bitmap bitmap; + if (drawingCache != null) { + bitmap = Bitmap.createBitmap(drawingCache); + view.setDrawingCacheEnabled(false); + } else { + bitmap = null; + } + return bitmap; + } + + public boolean saveImageToGallery(Bitmap bmp) { // 首先保存图片 + String storePath = ConstUrl.DEFAULT_PATH + File.separator + System.currentTimeMillis() + ""; + File appDir = new File(storePath); + if (!appDir.exists()) { + appDir.mkdir(); + } + String fileName = System.currentTimeMillis() + ".jpg"; + File file = new File(appDir, fileName); + try { + FileOutputStream fos = new FileOutputStream(file); + //通过io流的方式来压缩保存图片 + boolean isSuccess = bmp.compress(Bitmap.CompressFormat.JPEG, 60, fos); + fos.flush(); + fos.close(); + //把文件插入到系统图库 + MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), fileName, null); + //保存图片后发送广播通知更新数据库 + Uri uri = Uri.fromFile(file); + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); + if (isSuccess) { + return true; + } else { + return false; + } + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/SimpleItemTouchCallBack.java b/app/src/main/java/com/fengliyan/tianlesue/utils/SimpleItemTouchCallBack.java new file mode 100644 index 0000000..0eadea1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/SimpleItemTouchCallBack.java @@ -0,0 +1,93 @@ +package com.fengliyan.tianlesue.utils; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + +public class SimpleItemTouchCallBack extends ItemTouchHelper.Callback{ + + private TouchCallBack mCallBack; + private int mAdapterPosition; + + public SimpleItemTouchCallBack(TouchCallBack mCallBack) { + this.mCallBack = mCallBack; + } + + /** + * 返回可以滑动的方向,一般使用makeMovementFlags(int,int) + * 或makeFlag(int, int)来构造我们的返回值 + * @param recyclerView + * @param viewHolder + * @return + */ + @Override + public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + + //允许上下拖拽 + int drag = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; + //设置 + return makeMovementFlags(drag,0); + } + + /** + * 上下拖动item时回调,可以调用Adapter的notifyItemMoved方法来交换两个ViewHolder的位置, + * 最后返回true, + * 表示被拖动的ViewHolder已经移动到了目的位置 + * @param recyclerView + * @param viewHolder + * @param target + * @return + */ + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { + //通知适配器,两个子条目位置发生改变 + mCallBack.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition()); + return true; + } + + /** + * 当用户左右滑动item时达到删除条件就会调用,一般为一半,条目继续滑动删除,否则弹回 + * @param viewHolder + * @param direction + */ + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + + } + + /** + * 支持长按拖动,默认是true + * @return + */ + @Override + public boolean isLongPressDragEnabled() { + return super.isLongPressDragEnabled(); + } + + /** + * 支持滑动,即可以调用到onSwiped()方法,默认是true + * @return + */ + @Override + public boolean isItemViewSwipeEnabled() { + return true; + } + + @Override + public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) { + long animationDuration = super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy); + if (mCallBack != null) { + mCallBack.animationDuration(animationDuration); + } + return animationDuration; + } + + public interface TouchCallBack { + //交换条目位置 + void onItemMove(int fromPosition, int toPosition); + //删除条目 + void onItemDelete(int position); + + void animationDuration(long time); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/SoftHideKeyBoardUtil.java b/app/src/main/java/com/fengliyan/tianlesue/utils/SoftHideKeyBoardUtil.java new file mode 100644 index 0000000..dcbdeb6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/SoftHideKeyBoardUtil.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.utils; + +import android.app.Activity; +import android.graphics.Rect; +import android.os.Build; +import android.view.View; +import android.view.ViewTreeObserver; +import android.widget.FrameLayout; + +public class SoftHideKeyBoardUtil { + public static void assistActivity (Activity activity) { + new SoftHideKeyBoardUtil(activity); + } + private View mChildOfContent; + private int usableHeightPrevious; + private FrameLayout.LayoutParams frameLayoutParams; + //为适应华为小米等手机键盘上方出现黑条或不适配 + private int contentHeight;//获取setContentView本来view的高度 + private boolean isfirst = true;//只用获取一次 + private int statusBarHeight;//状态栏高度 + private SoftHideKeyBoardUtil(Activity activity) { + statusBarHeight= StatusBarUtil.getStatusBarHeight(activity); + //1、找到Activity的最外层布局控件,它其实是一个DecorView,它所用的控件就是FrameLayout + FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); + //2、获取到setContentView放进去的View + mChildOfContent = content.getChildAt(0); + //3、给Activity的xml布局设置View树监听,当布局有变化,如键盘弹出或收起时,都会回调此监听 + mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + //4、软键盘弹起会使GlobalLayout发生变化 + public void onGlobalLayout() { + if (isfirst) { + contentHeight = mChildOfContent.getHeight();//兼容华为等机型 + isfirst = false; + } + //5、当前布局发生变化时,对Activity的xml布局进行重绘 + possiblyResizeChildOfContent(); + } + }); + //6、获取到Activity的xml布局的放置参数 + frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); + } + + // 获取界面可用高度,如果软键盘弹起后,Activity的xml布局可用高度需要减去键盘高度 + private void possiblyResizeChildOfContent() { + //1、获取当前界面可用高度,键盘弹起后,当前界面可用布局会减少键盘的高度 + int usableHeightNow = computeUsableHeight(); + //2、如果当前可用高度和原始值不一样 + if (usableHeightNow != usableHeightPrevious) { + //3、获取Activity中xml中布局在当前界面显示的高度 + int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); + //4、Activity中xml布局的高度-当前可用高度 + int heightDifference = usableHeightSansKeyboard - usableHeightNow; + //5、高度差大于屏幕1/4时,说明键盘弹出 + if (heightDifference > (usableHeightSansKeyboard/4)) { + // 6、键盘弹出了,Activity的xml布局高度应当减去键盘高度 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ + frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight; + } else { + frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; + } + } else { + frameLayoutParams.height = contentHeight; + } + //7、 重绘Activity的xml布局 + mChildOfContent.requestLayout(); + usableHeightPrevious = usableHeightNow; + } + } + private int computeUsableHeight() { + Rect r = new Rect(); + mChildOfContent.getWindowVisibleDisplayFrame(r); + // 全屏模式下:直接返回r.bottom,r.top其实是状态栏的高度 + return (r.bottom - r.top); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/SoftKeyBoardListener.java b/app/src/main/java/com/fengliyan/tianlesue/utils/SoftKeyBoardListener.java new file mode 100644 index 0000000..dd56d47 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/SoftKeyBoardListener.java @@ -0,0 +1,80 @@ +package com.fengliyan.tianlesue.utils; + +import android.app.Activity; +import android.graphics.Rect; +import android.view.View; +import android.view.ViewTreeObserver; + +/** + * Created by 张斌 on 2018/5/2 0002. + */ + +public class SoftKeyBoardListener { + private View rootView;//activity的根视图 + int rootViewVisibleHeight;//纪录根视图的显示高度 + private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener; + + public SoftKeyBoardListener(Activity activity) { + //获取activity的根视图 + rootView = activity.getWindow().getDecorView(); + + //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变 + rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + //获取当前根视图在屏幕上显示的大小 + Rect r = new Rect(); + rootView.getWindowVisibleDisplayFrame(r); + int visibleHeight = r.height(); + if (rootViewVisibleHeight == 0) { + rootViewVisibleHeight = visibleHeight; + return; + } + + //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变 + if (rootViewVisibleHeight == visibleHeight) { + return; + } + + //根视图显示高度变小超过200,可以看作软键盘显示了 + if (rootViewVisibleHeight - visibleHeight > 200) { + if (onSoftKeyBoardChangeListener != null) { +// onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight); + onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight); + } + rootViewVisibleHeight = visibleHeight; + return; + } + + //根视图显示高度变大超过200,可以看作软键盘隐藏了 + if (visibleHeight - rootViewVisibleHeight > 200) { + if (onSoftKeyBoardChangeListener != null) { +// onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight); + onSoftKeyBoardChangeListener.keyBoardHide(rootViewVisibleHeight - visibleHeight); + } + rootViewVisibleHeight = visibleHeight; + return; + } + + } + }); + } + + private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { + this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener; + } + + public interface OnSoftKeyBoardChangeListener { +// void keyBoardShow(int height); +// +// void keyBoardHide(int height); + void keyBoardShow(int height); + + void keyBoardHide(int height); + } + + public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { + SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity); + softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/StatusBarUtil.java b/app/src/main/java/com/fengliyan/tianlesue/utils/StatusBarUtil.java new file mode 100644 index 0000000..6d0d562 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/StatusBarUtil.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.utils; + +import android.app.Activity; +import android.content.Context; +import android.view.View; + +public class StatusBarUtil { + public static void setAndroidNativeLightStatusBar(Activity activity, Boolean dark) { + View decorView= activity.getWindow().getDecorView(); + if (dark) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + }else { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + } + public static int getStatusBarHeight(Context context) { + int result = 0; + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + result = context.getResources().getDimensionPixelSize(resourceId); + } + return result; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/StrU.java b/app/src/main/java/com/fengliyan/tianlesue/utils/StrU.java new file mode 100644 index 0000000..2b85b30 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/StrU.java @@ -0,0 +1,596 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.graphics.Typeface; +import androidx.core.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.AbsoluteSizeSpan; +import android.text.style.ForegroundColorSpan; +import android.text.style.StyleSpan; +import android.widget.TextView; + +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public class StrU { + /** + * @param str + * @return String + */ + public static String doEmpty(String str) { + return doEmpty(str, ""); + } + + /** + * @param str + * @param defaultValue + * @return String + */ + public static String doEmpty(String str, String defaultValue) { + if (str == null || str.equalsIgnoreCase("null") || str.trim().equals("") || str.trim().equals("")) { + str = defaultValue; + } else if (str.startsWith("null")) { + str = str.substring(4, str.length()); + } + return str.trim(); + } + + /** + * + */ + private final static String PLEASE_SELECT = ""; + + public static boolean notEmpty(Object o) { + return o != null && !"".equals(o.toString().trim()) && !"null".equalsIgnoreCase(o.toString().trim()) && !"undefined".equalsIgnoreCase(o.toString().trim()) + && !PLEASE_SELECT.equals(o.toString().trim()); + } + + public static boolean empty(Object o) { + return o == null || "".equals(o.toString().trim()) || "null".equalsIgnoreCase(o.toString().trim()) || "undefined".equalsIgnoreCase(o.toString().trim()) + || PLEASE_SELECT.equals(o.toString().trim()); + } + + public static boolean num(Object o) { + int n = 0; + try { + n = Integer.parseInt(o.toString().trim()); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + if (n > 0) { + return true; + } else { + return false; + } + } + + public static boolean decimal(Object o) { + double n = 0; + try { + n = Double.parseDouble(o.toString().trim()); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + if (n > 0.0) { + return true; + } else { + return false; + } + } + + /** + * @param Jid + * @return + */ + public static String getUserNameByJid(String Jid) { + if (empty(Jid)) { + return null; + } + if (!Jid.contains("@")) { + return Jid; + } + return Jid.split("@")[0]; + } + + /** + * @param jidFor + * @param userName + * @return + */ + public static String getJidByName(String userName, String jidFor) { + if (empty(jidFor) || empty(jidFor)) { + return null; + } + return userName + "@" + jidFor; + } + + /** + * @param userName + * @return + */ + public static String getJidByName(String userName) { + String jidFor = "ahic.com.cn"; + return getJidByName(userName, jidFor); + } + + /** + * 判断是不是有汉字 + * + * @param name + * @return + */ + public static boolean checkNameChese(String name) { + boolean res = true; + char[] cTemp = name.toCharArray(); + for (int i = 0; i < name.length(); i++) { + if (!isChinese(cTemp[i])) { + res = false; + break; + } + } + return res; + } + + /** + * @param c + * @return + */ + public static boolean isChinese(char c) { + Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); + if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A + || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { + return true; + } + return false; + } + + /** + * 判断字符串是否为空 + * + * @param str + * @return + */ + public static boolean isEmpty(String str) { + if ("".equals(str) || null == str || "null".equals(str) || str.length() == 0) { + return true; + } + return false; + } + + /** + * 判断时间六个月内 + * + * @return + */ + public static boolean isDate(int staYear, int endYear, int staMonth, int endMonth) { + int sub = endMonth - staMonth; + if (staYear == endYear && sub > -1 && 6 > sub) { + return true; + } else { + if (sub < -6) { + return true; + } + return false; + } + } + + /** + * 判断是否是身份证号 + * + * @param str + * @return + */ + public static boolean isIdCard(String str) { + String regExpress = "([0-9]{17}([0-9]|X))|([0-9]{15})"; + Pattern pattern = Pattern.compile(regExpress); + boolean result = pattern.matcher(str).matches(); + return result; + } + + /** + * unicode转String + */ + public static String UnicodeToString(String str) { + Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))"); + Matcher matcher = pattern.matcher(str); + char ch; + while (matcher.find()) { + ch = (char) Integer.parseInt(matcher.group(2), 16); + str = str.replace(matcher.group(1), ch + ""); + } + return str; + } + + /** + * 从字符串中取数字 + * + * @param content + * @return + */ + public static String getNumbers(String content) { + Pattern pattern = Pattern.compile("\\d+"); + Matcher matcher = pattern.matcher(content); + while (matcher.find()) { + return matcher.group(0); + } + return ""; + } + + /** + * 描述:获取字符串的长度. + * + * @param str 指定的字符串 + * @return 字符串的长度(中文字符计2个) + */ + public static int strLength(String str) { + int valueLength = 0; + String chinese = "[\u0391-\uFFE5]"; + if (!isEmpty(str)) { + for (int i = 0; i < str.length(); i++) { + String temp = str.substring(i, i + 1); + if (temp.matches(chinese)) { + valueLength += 2; + } else { + valueLength += 1; + } + } + } + return valueLength; + } + + /** + * 判断字符串首字母是否为英文 + * + * @param s + * @return + */ + public static boolean isEnglish(String s) { + if (!(s.charAt(0) >= 'A' && s.charAt(0) <= 'Z') && !(s.charAt(0) >= 'a' && s.charAt(0) <= 'z')) { + return false; + } + return true; + } + + /** + * 10 * 中国移动:China Mobile 11 * + * 134[0-8],135,136,137,138,139,147,150,151,152,157 + * ,158,159,178,182,183,184,187,188 12 + */ + public static final String CM = "^1(34[0-8]|(3[5-9]|47|5[017-9]|78|8[23478])\\d)\\d{7}$"; + + /** + * 15 * 中国联通:China Unicom 16 * 130,131,132,145,152,155,156,176,185,186 17 + */ + public static final String CU = "^1(3[0-2]|45|5[256]|76|8[56])\\d{8}$"; + + /** + * 20 * 中国电信:China Telecom 21 * 133,1349,153,177,180,181,189 22 + */ + public static final String CT = "^1((33|53|77|8[019])[0-9]|349)\\d{7}$"; + + /** + * 29 * 虚拟运营商 30 * 170 31 + */ + public static final String VT = "^1(|70)\\d{8}$"; + + /** + * 验证手机号码 + */ + public static boolean isMobileNO(String mobilePhone) { + String str = "^1[3|4|5|6|7|8|9]\\d{9}$"; + Pattern p = Pattern.compile(str); + Matcher m = p.matcher(mobilePhone); + return m.matches(); + } + + /** + * 判断邮箱 + * + * @param email + * @return + */ + public static boolean isEmail(String email) { + String str = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$"; + Pattern p = Pattern.compile(str); + Matcher m = p.matcher(email); + return m.matches(); + } + + /** + * 判断车牌号 + * + * @return + */ + public static boolean isPlatenumber(String platenumber) { + String str = "[a-zA-Z]{1}[0-9a-zA-Z]{5,6}$"; + Pattern p = Pattern.compile(str); + Matcher m = p.matcher(platenumber); + return m.matches(); + } + + /** + * 用户名判断 + * + * @param str + * @return + */ + public static boolean isRight(String str) { + String sp = "/^1[34578][0-9]{9}$/"; + Pattern p = Pattern.compile(sp); + Matcher m = p.matcher(str); + if (m.find()) { + return true; + } + return false; + } + + /** + * 判断两个字符串是否相同 + * + * @param str + * @param oStr + * @return + */ + public static boolean equals(String str, String oStr) { + if (str != null && oStr != null) { + if (str.equals(oStr)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + /** + * 判断是否是网址 + * + * @return + */ + public static boolean isHttp(String url) { + String regex0 = "((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,3})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|([a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,3})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)"; + Pattern p = Pattern.compile(regex0); + Matcher m = p.matcher(url); + if (m.find()) { + return true; + } + return false; + } + + /** + * 判断是不是数字 + * + * @param str + * @return + */ + public static boolean isNumeric(String str) { + Pattern pattern = Pattern.compile("[0-9]*"); + return pattern.matcher(str).matches(); + } + + public static byte[] intToByteArray(int value) { + byte[] b = new byte[4]; + for (int i = 0; i < 4; i++) { + int offset = (b.length - 1 - i) * 8; + b[i] = (byte) (value >>> offset & 0xFF); + } + return b; + } + + public static byte[] byteMerger(byte[] byte_1, byte[] byte_2) { + byte[] byte_3 = new byte[byte_1.length + byte_2.length]; + System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length); + System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length); + return byte_3; + } + + public static int byteArrayToInt(byte[] b) throws Exception { + if (b.length > 4) { + throw new Exception("byte array to int ,byte array length must <=4 "); + } + return (int) byteArrayToLong(b); + } + + public static long byteArrayToLong(byte[] b) throws Exception { + if (b.length > 8) { + throw new Exception("byte array to long ,byte array length must <=8 "); + } + long value = 0L; + for (int i = 0; i < b.length; i++) { + value += ((b[i] & 0xFF) << ((b.length - i - 1) * 8)); + } + return value; + } + + public static String byteToHexString(byte[] data) { + StringBuffer sb = new StringBuffer(); + if (data != null) { + sb.append("\n["); + for (int i = 0; i < data.length; i++) { + int value = data[i] & 0xFF; + String str = Integer.toHexString(value); + if (str.length() == 1) { + sb.append("0"); + } + sb.append(str.toUpperCase()).append(" ,"); + if ((i > 0) && (i % 16 == 0)) { + sb.append('\n'); + } + } + if (sb.indexOf(",") > 0) { + sb.setLength(sb.length() - 1); + } + sb.append("]"); + } + return sb.toString(); + } + + /** + * 分割String转List + * + * @param listText + * @return + */ + public static List StringToList(String listText) { + String SEP1 = ","; + if (!StrU.isEmpty(listText)) { + List list = new ArrayList(); + String[] text = listText.split(SEP1); + for (String str : text) { + list.add(str); + } + return list; + } + return null; + } + + /** + * List转逗号分隔string + * + * @param list + * @return + */ + public static String listToString(List list, String separator) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + if (i == list.size() - 1) { + sb.append(list.get(i)); + } else { + sb.append(list.get(i)); + sb.append(separator); + } + } + return sb.toString(); + } + + /** + * 设置Span字体大小 + */ + public static void setSpanTextSize(String text, int start, int end, TextView tv, int textS) { + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new AbsoluteSizeSpan(textS, true), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + tv.setText(spannableString); + } + + /** + * 设置Span字体大小粗细 + */ + public static void setSpanTextSizeStyle(String text, int start, int end, TextView tv, int textS) { + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new AbsoluteSizeSpan(textS, true), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableString.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //粗体 + tv.setText(spannableString); + } + + /** + * 设置Span字体颜色 + */ + public static void setSpanTextColor(String text, int start, int end, TextView tv, int color, Context context) { + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, color)), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + tv.setText(spannableString); + } + + /** + * 设置Span字体颜色大小 + * + * @param text 文本 + * @param start 开始位置 + * @param end 结束位置 + * @param tv textview + * @param color 颜色 + * @param dp 字体大小 + * @param context c + */ + public static void setSpanTextColorSize(String text, int start, int end, TextView tv, int color, int dp, Context context) { + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new AbsoluteSizeSpan(dp, true), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, color)), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + tv.setText(spannableString); + } + + /** + * 设置Span字体颜色大小粗细 + * + * @param text 文本 + * @param start 开始位置 + * @param end 结束位置 + * @param tv textview + * @param color 颜色 + * @param dp 字体大小 + * @param isBold 是否加粗 + * @param context c + */ + public static void setSpanTextColorSizeBold(String text, int start, int end, TextView tv, int color, int dp, boolean isBold, Context context) { + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new AbsoluteSizeSpan(dp, true), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, color)), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + if (isBold) { + spannableString.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //粗体 + } else { + spannableString.setSpan(new StyleSpan(Typeface.NORMAL), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + tv.setText(spannableString); + } + + // 两次点击按钮之间的点击间隔不能少于1000毫秒 + private static final int MIN_CLICK_DELAY_TIME = 1000; + private static long lastClickTime; + + /** + * 防止重复点击 + * + * @return + */ + public static boolean isFastClick() { + boolean flag = false; + long curClickTime = System.currentTimeMillis(); + if ((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) { + flag = true; + } + lastClickTime = curClickTime; + return flag; + } + + public static int StringToInt(String number, int defaultNum) { + try { + if (!StrU.isEmpty(number)) { + return Integer.parseInt(number.trim()); + } else { + return defaultNum; + } + } catch (NumberFormatException ignore) { + return defaultNum; + } + } + + /** + * @param str 需要分割的字符串 + * @param key 分割的值 + * @param index 分割后返回值下标 + * @return 指定文本分割字符串 + */ + public static String StringSplit(String str, String key, int index) { + if (!StrU.isEmpty(str)) { + String[] array = str.split(key); + return array[index]; + } else { + return ""; + } + } + + //获取图片地址 + public static String getResourcePath(String path, Context context) { + return ConstUrl.IMAGE_URL + path + (!isEmpty(NoClearSPUtils.getString(context, ConsUser.RESOURCE_VERSION)) ? + NoClearSPUtils.getString(context, ConsUser.RESOURCE_VERSION) : ""); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/TimeZoneUtils.java b/app/src/main/java/com/fengliyan/tianlesue/utils/TimeZoneUtils.java new file mode 100644 index 0000000..079891b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/TimeZoneUtils.java @@ -0,0 +1,30 @@ +package com.fengliyan.tianlesue.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.TimeZone; + +/** + * Created by zhangbin on 2019/1/21. + */ + +public class TimeZoneUtils { + + public static long getTime() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); //指定时区 + String format = sdf.format(Calendar.getInstance().getTime()); +// DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + java.util.Date date = null; + try { + date = sdf.parse(format); + } catch (ParseException e) { + e.printStackTrace(); + } + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + long timestamp = cal.getTimeInMillis(); + return timestamp; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/WaveView.java b/app/src/main/java/com/fengliyan/tianlesue/utils/WaveView.java new file mode 100644 index 0000000..6dcf75a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/WaveView.java @@ -0,0 +1,307 @@ +package com.fengliyan.tianlesue.utils; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * 水波纹扩散效果 + * https://github.com/hackware1993/WaveView + */ +public class WaveView extends View { + + private float mInitialRadius; // 初始波纹半径 + private float mMaxRadius; // 最大波纹半径 + private long mDuration = 3000; // 一个波纹从创建到消失的持续时间 + private int mSpeed = 1000; // 波纹的创建速度,每500ms创建一个 + private float mMaxRadiusRate = 1f;//0.85f; + private boolean mMaxRadiusSet; + + private boolean mIsRunning; + private long mLastCreateTime; + private List mCircleList = new ArrayList(); + + private Runnable mCreateCircle = new Runnable() { + @Override + public void run() { + if (mIsRunning) { + newCircle(); + postDelayed(mCreateCircle, mSpeed); + } + } + }; + + private Interpolator mInterpolator = new LinearInterpolator(); + + private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + public WaveView(Context context) { + super(context); + } + + public WaveView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setStyle(Paint.Style style) { + mPaint.setStyle(style); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + if (!mMaxRadiusSet) { + mMaxRadius = Math.min(w, h) * mMaxRadiusRate / 2.0f; + } + } + + public void setMaxRadiusRate(float maxRadiusRate) { + mMaxRadiusRate = maxRadiusRate; + } + + public void setColor(int color) { + mPaint.setColor(color); + } + + /** + * 开始 + */ + public void start() { + if (!mIsRunning) { + mIsRunning = true; + mCreateCircle.run(); + } + } + + /** + * 缓慢停止 + */ + public void stop() { + mIsRunning = false; + } + + /** + * 立即停止 + */ + public void stopImmediately() { + mIsRunning = false; + mCircleList.clear(); + invalidate(); + } + + protected void onDraw(Canvas canvas) { + Iterator iterator = mCircleList.iterator(); + while (iterator.hasNext()) { + Circle circle = iterator.next(); + float radius = circle.getCurrentRadius(); + if (System.currentTimeMillis() - circle.mCreateTime < mDuration) { + mPaint.setAlpha(circle.getAlpha()); + canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mPaint); + } else { + iterator.remove(); + } + } + if (mCircleList.size() > 0) { + postInvalidateDelayed(10); + } + } + + public void setInitialRadius(float radius) { + mInitialRadius = radius; + } + + public void setDuration(long duration) { + mDuration = duration; + } + + public void setMaxRadius(float maxRadius) { + mMaxRadius = maxRadius; + mMaxRadiusSet = true; + } + + public void setSpeed(int speed) { + mSpeed = speed; + } + + private void newCircle() { + long currentTime = System.currentTimeMillis(); + if (currentTime - mLastCreateTime < mSpeed) { + return; + } + Circle circle = new Circle(); + mCircleList.add(circle); + invalidate(); + mLastCreateTime = currentTime; + } + + private class Circle { + private long mCreateTime; + + Circle() { + mCreateTime = System.currentTimeMillis(); + } + + int getAlpha() { + float percent = (getCurrentRadius() - mInitialRadius) / (mMaxRadius - mInitialRadius); + return (int) ((55 - mInterpolator.getInterpolation(percent) * 46)); + //Log.i("透明度",""+mInterpolator.getInterpolation(percent)); + //return (int) ((255*0.08)*mInterpolator.getInterpolation(percent)); + } + + float getCurrentRadius() { + float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mDuration; + return mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius); + } + } + + public void setInterpolator(Interpolator interpolator) { + mInterpolator = interpolator; + if (mInterpolator == null) { + mInterpolator = new LinearInterpolator(); + } + } + + /*private Context mContext; + private int centerRadius; + private int maxRadius; + private int waveWidth; + private long waveIntervalTime = 500; + private long waveDuration = 1500; + private boolean running = false; + private List waveList = new ArrayList<>(); + private Paint paint = new Paint(); + private int centerColor; + + public WaveView(Context context) { + this(context,null); + } + + public WaveView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs,0); + } + + public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaveView,defStyleAttr,0); + centerColor = typedArray.getColor( + R.styleable.WaveView_center_color, + ContextCompat.getColor(context, R.color.mainTextColor) + ); + centerRadius = (int) typedArray.getDimension(R.styleable.WaveView_center_radius, 4); + maxRadius = (int) typedArray.getDimension(R.styleable.WaveView_max_radius, 14f); + waveWidth = (int) typedArray.getDimension(R.styleable.WaveView_wave_width, 1.0f); + waveIntervalTime = typedArray.getInt(R.styleable.WaveView_wave_interval_time, 500); + waveDuration = typedArray.getInt(R.styleable.WaveView_wave_duration, 1500); + paint.setColor(centerColor); + typedArray.recycle(); + } + + public void setWaveStart(boolean waveStart) { + if (waveStart) { + if (!running) { + running = true; + waveList.add(new Wave()); + } + } else { + running = false; + for (Wave wave: waveList) { + wave.cancelAnimation(); + } + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + int radius = (Math.min(w,h)/2); + if (radius < maxRadius) { + maxRadius = radius; + } + + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + for (Wave wave: waveList) { + paint.setAlpha(wave.getAlpha()); + paint.setStrokeWidth(waveWidth); + paint.setStyle(Paint.Style.STROKE); + canvas.drawCircle(getWidth() >> 1, (getHeight() >> 1), wave.getCurrentRadius(), paint); + } + if (waveList.size() > 0) { + paint.setAlpha(255); + paint.setStyle(Paint.Style.FILL); + canvas.drawCircle(getWidth() >> 1, getHeight() >> 1, centerRadius, paint); + } + } + + public class Wave { + private boolean hasCreateNewWave = false; + private ValueAnimator createWaveAnimation = ObjectAnimator.ofFloat(this, "percent", 0f, 1.0f); + private Float percent =0f; + + @SuppressLint("ObjectAnimatorBinding") + public void setPercent(Float percent) { + + this.percent = percent; + if (running && percent >= waveIntervalTime / waveDuration && !hasCreateNewWave) { + Wave wave = new Wave(); + wave.createWaveAnimation.setInterpolator(new LinearInterpolator()); + wave.createWaveAnimation.setDuration(waveDuration); + wave.createWaveAnimation.start(); + wave.createWaveAnimation.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + if (running) { + waveList.remove(Wave.this); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + waveList.add(wave); + hasCreateNewWave = true; + } + invalidate(); + } + + public Float getPercent() { + return percent; + } + + public void cancelAnimation() { + createWaveAnimation.cancel(); + } + + public int getAlpha() { + return (int) (255 * (1 - percent)); + } + + public float getCurrentRadius() { + return centerRadius + percent * (maxRadius - centerRadius); + } + }*/ + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/BitmapUtils.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/BitmapUtils.kt new file mode 100644 index 0000000..3c0cb2d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/BitmapUtils.kt @@ -0,0 +1,254 @@ +package com.fengliyan.tianlesue.utils.camera2 + +import android.annotation.SuppressLint +import android.content.ContentValues +import android.content.Context +import android.content.res.Resources +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Matrix +import android.media.ExifInterface +import android.provider.MediaStore +import android.util.Base64 +import java.io.ByteArrayOutputStream +import java.io.FileOutputStream +import java.text.SimpleDateFormat +import java.util.* +import kotlin.concurrent.thread + +/** + * + * author : ChenSen + * data : 2018/3/16 + * desc: + */ +object BitmapUtils { + @JvmStatic + fun Bitmap2StrByBase64(bit: Bitmap): String? { + val bos = ByteArrayOutputStream() + var start: Int + var end: Int + var options = 50 + bit.compress(Bitmap.CompressFormat.JPEG, 100, bos) //参数100表示不压缩 + while (bos.toByteArray().size / 1024 > 30) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 + //循环判断如果压缩后图片是否大于100kb,大于继续压缩 + start = bos.toByteArray().size / 1024 + bos.reset() //重置baos即清空baos + bit.compress(Bitmap.CompressFormat.JPEG, options, bos) //这里压缩options%,把压缩后的数据存放到baos中 + if (options > 5) { + options -= 5 //每次都减少10 + } + end = bos.toByteArray().size / 1024 + if (start == end) { + break + } + } + return Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT) + } + + @JvmStatic + fun toByteArray(bitmap: Bitmap): ByteArray { + val os = ByteArrayOutputStream() + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os) + return os.toByteArray() + } + + @JvmStatic + fun mirror(rawBitmap: Bitmap): Bitmap { + val matrix = Matrix() + matrix.postScale(-1f, 1f) + return Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmap.width, rawBitmap.height, matrix, true) + } + + @JvmStatic + fun rotate(rawBitmap: Bitmap, degree: Float): Bitmap { + val matrix = Matrix() + matrix.postRotate(degree) + return Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmap.width, rawBitmap.height, matrix, true) + } + + @JvmStatic + fun decodeBitmap(bitmap: Bitmap, reqWidth: Int, reqHeight: Int): Bitmap { + val options = BitmapFactory.Options() + options.inJustDecodeBounds = true + + val bos = ByteArrayOutputStream() + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos) + BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.size(), options) + + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight) + options.inJustDecodeBounds = false + return BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.size(), options) + } + + @JvmStatic + fun decodeBitmapFromFile(path: String, reqWidth: Int, reqHeight: Int): Bitmap { + val options = BitmapFactory.Options() + options.inJustDecodeBounds = true + BitmapFactory.decodeFile(path, options) + + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight) + options.inJustDecodeBounds = false + return BitmapFactory.decodeFile(path, options) + } + + @JvmStatic + fun decodeBitmapFromResource( + res: Resources, + resId: Int, + reqWidth: Int, + reqHeight: Int + ): Bitmap { + val options = BitmapFactory.Options() + options.inJustDecodeBounds = true + BitmapFactory.decodeResource(res, resId, options) + + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight) + options.inJustDecodeBounds = false + return BitmapFactory.decodeResource(res, resId, options) + } + + @JvmStatic + private fun calculateInSampleSize( + options: BitmapFactory.Options, + reqWidth: Int, + reqHeight: Int + ): Int { + val rawWidth = options.outWidth + val rawHeight = options.outHeight + var inSampleSize = 1 + + if (rawWidth > reqWidth || rawHeight > reqHeight) { + val halfWidth = rawWidth / 2 + val halfHeight = rawHeight / 2 + + while ((halfWidth / inSampleSize) > reqWidth && (halfHeight / inSampleSize) > reqHeight) { + inSampleSize *= 2 //设置inSampleSize为2的幂是因为解码器最终还是会对非2的幂的数进行向下处理,获取到最靠近2的幂的数 + } + } + return inSampleSize + } + + @JvmStatic + fun savePicNoRotate( + data: ByteArray?, + folderName: String = "camera1", + onSuccess: (savedPath: String, time: String) -> Unit, + onFailed: (msg: String) -> Unit + ) { + thread { + try { + val temp = System.currentTimeMillis() + val picFile = FileUtil.createCameraFile(folderName) + if (picFile != null && data != null) { + + val rawBitmap = BitmapFactory.decodeByteArray(data, 0, data.size) +// val resultBitmap = if (isMirror) mirror(rawBitmap) else rawBitmap + val outputStream = FileOutputStream(picFile) + outputStream.write(toByteArray(rawBitmap)) + outputStream.close() + onSuccess(picFile.absolutePath, "${System.currentTimeMillis() - temp}") + + } + } catch (e: Exception) { + e.printStackTrace() + onFailed("${e.message}") + } + } + } + + fun getBitmapDegree(path: String): Int { + var degree = 0; + // 从指定路径下读取图片,并获取其EXIF信息 + var exifInterface = ExifInterface(path); + // 获取图片的旋转信息 + var orientation = exifInterface.getAttributeInt( + ExifInterface.TAG_ORIENTATION, + ExifInterface.ORIENTATION_NORMAL + ); + when (orientation) { + ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90 + ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180 + ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270 + } + return degree; + } + + @JvmStatic + fun savePic( + data: ByteArray?, + folderName: String = "camera1", + degree: Float, + onSuccess: (savedPath: String, time: String) -> Unit, + onFailed: (msg: String) -> Unit + ) { + thread { + try { + val temp = System.currentTimeMillis() + val picFile = FileUtil.createCameraFile(folderName) + if (picFile != null && data != null) { + val rawBitmap = BitmapFactory.decodeByteArray(data, 0, data.size) + val resultBitmap1 = mirror(rawBitmap) + val resultBitmap = rotate(resultBitmap1, degree) + val outputStream = FileOutputStream(picFile) + outputStream.write(toByteArray(resultBitmap)) + outputStream.close() +// var degree = getBitmapDegree(picFile.absolutePath) + onSuccess(picFile.absolutePath, "${System.currentTimeMillis() - temp}") + + } + } catch (e: Exception) { + e.printStackTrace() + onFailed("${e.message}") + } + } + } + + + @SuppressLint("SimpleDateFormat") + fun savePicToPublicStorage( + context: Context, + data: ByteArray?, + isMirror: Boolean = false, + onSuccess: (savedPath: String, time: String) -> Unit, + onFailed: (msg: String) -> Unit + ) { + thread { + try { + val temp = System.currentTimeMillis() + + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) + val fileName = "IMG_$timeStamp.jpg" + + // 创建图片索引 + val value = ContentValues().apply { + put(MediaStore.Images.Media.DISPLAY_NAME, fileName) + put(MediaStore.Images.Media.MIME_TYPE, "image/jpg") + put(MediaStore.Images.Media.DATE_ADDED, temp) + } + + // 将该索引信息插入数据表,获得图片的Uri + // 保存的路径在 /sdcard/Pictures + val imageUri = context.contentResolver.insert( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + value + ) + + if (imageUri != null && data != null) { + //通过图片uri获得输出流 + val outputStream = context.contentResolver.openOutputStream(imageUri) + + val rawBitmap = BitmapFactory.decodeByteArray(data, 0, data.size) + val resultBitmap = if (isMirror) mirror(rawBitmap) else rawBitmap + resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream) + + onSuccess(imageUri.path ?: "", "${System.currentTimeMillis() - temp}") + } + } catch (e: Exception) { + e.printStackTrace() + onFailed("${e.message}") + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/CameraHelper.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/CameraHelper.kt new file mode 100644 index 0000000..287582c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/CameraHelper.kt @@ -0,0 +1,273 @@ +package com.fengliyan.tianlesue.utils.camera2 + +import android.app.Activity +import android.graphics.ImageFormat +import android.graphics.Matrix +import android.graphics.RectF +import android.hardware.Camera +import android.view.Surface +import android.view.SurfaceHolder +import android.view.SurfaceView +import android.widget.Toast + +/** + * author : chensen + * data : 2018/3/17 + * desc : + */ +class CameraHelper(activity: Activity, surfaceView: SurfaceView) : Camera.PreviewCallback { + + private var mCamera: Camera? = null //Camera对象 + private lateinit var mParameters: Camera.Parameters //Camera对象的参数 + private var mSurfaceView: SurfaceView = surfaceView //用于预览的SurfaceView对象 + var mSurfaceHolder: SurfaceHolder //SurfaceHolder对象 + + private var mActivity: Activity = activity + private var mCallBack: CallBack? = null //自定义的回调 + + var mCameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT //摄像头方向 + var mDisplayOrientation: Int = 0 //预览旋转的角度 + + private var picWidth = 2160 //保存图片的宽 + private var picHeight = 3840 //保存图片的高 + + override fun onPreviewFrame(data: ByteArray?, camera: Camera?) { + mCallBack?.onPreviewFrame(data) + } + + fun takePic() { + mCamera?.let { + it.takePicture({}, null, { data, _ -> + it.startPreview() + mCallBack?.onTakePic(data) + }) + } + } + + + private fun init() { + mSurfaceHolder.addCallback(object : SurfaceHolder.Callback { + override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + } + + override fun surfaceDestroyed(holder: SurfaceHolder) { + releaseCamera() + } + + override fun surfaceCreated(holder: SurfaceHolder) { + if (mCamera == null) { + openCamera(mCameraFacing) + } + startPreview() + } + }) + } + + //打开相机 + private fun openCamera(cameraFacing: Int = Camera.CameraInfo.CAMERA_FACING_BACK): Boolean { + val supportCameraFacing = supportCameraFacing(cameraFacing) + if (supportCameraFacing) { + try { + mCamera = Camera.open(cameraFacing) + initParameters(mCamera!!) + mCamera?.setPreviewCallback(this) + } catch (e: Exception) { + e.printStackTrace() + toast("打开相机失败!") + return false + } + } + return supportCameraFacing + } + + //配置相机参数 + private fun initParameters(camera: Camera) { + try { + mParameters = camera.parameters + mParameters.previewFormat = ImageFormat.NV21 + + //获取与指定宽高相等或最接近的尺寸 + //设置预览尺寸 + val bestPreviewSize = getBestSize(mSurfaceView.width, mSurfaceView.height, mParameters.supportedPreviewSizes) + bestPreviewSize?.let { + mParameters.setPreviewSize(it.width, it.height) + } + //设置保存图片尺寸 + val bestPicSize = getBestSize(picWidth, picHeight, mParameters.supportedPictureSizes) + bestPicSize?.let { + mParameters.setPictureSize(it.width, it.height) + } + //对焦模式 + if (isSupportFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) + mParameters.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE + + camera.parameters = mParameters + } catch (e: Exception) { + e.printStackTrace() + toast("相机初始化失败!") + } + } + + //开始预览 + fun startPreview() { + mCamera?.let { + it.setPreviewDisplay(mSurfaceHolder) + setCameraDisplayOrientation(mActivity) + it.startPreview() +// startFaceDetect() + } + } + + private fun startFaceDetect() { + mCamera?.let { + it.startFaceDetection() + it.setFaceDetectionListener { faces, _ -> + mCallBack?.onFaceDetect(transForm(faces)) +// log("检测到 ${faces.size} 张人脸") + } + } + } + + //判断是否支持某一对焦模式 + private fun isSupportFocus(focusMode: String): Boolean { + var autoFocus = false + val listFocusMode = mParameters.supportedFocusModes + for (mode in listFocusMode) { + if (mode == focusMode) + autoFocus = true +// log("相机支持的对焦模式: $mode") + } + return autoFocus + } + + //切换摄像头 + fun exchangeCamera() { + releaseCamera() + mCameraFacing = if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) + Camera.CameraInfo.CAMERA_FACING_FRONT + else + Camera.CameraInfo.CAMERA_FACING_BACK + + openCamera(mCameraFacing) + startPreview() + } + + //释放相机 + fun releaseCamera() { + if (mCamera != null) { + // mCamera?.stopFaceDetection() + mCamera?.stopPreview() + mCamera?.setPreviewCallback(null) + mCamera?.release() + mCamera = null + } + } + + //获取与指定宽高相等或最接近的尺寸 + private fun getBestSize(targetWidth: Int, targetHeight: Int, sizeList: List): Camera.Size? { + var bestSize: Camera.Size? = null + val targetRatio = (targetHeight.toDouble() / targetWidth) //目标大小的宽高比 + var minDiff = targetRatio + + for (size in sizeList) { + val supportedRatio = (size.width.toDouble() / size.height) +// log("系统支持的尺寸 : ${size.width} * ${size.height} , 比例$supportedRatio") + } + + for (size in sizeList) { + if (size.width == targetHeight && size.height == targetWidth) { + bestSize = size + break + } + + val supportedRatio = (size.width.toDouble() / size.height) + if (Math.abs(supportedRatio - targetRatio) < minDiff) { + minDiff = Math.abs(supportedRatio - targetRatio) + bestSize = size + } + } +// log("目标尺寸 :$targetWidth * $targetHeight , 比例 $targetRatio") +// log("最优尺寸 :${bestSize?.height} * ${bestSize?.width}") + return bestSize + } + + //设置预览旋转的角度 + private fun setCameraDisplayOrientation(activity: Activity) { + val info = Camera.CameraInfo() + Camera.getCameraInfo(mCameraFacing, info) + val rotation = activity.windowManager.defaultDisplay.rotation + + var screenDegree = 0 + when (rotation) { + Surface.ROTATION_0 -> screenDegree = 0 + Surface.ROTATION_90 -> screenDegree = 90 + Surface.ROTATION_180 -> screenDegree = 180 + Surface.ROTATION_270 -> screenDegree = 270 + } + + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + mDisplayOrientation = (info.orientation + screenDegree) % 360 + mDisplayOrientation = (360 - mDisplayOrientation) % 360 // compensate the mirror + } else { + mDisplayOrientation = (info.orientation - screenDegree + 360) % 360 + } + mCamera?.setDisplayOrientation(mDisplayOrientation) +// log("屏幕的旋转角度 : $rotation") +// log("setDisplayOrientation(result) : $mDisplayOrientation") + } + + //判断是否支持某个相机 + private fun supportCameraFacing(cameraFacing: Int): Boolean { + val info = Camera.CameraInfo() + for (i in 0 until Camera.getNumberOfCameras()) { + Camera.getCameraInfo(i, info) + if (info.facing == cameraFacing) return true + } + return false + } + + //将相机中用于表示人脸矩形的坐标转换成UI页面的坐标 + private fun transForm(faces: Array): ArrayList { + val matrix = Matrix() + // Need mirror for front camera. + val mirror = (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) + matrix.setScale(if (mirror) -1f else 1f, 1f) + // This is the value for android.hardware.Camera.setDisplayOrientation. + matrix.postRotate(mDisplayOrientation.toFloat()) + // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). + // UI coordinates range from (0, 0) to (width, height). + matrix.postScale(mSurfaceView.width / 2000f, mSurfaceView.height / 2000f) + matrix.postTranslate(mSurfaceView.width / 2f, mSurfaceView.height / 2f) + + val rectList = ArrayList() + for (face in faces) { + val srcRect = RectF(face.rect) + val dstRect = RectF(0f, 0f, 0f, 0f) + matrix.mapRect(dstRect, srcRect) + rectList.add(dstRect) + } + return rectList + } + + + private fun toast(msg: String) { + Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show() + } + + fun getCamera(): Camera? = mCamera + + fun addCallBack(callBack: CallBack) { + this.mCallBack = callBack + } + + interface CallBack { + fun onPreviewFrame(data: ByteArray?) + fun onTakePic(data: ByteArray?) + fun onFaceDetect(faces: ArrayList) + } + + init { + mSurfaceHolder = mSurfaceView.holder + init() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/FaceView.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/FaceView.kt new file mode 100644 index 0000000..637264e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/FaceView.kt @@ -0,0 +1,53 @@ +package com.fengliyan.tianlesue.utils.camera2 + +import android.content.Context +import android.graphics.* +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View + +/** + * author : chensen + * data : 2018/3/19 + * desc : + */ +class FaceView : View { + lateinit var mPaint: Paint + private var mCorlor = "#42ed45" + private var mFaces: ArrayList? = null + + constructor(context: Context) : super(context) { + init() + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init() + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + init() + } + + private fun init() { + mPaint = Paint() + mPaint.color = Color.parseColor(mCorlor) + mPaint.style = Paint.Style.STROKE + mPaint.strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f, context.resources.displayMetrics) + mPaint.isAntiAlias = true + } + + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + mFaces?.let { + for (face in it) { + canvas.drawRect(face, mPaint) + } + } + } + + fun setFaces(faces: ArrayList) { + this.mFaces = faces + invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/FileUtil.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/FileUtil.kt new file mode 100644 index 0000000..f5c0ef7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/FileUtil.kt @@ -0,0 +1,76 @@ +package com.fengliyan.tianlesue.utils.camera2 + +import android.annotation.SuppressLint +import com.fengliyan.tianlesue.controller.constant.ConstUrl +import java.io.File +import java.text.SimpleDateFormat +import java.util.* + + +/** + * author : ChenSen + * data : 2018/3/15 + * desc : + */ +object FileUtil { + private val rootFolderPath = ConstUrl.DEFAULT_PATH + File.separator + "CameraDemo" +// private val rootFolderPath = App.getRootPath() + File.separator + "CameraDemo" + + @SuppressLint("SimpleDateFormat") + fun createImageFile(isCrop: Boolean = false): File? { + return try { + val rootFile = File(rootFolderPath + File.separator + "capture") + if (!rootFile.exists()) + rootFile.mkdirs() + + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) + val fileName = if (isCrop) "IMG_${timeStamp}_CROP.jpg" else "IMG_$timeStamp.jpg" + File(rootFile.absolutePath + File.separator + fileName).apply { + if (!exists()) + createNewFile() + } + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + @SuppressLint("SimpleDateFormat") + fun createCameraFile(folderName: String = "camera1"): File? { + return try { + val rootFile = File(rootFolderPath + File.separator + folderName) + if (!rootFile.exists()) + rootFile.mkdirs() + + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) + val fileName = "IMG_$timeStamp.jpg" + File(rootFile.absolutePath + File.separator + fileName).apply { + if (!exists()) + createNewFile() + } + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + @SuppressLint("SimpleDateFormat") + fun createVideoFile(): File? { + return try { + val rootFile = File(rootFolderPath + File.separator + "video") + if (!rootFile.exists()) + rootFile.mkdirs() + + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) + val fileName = "VIDEO_$timeStamp.mp4" + File(rootFile.absolutePath + File.separator + fileName).apply { + if (!exists()) + createNewFile() + } + } catch (e: Exception) { + e.printStackTrace() + null + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/GirlCameraTakePicActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/GirlCameraTakePicActivity.kt new file mode 100644 index 0000000..4fff947 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/utils/camera2/GirlCameraTakePicActivity.kt @@ -0,0 +1,140 @@ +package com.fengliyan.tianlesue.utils.camera2 + +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.graphics.RectF +import android.os.Bundle +import android.view.WindowManager +import com.fengliyan.base.base.permission.AbsPermissionResultCallBack +import com.fengliyan.base.base.permission.PermissionHelper +import com.fengliyan.device.DeviceManager +import com.fengliyan.tianlesue.databinding.ActivityCamera2Binding +import com.fengliyan.tianlesue.im.uikit.common.media.picker.activity.CropImageActivity +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog +import com.fengliyan.uikit.toast.MaleToast + +class GirlCameraTakePicActivity : BaseActivity() { + + private var mCameraHelper: CameraHelper? = null + lateinit var binding: ActivityCamera2Binding + private var _savedPath: String? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityCamera2Binding.inflate(layoutInflater) + setContentView(binding.root) + + //权限允许 + val permissionDialog = PermissionDialog( + this, arrayOf( + Manifest.permission.CAMERA, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE + ) + ) + permissionDialog.show() + PermissionHelper.request(arrayOf( + Manifest.permission.CAMERA, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE + ), + object : AbsPermissionResultCallBack() { + override fun onPermissionGranted() { + permissionDialog.dismiss() + setContentView(binding.root) + setDefaultTitle() + hideTitleBar() + window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) + mCameraHelper = + CameraHelper(this@GirlCameraTakePicActivity, binding.surfaceView) + mCameraHelper!!.addCallBack(object : CameraHelper.CallBack { + override fun onPreviewFrame(data: ByteArray?) { + + } + + override fun onTakePic(data: ByteArray?) { + save(data!!) + } + + override fun onFaceDetect(faces: ArrayList) { + + } + }) + binding.btnTakePic.setOnClickListener { mCameraHelper?.takePic() } + binding.cancelBtn.setOnClickListener { finish() } + + } + + override fun onPermissionDenied(vararg permissions: String) { + val market = DeviceManager.getInstance().applicationMarket + if (market != null && market == "huawei") { + permissionDialog.dismiss() + finish() + return + } + super.onPermissionDenied(*permissions) + permissionDialog.dismiss() + } + }) + + } + + private fun save(byteArray: ByteArray) { + mCameraHelper?.mDisplayOrientation?.toFloat()?.let { + BitmapUtils.savePic( + byteArray, + "camera2", + it, + { savedPath, time -> + runOnUiThread { + //剪裁 + _savedPath = savedPath; + resources.displayMetrics.widthPixels*1.5 + CropImageActivity.startForFile( + this@GirlCameraTakePicActivity, + savedPath, + resources.displayMetrics.widthPixels, + (resources.displayMetrics.widthPixels * 1.5).toInt(), + savedPath, + 100 + ); + // finish() + // mManager?.whoStartCropWithUi(Uri.parse("file://$savedPath")) + // val intent = Intent() + // intent.putExtra("path",savedPath) + // setResult(Activity.RESULT_OK,intent) + // finish() + } + }, + { msg -> + runOnUiThread { + MaleToast.showMessage(this@GirlCameraTakePicActivity, "拍照失败") + + } + }) + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == 100 && resultCode == Activity.RESULT_OK) { + // val result = Intent() +// result.putExtra(Extras.EXTRA_FILE_PATH, outPath) +// setResult(Activity.RESULT_OK, result) +// finish() + val intent = Intent() + intent.putExtra("path", _savedPath) + setResult(Activity.RESULT_OK, intent) + finish() + } + } + + override fun onDestroy() { + super.onDestroy() + mCameraHelper?.releaseCamera() + } + +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseActivity.java new file mode 100644 index 0000000..fce8071 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseActivity.java @@ -0,0 +1,247 @@ +package com.fengliyan.tianlesue.view.base; + +import android.app.Activity; +import android.content.Intent; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.utils.AppStatusCallbacks; +import com.fengliyan.tianlesue.view.login.LoginActivity; +import com.fengliyan.tianlesue.view.main.MainActivity; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; + +/** + * Created by abby on 2018/3/20. + */ + +public class BaseActivity extends AppCompatActivity { + public Title mTitle; + private ViewGroup mContent; + private SwipeRefreshLayout mRefresh; + private View mNoNetView; + private Button mRetry; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + DeviceManager.getInstance().init(this); + if (needScallfold()) { + super.setContentView(R.layout.activity_base); + mTitle = (Title) findViewById(R.id.base_title); + mContent = (ViewGroup) findViewById(R.id.base_content); + mNoNetView = findViewById(R.id.base_no_network); + mRetry = findViewById(R.id.base_retry); + mRefresh = findViewById(R.id.base_refresh); + mRefresh.setEnabled(false); + setDefaultTitle(); + initState(this, Color.TRANSPARENT); + if (null != getSupportActionBar()) { + getSupportActionBar().hide(); + } + } + if (AppStatusCallbacks.get().getmAppStatus() == AppStatusCallbacks.STATUS_KILLED) { + boolean is_login = SPUtils.getBoolean(this, ConsUser.IS_LOGIN, false); + BaseApplication.getInstance().initSdk(); + Intent intent; + if (is_login) { + intent = new Intent(this, MainActivity.class); + } else { + intent = new Intent(this, LoginActivity.class); + } + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + } + } + + public boolean needScallfold() { + return true; + } + + //设置状态栏透明 + public void initState(Activity mActivity, int color) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + //Android 4.4 statusBar半透明 + mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + //Android 5.0以上 statusBar背景全透明 + Window window = mActivity.getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(color); + } + Utils.StatusBarLightMode(this, true); + } + + private String getRunningActivityName() { + String contextString = this.toString(); + return contextString.substring(contextString.lastIndexOf(".") + + 1, contextString.indexOf("@")); + } + + public void dissmissTitleBottomLine() { + mTitle.dismissBottomLine(); + } + + public void showTitleBottomLine() { + mTitle.showBottomLine(); + } + + public void setTitleName(String titleName) { + mTitle.setTitle(titleName); + } + + public void hideTitleBar() { + mTitle.setVisibility(View.GONE); + } + + public void setDefaultTitle() { + mTitle.findViewById(R.id.title_bg).getBackground().setAlpha(255); + ImageView left = (ImageView) mTitle.findViewById(R.id.left_image); + left.setImageResource(R.drawable.ic_return); + + RelativeLayout rlBaseBack = mTitle.findViewById(R.id.rl_base_back); + + rlBaseBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + finishActivity(); + } + }); + } + + public void finishActivity() { + finish(); + } + + @Override + public void onResume() { + super.onResume(); + // AnalyticsManager.getInstance(this).onResume(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + StorageManager.getInstance(this).putBoolean(Constans.IS_SHOW_DIALOG, false); + // AnalyticsManager.getInstance(this).onPageStop(getRunningActivityName()); + } + + @Override + public void setContentView(View v) { + mContent.removeAllViews(); + mContent.addView(v); + } + + @Override + public void setContentView(int viewId) { + if (needScallfold()) { + setContentView(View.inflate(this, viewId, null)); + } else { + super.setContentView(viewId); + } + } + + public Title getCustomTitle() { + return mTitle; + } + + public void setRightCustomTextTitle(String titleName, String rightText, View.OnClickListener rightClickListener) { + setDefaultTitle(); + setTitleName(titleName); + TextView textView = mTitle.findViewById(R.id.right_text); + textView.setVisibility(View.VISIBLE); + textView.setText(rightText); + textView.setOnClickListener(rightClickListener); + } + + public void setRightCustomTextTitle(String rightText, int textColor, float textSize, View.OnClickListener rightClickListener) { + TextView textView = mTitle.findViewById(R.id.right_text); + textView.setTextColor(textColor); + textView.setTextSize(textSize); + textView.setVisibility(View.VISIBLE); + textView.setText(rightText); + textView.setOnClickListener(rightClickListener); + } + + public void setRightCustomImageTitle(String titleName, int resid, View.OnClickListener rightClickListener) { + setDefaultTitle(); + setTitleName(titleName); + ImageView imageView = mTitle.findViewById(R.id.right_image); + imageView.setVisibility(View.VISIBLE); + imageView.setOnClickListener(rightClickListener); + imageView.setImageResource(resid); + } + + + @Override + public Resources getResources() { + // 字体大小不跟随系统 + Resources res = super.getResources(); +// if (res.getConfiguration().fontScale!=1) { + Configuration config = new Configuration(); + config.setToDefaults(); + res.updateConfiguration(config, res.getDisplayMetrics()); +// } + return res; + } + + public SwipeRefreshLayout getRefresh() { + return mRefresh; + } + + public void showNoNetView() { + mContent.setVisibility(View.GONE); + mNoNetView.setVisibility(View.VISIBLE); + } + + public void dimissNoNetView() { + mContent.setVisibility(View.VISIBLE); + mNoNetView.setVisibility(View.GONE); + } + + public void setRetryButton(View.OnClickListener listener) { + mRetry.setOnClickListener(listener); + } +// @Override +// public Resources getResources() { +// +// Resources res = super.getResources(); +// if (res.getConfiguration().fontScale != 1) {//非默认值 +// Configuration configuration = new Configuration(); +// configuration.setToDefaults(); +// res.updateConfiguration(configuration, res.getDisplayMetrics()); +// } +// return res; +// } + + public void startMainActivity(Class clz) { + Intent intent = new Intent(); + intent.setClass(this, clz); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseApplication.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseApplication.java new file mode 100644 index 0000000..7909e9a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseApplication.java @@ -0,0 +1,1029 @@ +package com.fengliyan.tianlesue.view.base; + +import android.app.Activity; +import android.app.ActivityManager; +import android.app.Application; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.net.http.HttpResponseCache; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Process; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; + +import com.alipay.face.api.ZIMFacade; +import com.amap.api.maps.MapsInitializer; +import com.blankj.utilcode.util.ActivityUtils; +import com.bytedance.ads.convert.BDConvert; +import com.bytedance.ads.convert.config.BDConvertConfig; +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.imagepipeline.core.ImagePipelineConfig; +import com.faceunity.nama.FURenderer; +import com.github.gzuliyujiang.oaid.DeviceIdentifier; +import com.google.android.exoplayer2.database.DatabaseProvider; +import com.google.android.exoplayer2.database.ExoDatabaseProvider; +import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor; +import com.google.android.exoplayer2.upstream.cache.SimpleCache; +import com.google.gson.Gson; +import com.heytap.msp.push.HeytapPushManager; +import com.heytap.msp.push.callback.ICallBackResultService; +import com.hihonor.push.sdk.HonorPushCallback; +import com.hihonor.push.sdk.HonorPushClient; +import com.huawei.hms.support.common.ActivityMgr; +import com.fengliyan.base.base.ContextHolder; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.location.LocationManager; +import com.fengliyan.messaging.AttentionAttachment; +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.messaging.CustomAttachment; +import com.fengliyan.messaging.CustomParser; +import com.fengliyan.messaging.DynamicAttachment; +import com.fengliyan.messaging.GiftAttachment; +import com.fengliyan.messaging.OnlineNoticeAttachment; +import com.fengliyan.messaging.SysInfoAttachment; +import com.fengliyan.messaging.SysInfoDoubleImageAttachment; +import com.fengliyan.messaging.SysInfoSingleImageAttachment; +import com.fengliyan.messaging.VideoAttachment; +import com.fengliyan.messaging.YestordayAttachment; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.eventBus.NotificationEvent; +import com.fengliyan.tianlesue.controller.eventBus.UnReadCountEvent; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.api.model.recent.RecentCustomization; +import com.fengliyan.tianlesue.im.uikit.api.model.session.SessionCustomization; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.GiftViewHolder; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderTip; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultRecentCustomization; +import com.fengliyan.tianlesue.model.main.VideoRequestBean; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.model.webSocket.RedEnvelopesSocketBean; +import com.fengliyan.tianlesue.utils.BeautySPUtils; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.utils.AppStatusCallbacks; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.FirstChargeGiftDialog; +import com.fengliyan.tianlesue.view.base.utils.view.LotteryNineDialog; +import com.fengliyan.tianlesue.view.main.MainActivity; +import com.fengliyan.tianlesue.view.main.dialog.RedEnvelopesDialog; +import com.fengliyan.tianlesue.view.news.activity.ChatSettingActivity; +import com.fengliyan.tianlesue.view.news.activity.FakeActivity; +import com.fengliyan.tianlesue.view.news.im.DemoCache; +import com.fengliyan.tianlesue.view.news.im.holder.AttentionFansHolder; +import com.fengliyan.tianlesue.view.news.im.holder.DynamicHolder; +import com.fengliyan.tianlesue.view.news.im.holder.OnlineNoticeHolder; +import com.fengliyan.tianlesue.view.news.im.holder.SysInfoDoubleImageViewHolder; +import com.fengliyan.tianlesue.view.news.im.holder.SysInfoSingleImageViewHolder; +import com.fengliyan.tianlesue.view.news.im.holder.SysInfoViewHolder; +import com.fengliyan.tianlesue.view.news.im.holder.VideoViewHolder; +import com.fengliyan.tianlesue.view.news.im.holder.YestodayViewHolder; +import com.fengliyan.tianlesue.view.news.im.mixpush.DemoMixPushMessageHandler; +import com.fengliyan.tianlesue.view.news.im.mixpush.DemoPushContentProvider; +import com.fengliyan.tianlesue.view.settings.QuickRechargeActivity; +import com.fengliyan.tianlesue.view.settings.dialog.GirlAuthDialog; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.htprotect.HTProtect; +import com.netease.htprotect.callback.HTPCallback; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.SDKOptions; +import com.netease.nimlib.sdk.ServerAddresses; +import com.netease.nimlib.sdk.StatusBarNotificationConfig; +import com.netease.nimlib.sdk.auth.LoginInfo; +import com.netease.nimlib.sdk.mixpush.MixPushConfig; +import com.netease.nimlib.sdk.mixpush.NIMPushClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.netease.nimlib.sdk.util.NIMUtil; +import com.tencent.bugly.crashreport.CrashReport; +import com.xinlingwu.share.ShareManager; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * Created by abby on 2018/3/20. + */ + +public class BaseApplication extends Application { + + private static final String TAG = "BaseApplication"; + private static BaseApplication instance; + + public static BaseApplication getInstance() { + return instance; + } + + private boolean isVideo = false; + private boolean isFront = true; + private com.netease.nimlib.sdk.Observer> mMessageObserver; + private Activity mActivity; + private BaseWebSocket mBaseWebSocket = null; + // private UserStatisticsWebSocket userStatisticsWebSocket; + private RedEnvelopesDialog mRedEnvelopesDialog; + private String avatar; + + @Override + public void onCreate() { + super.onCreate(); + instance = this; + disableAPIDialog(); + activityLifeCallback(); + + ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this) + .setDownsampleEnabled(true).build(); + + Fresco.initialize(this, config); + ContextHolder.init(this); + + //oaid的 +// System.loadLibrary("nllvm1632808251147706677"); + + // 加固版本在调用前必须载入 SDK 安全库 + NIMClient.config(this, getLoginInfo(), options(this)); + if (SPUtils.getBoolean(this, ConsUser.IS_LOGIN_AGREEMENT_CHECK, false)) { + initSdk(); + initCache(); + } + } + + public static SimpleCache getSimpleCache() { + if (simpleCache == null) { + initCache(); + } + return simpleCache; + } + + private static void initCache() { + // 定义缓存文件夹 + File cacheDir = new File(instance.getCacheDir(), "video_cache"); + // 定义缓存逐出策略(基于 LRU 缓存策略) + LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(CACHE_SIZE_BYTES); + // 数据库用于存储缓存元数据 + DatabaseProvider databaseProvider = new ExoDatabaseProvider(instance); + // 初始化 SimpleCache + simpleCache = new SimpleCache(cacheDir, evictor, databaseProvider); + } + + public Activity getTopActivity() { + return mActivity; + } + + private static SimpleCache simpleCache; + private static final long CACHE_SIZE_BYTES = 1024 * 1024 * 1024; // 100 MB 缓存大小 + + public void initSdk() { + if (NIMUtil.isMainProcess(this)) { + try { + HttpResponseCache.install(new File(ConstUrl.DEFAULT_PATH, "svga"), CACHE_SIZE_BYTES); + } catch (IOException e) { + e.printStackTrace(); + } + DeviceIdentifier.register(this); +// HTProtectConfig config = new HTProtectConfig(); +// config.setHost("12.23.34.45:8080"); // 设置额外数据 + + HTProtect.init(this, "YD00378411416036", new HTPCallback() { + @Override + public void onReceive(int i, String s) { + if (BuildConfig.DEBUG) { + Log.i("TAG", "onReceive: s-------->" + s); + } + } + }, null); + NIMClient.initSDK(); + CrashReport.initCrashReport(getApplicationContext(), "5efbf6af0e", BuildConfig.IS_DEV); + DeviceManager.getInstance().init(this); + /* + 调用初始化时请注意: + 1. 首次启动,确保用户同意《隐私政策》之后,再初始化openinstall SDK; + 2. 仅在主进程的UI线程中调用初始化接口,多进程调用将会导致获取参数失败,统计数据异常; + 3. 初始化调用时,尽量保证应用处于前台可触控状态下,对提升参数还原精度有很大的帮助。 + */ +// OpenInstall.init(this); + MapsInitializer.updatePrivacyShow(instance, true, true); + MapsInitializer.updatePrivacyAgree(instance, true); + LocationManager.getInstance().init(this); +// StatusBarNotificationConfig statusBarNotificationConfig = new StatusBarNotificationConfig(); +// statusBarNotificationConfig.notificationEntrance = ChatActivity.class; +// +// ChatManager.getInstance().init(this, statusBarNotificationConfig); + + // AnalyticsManager.getInstance(this).onInint(this); + + new Thread(new Runnable() { + @Override + public void run() { + NoClearSPUtils.saveString(instance, "x-risk-engine-token", ""); + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + FURenderer.getInstance().setup(instance); + ShareManager.getInstance().configWeibo("1310381086", + "a0827c4e349c051e4da9bce421124945", + "https://api.weibo.com/oauth2/default.html"); + ShareManager.getInstance().configQQ("1112299706", + "RGq1XT6LaLvuP5DJ"); + ShareManager.getInstance().configWeixin("wx99d6a2e2d4967362", + "0133b45344a854e4870f7bad5468b618"); + + BDConvertConfig config = new BDConvertConfig(); + config.setEnableLog(true); + if (ActivityUtils.getTopActivity() != null) { + BDConvert.INSTANCE.init(instance, config, ActivityUtils.getTopActivity()); + } + ZIMFacade.install(instance); + String manufacturer = Build.MANUFACTURER; + if (manufacturer != null && manufacturer.length() > 0) { + String phone_type = manufacturer.toLowerCase(); + Log.i("TAG", "initSdk: phone_type------------>" + phone_type); + switch (phone_type) { + case "huawei": + //华为推送初始化 + ActivityMgr.INST.init(instance); + break; + case "xiaomi": + break; + case "oppo": + case "realme": + //oppo推送 + HeytapPushManager.init(instance, true); + Log.i("TAG", "run: HeytapPushManager.isSupportPush()------------>" + HeytapPushManager.isSupportPush()); + HeytapPushManager.register(instance, "939237cf4bd74b18aaa3d976b63fd51b", "3938eb1a153b42ac84c9fb5b1143b122", new ICallBackResultService() { + @Override + public void onRegister(int i, String s) { + Log.i("TAG", "onRegister: s---------->" + i + s); + } + + @Override + public void onUnRegister(int i) { + + } + + @Override + public void onSetPushTime(int i, String s) { + + } + + @Override + public void onGetPushStatus(int i, int i1) { + + } + + @Override + public void onGetNotificationStatus(int i, int i1) { + + } + }); + HeytapPushManager.requestNotificationPermission(); + break; + case "honor": + HonorPushClient.getInstance().init(getApplicationContext(), true); + boolean isSupport = HonorPushClient.getInstance().checkSupportHonorPush(instance); + Log.i(TAG, "run: isSupport------->" + isSupport); + HonorPushClient.getInstance().getPushToken(new HonorPushCallback() { + @Override + public void onSuccess(String pushToken) { + Log.i(TAG, "run: pushToken------->" + pushToken); + } + + @Override + public void onFailure(int errorCode, String errorString) { + } + }); + break; + } + } + } + }).start(); + + // 注册自定义推送消息处理,这个是可选项 + NIMPushClient.registerMixPushMessageHandler(new DemoMixPushMessageHandler()); + + NimUIKit.init(this); + NIMClient.toggleNotification(NoClearSPUtils.getBoolean(this, Constant.NEW_MESSAGE_NOTICE, true)); + NIMClient.getService(MsgService.class).registerCustomAttachmentParser(new CustomParser()); + NimUIKit.registerMsgItemViewHolder(SysInfoAttachment.class, SysInfoViewHolder.class); + NimUIKit.registerMsgItemViewHolder(SysInfoSingleImageAttachment.class, SysInfoSingleImageViewHolder.class); + NimUIKit.registerMsgItemViewHolder(SysInfoDoubleImageAttachment.class, SysInfoDoubleImageViewHolder.class); + NimUIKit.registerMsgItemViewHolder(GiftAttachment.class, GiftViewHolder.class); + NimUIKit.registerMsgItemViewHolder(VideoAttachment.class, VideoViewHolder.class); + NimUIKit.registerMsgItemViewHolder(YestordayAttachment.class, YestodayViewHolder.class); + NimUIKit.registerMsgItemViewHolder(AttentionAttachment.class, AttentionFansHolder.class); + NimUIKit.registerMsgItemViewHolder(DynamicAttachment.class, DynamicHolder.class); + NimUIKit.registerMsgItemViewHolder(OnlineNoticeAttachment.class, OnlineNoticeHolder.class); + NimUIKit.registerTipMsgViewHolder(MsgViewHolderTip.class); + + // 添加自定义推送文案以及选项,请开发者在各端(Android、IOS、PC、Web)消息发送时保持一致,以免出现通知不一致的情况 + NimUIKit.setCustomPushContentProvider(new DemoPushContentProvider()); + + // 会话列表改变 + mMessageObserver = recentContacts -> { + if (recentContacts != null) { + int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount(); + avatar = ""; + NIMClient.getService(MsgService.class).queryRecentContacts().setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List recentContacts, Throwable throwable) { + if (recentContacts != null && recentContacts.size() > 0) { + for (int i = 0; i < recentContacts.size(); i++) { + if (recentContacts.get(i).getUnreadCount() != 0 && Long.parseLong(recentContacts.get(i).getContactId()) > 20 && recentContacts.get(i).getSessionType() == SessionTypeEnum.P2P) { + NimUserInfo userInfo = NIMClient.getService(UserService.class).getUserInfo(recentContacts.get(i).getContactId()); + Log.i("TAG", "recentContacts: ----------->" + userInfo); + if (userInfo != null) { + avatar = userInfo.getAvatar(); + if (!TextUtils.isEmpty(avatar)) { + avatar = StrU.getResourcePath(avatar, getApplicationContext()); + } + } + break; + } + } + } + EventBus.getDefault().post(new UnReadCountEvent(unreadNum, avatar)); + } + }); + } + }; + + NIMClient.getService(MsgServiceObserve.class) + .observeRecentContact((com.netease.nimlib.sdk.Observer>) mMessageObserver, true); + + registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + + } + + @Override + public void onActivityStarted(Activity activity) { + + } + + @Override + public void onActivityResumed(Activity activity) { + //当前activity + mActivity = activity; + mRedEnvelopesDialog = null; + if (mActivity instanceof MainActivity && mBaseWebSocket == null) { + mBaseWebSocket = new BaseWebSocket(new BaseWebSocket.MyWebSocketListener() { + @Override + public void onMessageListener(String type, String data) { + if (mActivity == null || !SPUtils.getBoolean(getApplicationContext(), ConsUser.IS_LOGIN, false)) + return; + if ("redEnvelope".equals(type)) {//红包 + Gson gson = new Gson(); + RedEnvelopesSocketBean redEnvelopesSocketBean = gson.fromJson(data, RedEnvelopesSocketBean.class); + if (mRedEnvelopesDialog == null) + mRedEnvelopesDialog = new RedEnvelopesDialog(mActivity); + mRedEnvelopesDialog.show(redEnvelopesSocketBean.rpId); + } + } + + }); + } + } + + @Override + public void onActivityPaused(Activity activity) { + + } + + @Override + public void onActivityStopped(Activity activity) { + + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + + } + + @Override + public void onActivityDestroyed(Activity activity) { + if (mActivity == activity) { + mActivity = null; + } + } + }); + + NimUIKit.setRecentCustomization(getRecentCustomization()); + + ChatManager.getInstance().registerCustomNotification(new ChatManager.CustomNotificationListener() { + @Override + public void onNotificationReceived(CustomNotification notification) { + String content = notification.getContent(); + Gson gson = new Gson(); + final VideoRequestBean videoRequestBean = gson.fromJson(content, VideoRequestBean.class); + if (null != videoRequestBean) { + Log.i("TAG", "onNotificationReceived: videoRequestBean.getId()----------->" + videoRequestBean.getId()); + if (11 == videoRequestBean.getId() || 10 == videoRequestBean.getId() || 12 == videoRequestBean.getId() || 13 == videoRequestBean.getId()) { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + EventBus.getDefault().post(new NotificationEvent(videoRequestBean)); + } + }, 500); + } + if (14 == videoRequestBean.getId()) { + LotteryNineDialog dialog = new LotteryNineDialog(ActivityUtils.getTopActivity(),videoRequestBean.getData()); + dialog.show(); + } + } + } + }); + } + + NimUIKit.setCommonP2PSessionCustomization(getP2pCustomization()); + if (!BeautySPUtils.getBoolean("isSet")) { + BaseApplication.getInstance().setDefaultBeautySetting(); + } + } + +// public void userstatisticsSocketConnect() { +// userStatisticsWebSocket = new UserStatisticsWebSocket(new UserStatisticsWebSocket.MyWebSocketListener() { +// @Override +// public void onMessageListener(String type, String data) { +// +// } +// }); +// } + +// public void userstatisticsSocketClose() { +// if (userStatisticsWebSocket != null) { +// userStatisticsWebSocket.close(); +// userStatisticsWebSocket = null; +// } +// } + + /** + * 反射 禁止弹窗 + */ + private void disableAPIDialog() { + try { + // 仅适用于旧版本 Android 的反射方法 + Class clazz = Class.forName("android.app.ActivityThread"); + Method method = clazz.getDeclaredMethod("currentActivityThread"); + Object activityThread = method.invoke(null); + // 尝试兼容不同版本的字段名 + String[] possibleFieldNames = {"mHiddenApiWarningShown", "sHiddenApiWarningShown"}; + for (String fieldName : possibleFieldNames) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + field.setBoolean(activityThread, true); + return; // 成功设置则退出 + } catch (NoSuchFieldException ignore) { + // 尝试下一个可能的字段名 + } + } + } catch (Exception e) { + } + } + + private int mFinalCount; + + /** + * 前后台切换监听 + */ + private void activityLifeCallback() { + AppStatusCallbacks.init(instance); +// registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { +// +// @Override +// public void onActivityCreated(Activity activity, Bundle savedInstanceState) { +// } +// +// @Override +// public void onActivityStarted(Activity activity) { +// mFinalCount++; //如果mFinalCount ==1,说明是从后台到前台 +//// Log.e("onActivityStarted", mFinalCount + ""); +// if (mFinalCount == 1) {//说明从后台回到了前台 +//// Log.d("nail","回到前台"); +// EventBus.getDefault().post(new ActiveUpdateEvent()); +// setFront(true); +// } +// } +// +// @Override +// public void onActivityResumed(Activity activity) { +// } +// +// @Override +// public void onActivityPaused(Activity activity) { +// } +// +// @Override +// public void onActivityStopped(Activity activity) { +// mFinalCount--; //如果mFinalCount ==0,说明是前台到后台 +//// Log.i("onActivityStopped", mFinalCount + ""); +// if (mFinalCount == 0) {//说明从前台回到了后台 +//// Log.d("nail","退到后台"); +// setFront(false); +// } +// } +// +// @Override +// public void onActivitySaveInstanceState(Activity activity, Bundle outState) { +// } +// +// @Override +// public void onActivityDestroyed(Activity activity) { +// } +// }); + } + + private RecentCustomization recentCustomization; + + private RecentCustomization getRecentCustomization() { + if (recentCustomization == null) { + recentCustomization = new DefaultRecentCustomization() { + @Override + public String getDefaultDigest(RecentContact recent) { + switch (recent.getMsgType()) { + case custom: + MsgAttachment attachment = recent.getAttachment(); + CustomAttachment customAttachment = (CustomAttachment) attachment; + if (customAttachment.getType() == 11) { + SysInfoAttachment sysInfoAttachment = (SysInfoAttachment) customAttachment; + return sysInfoAttachment.getSysInfoTextBean().getTitle(); + } else if (customAttachment.getType() == 12) { + SysInfoSingleImageAttachment sysInfoSingleImageAttachment = (SysInfoSingleImageAttachment) customAttachment; + if (sysInfoSingleImageAttachment.getAct_type() == 1) { + return sysInfoSingleImageAttachment.getAct_string(); + } else if (sysInfoSingleImageAttachment.getAct_type() == 2) { + return sysInfoSingleImageAttachment.getTitle(); + } else { + return "图文"; + } + + } else if (customAttachment.getType() == 13) { + SysInfoDoubleImageAttachment sysInfoDoubleImageAttachment = (SysInfoDoubleImageAttachment) customAttachment; + return sysInfoDoubleImageAttachment.getImageList().get(0).getTitle(); + } else if (customAttachment.getType() == 14) { + GiftAttachment giftAttachment = (GiftAttachment) customAttachment; + if (giftAttachment.getFrom_uid() == SPUtils.getInt(getApplicationContext(), ConsUser.USER_ID)) { + return "[赠送礼物]"; + } else { + return "[收到礼物]"; + } + } else if (customAttachment.getType() == 15) { + VideoAttachment videoAttachment = (VideoAttachment) customAttachment; + String videoStr; + if (videoAttachment.getCalltype() == 1) { + videoStr = "[视频通话]"; + } else { + videoStr = "[语音通话]"; + } + if (videoAttachment.getFrom_uid().equals(SPUtils.getInt(getApplicationContext(), ConsUser.USER_ID) + "")) { //发送的 + if (videoAttachment.getStatus() == 1) { + return videoStr + "[已取消]"; + } else if (videoAttachment.getStatus() == 2) { + return videoStr + "[对方已拒绝]"; + } else if (videoAttachment.getStatus() == 3) { + return videoStr + "[超时未接听]"; + } else if (videoAttachment.getStatus() == 4) { + return videoStr + "[通话时长:" + secondToTime(videoAttachment.getCall_time()) + "]"; + } else { + return videoStr; + } + } else { //接收的 + if (videoAttachment.getStatus() == 1) { + return videoStr + "[对方已取消]"; + } else if (videoAttachment.getStatus() == 2) { + return videoStr + "[已拒绝]"; + } else if (videoAttachment.getStatus() == 3) { + return videoStr + "[超时未接听]"; + } else if (videoAttachment.getStatus() == 4) { + return videoStr + "[通话时长:" + secondToTime(videoAttachment.getCall_time()) + "]"; + } + } + } else if (customAttachment.getType() == 16) { + AttentionAttachment attentionAttachment = (AttentionAttachment) customAttachment; + return attentionAttachment.getNickname() + "关注了你"; + } else if (customAttachment.getType() == 17) { + return "动态更新"; + } else if (customAttachment.getType() == 18) { + OnlineNoticeAttachment onlineNoticeAttachment = (OnlineNoticeAttachment) customAttachment; + return onlineNoticeAttachment.getNickname() + "上线啦"; + } else if (customAttachment.getType() == 22) { + return "您的昨日收益"; + } else if (customAttachment.getType() == 24) { + DynamicAttachment dynamicAttachment = (DynamicAttachment) customAttachment; + return dynamicAttachment.getNickname() + "点赞了你的动态"; + } else if (customAttachment.getType() == 26) { + DynamicAttachment dynamicAttachment = (DynamicAttachment) customAttachment; + return dynamicAttachment.getNickname() + "评论了你的动态"; + } +// AVChatAttachment avchat = (AVChatAttachment) attachment; +// if (avchat.getState() == AVChatRecordState.Missed && !recent.getFromAccount().equals(NimUIKit.getAccount())) { +// // 未接通话请求 +// StringBuilder sb = new StringBuilder("[未接"); +// if (avchat.getType() == AVChatType.VIDEO) { +// sb.append("视频电话]"); +// } else { +// sb.append("音频电话]"); +// } +// return sb.toString(); +// } else if (avchat.getState() == AVChatRecordState.Success) { +// StringBuilder sb = new StringBuilder(); +// if (avchat.getType() == AVChatType.VIDEO) { +// sb.append("[视频电话]: "); +// } else { +// sb.append("[音频电话]: "); +// } +// sb.append(TimeUtil.secToTime(avchat.getDuration())); +// return sb.toString(); +// } else { +// if (avchat.getType() == AVChatType.VIDEO) { +// return ("[视频电话]"); +// } else { +// return ("[音频电话]"); +// } +// } + } + return super.getDefaultDigest(recent); + } + }; + } + + return recentCustomization; + } + +// public String getFormatedDateTime(long dateTime) { +// SimpleDateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss"); +// return sDateFormat.format(new Date(dateTime + 0)); +// } + + private String secondToTime(long second) { + second = second % 86400; + long hours = second / 3600; + second = second % 3600; + long minutes = second / 60; + second = second % 60; + + String strHours = String.format("%02d", hours); + String strMinutes = String.format("%02d", minutes); + String strSecond = String.format("%02d", second); + return strHours + ":" + strMinutes + ":" + strSecond; + } + + + public String getProcessName(Context cxt, int pid) { + ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE); + List runningApps = am.getRunningAppProcesses(); + if (runningApps == null) { + return null; + } + for (ActivityManager.RunningAppProcessInfo procInfo : runningApps) { + if (procInfo.pid == pid) { + return procInfo.processName; + } + } + return null; + } + + private MixPushConfig buildMixPushConfig() { + + // 第三方推送配置 + MixPushConfig config = new MixPushConfig(); + + // 小米推送 + config.xmAppId = "2882303761520246241"; + config.xmAppKey = "5342024622241"; + config.xmCertificateName = "siyuXiaomi"; + + // 华为推送 + config.hwAppId = "108318391"; + config.hwCertificateName = "xiayueHuawei"; +// +// // 魅族推送 + config.mzAppId = "126471"; + config.mzAppKey = "7f1ead3831f14f628829056619804b0e"; + config.mzCertificateName = "xiayueMeizu"; +// +// // fcm 推送,适用于海外用户,不使用fcm请不要配置 +// config.fcmCertificateName = "DEMO_FCM_PUSH"; + + //oppo + config.oppoAppId = "31060347"; + config.oppoAppKey = "939237cf4bd74b18aaa3d976b63fd51b"; + config.oppoAppSercet = "3938eb1a153b42ac84c9fb5b1143b122"; + config.oppoCertificateName = "siyuOppo"; + + config.vivoCertificateName = "siyuVIVO"; + + config.honorCertificateName = "siyuHonor"; + + return config; + } + + + //获取IM登录信息 + private LoginInfo getLoginInfo() { + String account = SPUtils.getString(this, "im_account"); + String token = SPUtils.getString(this, "im_token"); + + if (!TextUtils.isEmpty(account) && !TextUtils.isEmpty(token)) { + DemoCache.setAccount(account); + return new LoginInfo(account, token); + } else { + return null; + } + } + + public boolean isVideo() { + return isVideo; + } + + public void setVideo(boolean video) { + isVideo = video; + } + + public boolean isFront() { + return AppStatusCallbacks.get().isFront(); + } + +// public void setFront(boolean front) { +// isFront = front; +// } + + private SDKOptions options(Context context) { + SDKOptions options = new SDKOptions(); + options.statusBarNotificationConfig = getStatusConfig(NoClearSPUtils.getBoolean(this, Constant.RING_NOTICE, true) + , NoClearSPUtils.getBoolean(this, Constant.SHAKE_NOTICE, true)); + String sdkPath = getAppCacheDir(context) + "/nim"; + options.sdkStorageRootPath = sdkPath; + options.preloadAttach = true; + //第三方推送设置 + options.mixPushConfig = buildMixPushConfig(); + + ServerAddresses serverAddresses = new ServerAddresses(); + serverAddresses.module = "0081c4bb8bf3ec6941275d4a74af3e4bcd38775caf912eab0fa490e4b33bf6ee0cc85e09f1482d10bfbf9fa7bfc06c2fbfd86565690c0f2c2014f17cd46a482bb4b8b8e56c9a93fec3273d3d71c5d42b91bd474a7b92c936d96ea6889d0d77b4113649f70086c419249d61290484d90c8a38cc503e13f9f37a9cb088436dd131bf"; + serverAddresses.defaultLink = "link.chatnos.com:8080"; + serverAddresses.lbs = "https://lbs.chatnos.com/lbs/conf.jsp"; + serverAddresses.nosUploadLbs = "https://wanproxy.127.net/lbs"; + serverAddresses.nosUploadDefaultLink = "https://nosup-hz1.127.net"; + serverAddresses.nosDownloadUrlFormat = "{bucket}.nosdn.127.net/{object}"; + serverAddresses.nosSupportHttps = true; + serverAddresses.nosUpload = "nosup-hz1.127.net"; + options.serverConfig = serverAddresses; + return options; + } + + + public StatusBarNotificationConfig getStatusConfig(boolean ring, boolean vibrate) { + StatusBarNotificationConfig config = new StatusBarNotificationConfig(); + config.notificationEntrance = FakeActivity.class; + config.ledARGB = Color.GREEN; + config.ledOnMs = 1000; + config.ledOffMs = 1500; + config.ring = ring; + config.vibrate = vibrate; + return config; + } + + + /** + * 配置 APP 保存图片/语音/文件/log等数据的目录 + * 这里示例用SD卡的应用扩展存储目录 + */ + private String getAppCacheDir(Context context) { + String storageRootPath = null; +// try { +// if (context.getExternalCacheDir() != null) { +// storageRootPath = context.getExternalCacheDir().getCanonicalPath(); +// } +// } catch (IOException e) { +// +// } +// if (TextUtils.isEmpty(storageRootPath)) { +// storageRootPath = Environment.getExternalStorageDirectory() + "/" + context.getPackageName(); +// } + storageRootPath = getCacheDir().getAbsolutePath(); + + return storageRootPath; + } + + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + } + + /** + * "usercode":"101223", + * "nickname":"111111", + * "type":0, + * "mobile":"130****1017", + * "avatar":"uploads/album/201809/02/b38a3845d6291fbe869d63b42134e642.jpg", + * "gender":2, + * "age":6, + * "birthday":"2012-01-01", + * "city":"北京", + * "finish_status":1, + * "im_token":"8144d5aa-389d-48d2-acda-b2cf8a27115d", + * "is_anchor":0, + * "invite_code":"105647", + * "token":"94ea021c-6e4c-4863-827b-2487156517b6", + * "user_id":241, + * "createtime":1543907842, + * "expiretime":1546499842, + * "expires_in":2592000 + */ + public void setUserInfo(BaseUserInfo userInfo) { + + SPUtils.saveBoolean(this, ConsUser.IS_LOGIN, true); + + SPUtils.saveString(this, ConsUser.USERCODE, userInfo.getUsercode()); + SPUtils.saveString(this, ConsUser.NICKNAME, userInfo.getNickname()); + SPUtils.saveInt(this, ConsUser.TYPE, userInfo.getUser_type()); + SPUtils.saveString(this, ConsUser.MOBILE, userInfo.getMobile()); + SPUtils.saveString(this, ConsUser.AVATAR, userInfo.getAvatar()); + SPUtils.saveInt(this, ConsUser.GENDER, userInfo.getGender()); + SPUtils.saveInt(this, ConsUser.AGE, userInfo.getAge()); + SPUtils.saveString(this, ConsUser.BIRTHDAY, userInfo.getBirthday()); + SPUtils.saveString(this, ConsUser.CITY, userInfo.getCity()); + SPUtils.saveInt(this, ConsUser.FINISH_STATUS, userInfo.getFinish_status()); + SPUtils.saveString(this, ConsUser.IM_TOKEN, userInfo.getIm_token()); + SPUtils.saveInt(this, ConsUser.IS_ANCHOR, userInfo.getIs_anchor()); + SPUtils.saveInt(this, ConsUser.IS_FACE_STATUS, userInfo.getIs_face_status()); + SPUtils.saveString(this, ConsUser.INVITE_CODE, userInfo.getInvite_code()); + SPUtils.saveString(this, ConsUser.TOKEN, userInfo.getToken()); + SPUtils.saveInt(this, ConsUser.USER_ID, userInfo.getUser_id()); + +// SPUtils.saveString(this, userInfo.getUser_id() + "", userInfo.getCity()); + + } + + /** + * 默认美颜参数 + */ + public void setDefaultBeautySetting() { + BeautySPUtils.saveFloat("sSkinDetect", 1.0f); + BeautySPUtils.saveFloat("sHeavyBlur", 0.0f); + BeautySPUtils.saveFloat("sHeavyBlurLevel", 0.6f); + BeautySPUtils.saveFloat("sBlurLevel", 0.4f); + BeautySPUtils.saveFloat("sColorLevel", 0.8f); + BeautySPUtils.saveFloat("sRedLevel", 0.9f); + BeautySPUtils.saveFloat("sEyeBright", 0.2f); + BeautySPUtils.saveFloat("sToothWhiten", 1.0f); + BeautySPUtils.saveFloat("sFaceShape", 0.0f); + BeautySPUtils.saveFloat("sEyeEnlarging", 0.4f); + BeautySPUtils.saveFloat("sEyeEnlargingOld", 0.9f); + BeautySPUtils.saveFloat("sCheekThinning", 0.4f); + BeautySPUtils.saveFloat("sCheekThinningOld", 0.8f); + BeautySPUtils.saveFloat("sIntensityChin", 0.3f); + BeautySPUtils.saveFloat("sIntensityForehead", 0.3f); + BeautySPUtils.saveFloat("sIntensityNose", 0.7f); + BeautySPUtils.saveFloat("sIntensityMouth", 0.4f); + BeautySPUtils.saveString("filter", "danya"); + BeautySPUtils.saveFloat("filterLevel", 0.4f); + BeautySPUtils.saveBoolean("isSet", false); + BeautySPUtils.saveBoolean("isClose", false); + } + + public static SessionCustomization getP2pCustomization() { + p2pCustomization = new SessionCustomization(); + // // 定制ActionBar右边的按钮,可以加多个 + ArrayList buttons = new ArrayList<>(); + SessionCustomization.OptionsButton cloudMsgButton = new SessionCustomization.OptionsButton() { + @Override + public void onClick(Context context, View view, String sessionId) { + if (!TextUtils.isEmpty(sessionId)) { + //跳转到个人中心 +// Intent intent = new Intent(context, MainPageActivity.class); +// intent.putExtra("userId", Integer.valueOf(sessionId)); +// context.startActivity(intent); + Intent intent = new Intent(context, ChatSettingActivity.class); + intent.putExtra("userId", Integer.valueOf(sessionId)); + context.startActivity(intent); + } else { + MaleToast.showFailureMsg(context, "请重试"); + } + + } + }; + cloudMsgButton.iconId = R.drawable.ic_im_details; + + buttons.add(cloudMsgButton); + p2pCustomization.buttons = buttons; + return p2pCustomization; + } + + private static SessionCustomization p2pCustomization; + + private FirstChargeGiftDialog dialog; + + /** + * 首充、快捷弹窗 + * + * @param activity + */ + public void getRechargeInfo(BaseActivity activity, int type) { + if (UserManager.getUserInfo().getGender() == 2 && activity != null) { + if (!StorageManager.getInstance(activity).getBoolean(Constans.IS_SHOW_DIALOG, false)) { + SettingManager.getRechargeInfo(activity, 2, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RechargeListBean result, String message) { + if (result != null) { + StorageManager.getInstance(activity).putBoolean(Constans.IS_SHOW_DIALOG, true); + StorageManager.getInstance(activity).putInt(Constans.IS_FIRST_RECHARGE, result.getIs_first_recharge()); + // 1=已经首充过、0=没有首充过 + if (result.getIs_first_recharge() == 0) { + if (result.getGift_bag_list() != null && result.getGift_bag_list().size() > 2) { + dialog = new FirstChargeGiftDialog(activity, result.getGift_bag_list(), result.getShow_wx_pay_type(), result.getShow_alipay_pay_type()); + dialog.setCanceledOnTouchOutside(false); + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + StorageManager.getInstance(activity).putBoolean(Constans.IS_SHOW_DIALOG, false); +// if (!SPUtils.getBoolean(activity, ConsUser.USER_VIP, false) && type == 1) { +// VipGuideDialog dialog1 = new VipGuideDialog(activity); +// dialog1.show(); +// } + } + }); + dialog.show(); + } + } else { +// if (!SPUtils.getBoolean(activity, ConsUser.USER_VIP, false) && type == 1) { +// VipGuideDialog dialog1 = new VipGuideDialog(activity); +// dialog1.show(); +// } else { + Intent intent = new Intent(activity, QuickRechargeActivity.class); + activity.startActivity(intent); +// } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } else { +// if (!SPUtils.getBoolean(activity, ConsUser.USER_VIP, false) && type == 1) { +// VipGuideDialog dialog1 = new VipGuideDialog(activity); +// dialog1.show(); +// } else { + Intent intent = new Intent(activity, QuickRechargeActivity.class); + activity.startActivity(intent); +// } + } + } + } + + public void setDismissDialog() { + if (dialog != null && dialog.isShowing()) { + dialog.dismiss(); +// StorageManager.getInstance(this).putBoolean(Constans.IS_SHOW_DIALOG, false); + } + } + + public boolean showCertificationDialog(Context mContext) { + if ((UserManager.getUserInfo().getIs_anchor() != 1 || UserManager.getUserInfo().getIs_face_status() != 1) && UserManager.getUserInfo().isWomen()) { + if (StorageManager.getInstance(mContext).getInt(Constans.SHOW_CER_DIALOG, 0) == 0) { + GirlAuthDialog dialog = new GirlAuthDialog(mContext); + dialog.show(); + StorageManager.getInstance(mContext).putInt(Constans.SHOW_CER_DIALOG, 1); + return true; + } else { + StorageManager.getInstance(mContext).putInt(Constans.SHOW_CER_DIALOG, 0); + return false; + } + } else { + return false; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseWebSocket.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseWebSocket.java new file mode 100644 index 0000000..a6b7ae4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseWebSocket.java @@ -0,0 +1,158 @@ +package com.fengliyan.tianlesue.view.base; + +import android.os.Handler; +import android.util.Log; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; + +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; +import okio.ByteString; + +/** + * ying 2021/1/26 + * Describe : + */ + +public class BaseWebSocket extends WebSocketListener { + private static final String TAG = "MyWebSocket"; + private final MyWebSocketListener mListener; + private WebSocket mSocket; + Handler mHandler = new Handler(); + Runnable mHeartbeatRunnable = new Runnable() { + + @Override + public void run() { + sedText("{\"type\":\"Heartbeat\"}"); + heartbeat(); + } + }; + + JsonParser mJsonParser = new JsonParser(); + int connectSize = 5;//重连次数 + int connectindex; + + public BaseWebSocket(MyWebSocketListener listener) { + mListener = listener; + connect(); + } + + public void connect() { + OkHttpClient httpclient = new OkHttpClient.Builder() + .readTimeout(3, TimeUnit.SECONDS)//设置读取超时时间 + .writeTimeout(3, TimeUnit.SECONDS)//设置写的超时时间 + .connectTimeout(3, TimeUnit.SECONDS)//设置连接超时时间 + .build(); + Request request = new Request.Builder().url(ConstUrl.WEBSOCKTURL).build(); + httpclient.newWebSocket(request, this); + httpclient.dispatcher().executorService().shutdown(); //清除并关闭线程池 + } + + //心跳 + public void heartbeat() { + mHandler.postDelayed(mHeartbeatRunnable, 20000); + } + + public void close() { + if (mSocket != null) { + mSocket.cancel(); + mSocket.close(1001, "close"); + mSocket = null; + } + } + + public void sedText(String text) { + if (mSocket != null) + mSocket.send(text); + } + + public void sedText(final String text, int delay) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + sedText(text); + } + }, delay); + } + + @Override + public void onOpen(WebSocket webSocket, Response response) { + super.onOpen(webSocket, response); + mSocket = webSocket; + connectindex = 0; + if (ConstUrl.LOGDEBUG) Log.i(TAG, ConstUrl.WEBSOCKTURL+"连接成功"); + heartbeat(); + } + + @Override + public void onMessage(WebSocket webSocket, ByteString bytes) { + super.onMessage(webSocket, bytes); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "接收 bytes:" + bytes.hex()); + } + + @Override + public void onMessage(WebSocket webSocket, String text) { + super.onMessage(webSocket, text); +// if (ConstUrl.LOGDEBUG) Log.i(TAG, "接收 text:" + text); + + JsonElement parse = mJsonParser.parse(text); + if (parse.isJsonObject()) { + JsonObject asJsonObject = parse.getAsJsonObject(); + final String type = asJsonObject.get("type").getAsString(); + if (type.equals("Heartbeat")) return; + final String data = asJsonObject.get("data").getAsJsonObject().toString(); + mHandler.post(new Runnable() { + @Override + public void run() { + mListener.onMessageListener(type, data); + } + }); + + } + } + + @Override + public void onClosed(WebSocket webSocket, int code, String reason) { + super.onClosed(webSocket, code, reason); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "关闭:" + reason); + } + + @Override + public void onClosing(WebSocket webSocket, int code, String reason) { + super.onClosing(webSocket, code, reason); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "结束:" + reason); + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + super.onFailure(webSocket, t, response); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "失败:response---------->" + t.toString()); + reconnection(); + } + + //重连 + private void reconnection() { + ++connectindex; + if (connectindex < connectSize) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + connect(); + } + }, 60000); + } + } + + public interface MyWebSocketListener { + void onMessageListener(String type, String data); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseWebViewActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseWebViewActivity.java new file mode 100644 index 0000000..d8cb947 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/BaseWebViewActivity.java @@ -0,0 +1,132 @@ +package com.fengliyan.tianlesue.view.base; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Build; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.webkit.ConsoleMessage; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ProgressBar; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.settings.MyItemsActivity; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by chenqihong on 2017/3/20. + */ + +public class BaseWebViewActivity extends BaseActivity { + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_webview); + String url = getIntent().getStringExtra("ClickUrl"); + if (!TextUtils.isEmpty(DeviceManager.getInstance().getToken())) { + if (url.contains("?")) { + url = url + "&token=" + DeviceManager.getInstance().getToken(); + } else { + url = url + "?token=" + DeviceManager.getInstance().getToken(); + } + } + if (BuildConfig.IS_DEV) { + Log.i("TAG", "onCreate: url---------->" + url); + } + final ProgressBar progressBar = (ProgressBar) findViewById(R.id.webview_progress); + final WebView webView = (WebView) findViewById(R.id.webview_view); + getCustomTitle().dismissBottomLine(); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); + } + webView.getSettings().setBlockNetworkImage(false); + webView.getSettings().setJavaScriptEnabled(true); + //设置自适应屏幕,两者合用 + webView.getSettings().setUseWideViewPort(true); //将图片调整到适合webview的大小 + webView.getSettings().setLoadWithOverviewMode(true); // 缩放至屏幕的大小 + // 开启 DOM storage API 功能 + webView.getSettings().setDomStorageEnabled(true); + // 开启 database storage API 功能 + webView.getSettings().setDatabaseEnabled(true); + // 设置可以访问文件 + webView.getSettings().setAllowFileAccess(true); + webView.setWebChromeClient(new WebChromeClient() { + @Override + public void onProgressChanged(WebView view, int newProgress) { + super.onProgressChanged(view, newProgress); + progressBar.setProgress(newProgress); + if (newProgress == 100) { + progressBar.setVisibility(View.GONE); + } + + } + + @Override + public boolean onConsoleMessage(ConsoleMessage consoleMessage) { + String msg = consoleMessage.message();// Javascript输入的Log内容 + if (ConstUrl.LOGDEBUG) Log.i("info", " msg ---------------> " + msg); + if (!TextUtils.isEmpty(msg)) { + try { + JSONObject json = new JSONObject(msg); + if (ConstUrl.LOGDEBUG) + Log.i("info", " json.get(fun) ---------------> " + json.get("fun")); + String fun = (String) json.get("fun"); + int param1 = 0; + String param2 = ""; + if (TextUtils.equals(fun, "HomePage")) { + param1 = (int) json.get("userId"); + showHomePage(param1); + } else if (TextUtils.equals(fun, "TurntableCoupon")) { + showRedCoupon(); + } + + } catch (JSONException | ClassCastException e) { + e.printStackTrace(); + } + } + return super.onConsoleMessage(consoleMessage); + } + }); + + webView.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + setTitleName(webView.getTitle()); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + + } + }); + webView.loadUrl(url); + } + + /** + * 跳转个人主页 + * + * @param userId 用户id + */ + public void showHomePage(int userId) { + Intent intent = new Intent(this, MainPageActivity.class); + intent.putExtra("userId", userId); + startActivity(intent); + } + + public void showRedCoupon() { + Intent intent = new Intent(this, MyItemsActivity.class); + startActivity(intent); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/PayWebViewActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/PayWebViewActivity.java new file mode 100644 index 0000000..173eaf3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/PayWebViewActivity.java @@ -0,0 +1,170 @@ +package com.fengliyan.tianlesue.view.base; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.webkit.ConsoleMessage; +import android.webkit.WebChromeClient; +import android.webkit.WebResourceRequest; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ProgressBar; + +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.utils.PayUtils; +import com.fengliyan.uikit.toast.MaleToast; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +import java.io.File; +import java.net.URISyntaxException; + +/** + * Created by chenqihong on 2017/3/20. + */ + +public class PayWebViewActivity extends BaseActivity { + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_webview); + String url = getIntent().getStringExtra("ClickUrl"); + int type = getIntent().getIntExtra("type", 4); + if (BuildConfig.IS_DEV) { + Log.i("TAG", "onCreate: url---------->" + url); + } + final ProgressBar progressBar = (ProgressBar) findViewById(R.id.webview_progress); + final WebView webView = (WebView) findViewById(R.id.webview_view); + getCustomTitle().dismissBottomLine(); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); + } + webView.getSettings().setBlockNetworkImage(false); + webView.getSettings().setJavaScriptEnabled(true); + //设置自适应屏幕,两者合用 + webView.getSettings().setUseWideViewPort(true); //将图片调整到适合webview的大小 + webView.getSettings().setLoadWithOverviewMode(true); // 缩放至屏幕的大小 + // 开启 DOM storage API 功能 + webView.getSettings().setDomStorageEnabled(true); + // 开启 database storage API 功能 + webView.getSettings().setDatabaseEnabled(true); + // 设置可以访问文件 + webView.getSettings().setAllowFileAccess(true); + webView.setWebChromeClient(new WebChromeClient() { + @Override + public void onProgressChanged(WebView view, int newProgress) { + super.onProgressChanged(view, newProgress); + progressBar.setProgress(newProgress); + if (newProgress == 100) { + progressBar.setVisibility(View.GONE); + } + } + + @Override + public boolean onConsoleMessage(ConsoleMessage consoleMessage) { + String msg = consoleMessage.message();// Javascript输入的Log内容 + if (ConstUrl.LOGDEBUG) Log.i("info", " msg ---------------> " + msg); + return super.onConsoleMessage(consoleMessage); + } + }); + + webView.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + setTitleName(webView.getTitle()); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + String url = request.getUrl().toString(); + if (ConstUrl.LOGDEBUG) + Log.e("TAG", "shouldOverrideUrlLoading: url---------->" + url); + if (ConstUrl.LOGDEBUG) + Log.e("TAG", "shouldOverrideUrlLoading: url---------->" + PayUtils.parseScheme(url)); + + if (url.startsWith("tel:")) { + Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + return true; + } + + // 如下方案可在非微信内部WebView的H5页面中调出微信支付 + if (url.startsWith("weixin://")) { + IWXAPI api = WXAPIFactory.createWXAPI(PayWebViewActivity.this, null); + api.registerApp(Constant.WECHAT_APP_ID); + if (PayUtils.isWeChatAppInstalled(PayWebViewActivity.this, api)) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + startActivity(intent); + finish(); + } else { + MaleToast.showMessage(PayWebViewActivity.this, "您还未安装微信客户端"); + } + return true; + } else if (PayUtils.parseScheme(url)) { + try { + Intent intent; + intent = Intent.parseUri(url, + Intent.URI_INTENT_SCHEME); + intent.addCategory("android.intent.category.BROWSABLE"); + intent.setComponent(null); + // intent.setSelector(null); + startActivity(intent); + finish(); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + } else if (url.startsWith("androidamap://")) { + try { + Intent localIntent = Intent.getIntent(url); + if (isInstallByread("com.autonavi.minimap")) { + startActivity(localIntent); + return true; + } + MaleToast.showMessage(PayWebViewActivity.this, "您还没有安装高德地图客户端"); + } catch (URISyntaxException localURISyntaxException) { + localURISyntaxException.printStackTrace(); + } + } else if (url.startsWith("baidumap://map")) { + try { + Intent localIntent = Intent.getIntent(url); + if (isInstallByread("com.baidu.BaiduMap")) { + startActivity(localIntent); + return true; + } + MaleToast.showMessage(PayWebViewActivity.this, "您还没有安装百度地图客户端"); + } catch (URISyntaxException localURISyntaxException) { + localURISyntaxException.printStackTrace(); + } + } + return false; + } + }); + if (type == 4) { + webView.loadData(url, "text/html", "utf-8"); + } else { + webView.loadUrl(url); + } + } + + private boolean isInstallByread(String paramString) { + return new File("/data/data/" + paramString).exists(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/RefreshFrameLayout.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/RefreshFrameLayout.java new file mode 100644 index 0000000..7d9e4b1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/RefreshFrameLayout.java @@ -0,0 +1,96 @@ +package com.fengliyan.tianlesue.view.base; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ListView; + +import in.srain.cube.views.ptr.PtrClassicFrameLayout; +import in.srain.cube.views.ptr.PtrDefaultHandler; +import in.srain.cube.views.ptr.PtrFrameLayout; + +/** + * Created by abby on 2016/12/18. + */ + +public class RefreshFrameLayout extends PtrClassicFrameLayout { + + private RefreshBeginListener mListener; + + private ListView mListView; + + public interface RefreshBeginListener{ + void onRefreshBegin(); + } + + public void setRefreshBeginListener(RefreshBeginListener listener){ + this.mListener = listener; + } + + public void setCheckRefreshListView(ListView listView){ + this.mListView = listView; + } + + public RefreshFrameLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setPtrHandler(new PtrDefaultHandler() { + @Override + public void onRefreshBegin(PtrFrameLayout frame) { + refreshComplete(); + if(null != mListener) { + mListener.onRefreshBegin(); + } + } + + @Override + public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { + + // here check $mListView instead of $content + return PtrDefaultHandler.checkContentCanBePulledDown(frame, mListView, header); + } + }); + + } + + public RefreshFrameLayout(Context context) { + super(context); + setPtrHandler(new PtrDefaultHandler() { + @Override + public void onRefreshBegin(PtrFrameLayout frame) { + refreshComplete(); + if(null != mListener) { + mListener.onRefreshBegin(); + } + } + + @Override + public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { + + // here check $mListView instead of $content + return PtrDefaultHandler.checkContentCanBePulledDown(frame, mListView, header); + } + }); + } + + public RefreshFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + setPtrHandler(new PtrDefaultHandler() { + @Override + public void onRefreshBegin(PtrFrameLayout frame) { + refreshComplete(); + if(null != mListener) { + mListener.onRefreshBegin(); + } + } + + @Override + public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { + + // here check $mListView instead of $content + return PtrDefaultHandler.checkContentCanBePulledDown(frame, mListView, header); + } + }); + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/SpeedWebSocket.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/SpeedWebSocket.java new file mode 100644 index 0000000..792802e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/SpeedWebSocket.java @@ -0,0 +1,198 @@ +package com.fengliyan.tianlesue.view.base; + +import android.app.Activity; +import android.os.Handler; +import android.util.Log; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.view.luck.SpeedDatingActivity; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; +import okio.ByteString; + +public class SpeedWebSocket extends WebSocketListener { + private static final String TAG = "SpeedWebSocket"; + private static volatile SpeedWebSocket instance; + private WebSocket mSocket; + private SpeedWebSocketListener mListener; + Handler mHandler = new Handler(); + + private Disposable heartbeatDisposable; + int connectSize = 30;//重连次数 + int connectindex; + private String socketUrl; + private boolean isReconnect = false; + + public static SpeedWebSocket getInstance() { + if (instance == null) { + synchronized (SpeedWebSocket.class) { + if (instance == null) { + instance = new SpeedWebSocket(); + } + } + } + return instance; + } + + public void connect() { + OkHttpClient httpclient = new OkHttpClient.Builder() + .readTimeout(3, TimeUnit.SECONDS)//设置读取超时时间 + .writeTimeout(3, TimeUnit.SECONDS)//设置写的超时时间 + .connectTimeout(3, TimeUnit.SECONDS)//设置连接超时时间 + .build(); + //重连后端需要清除速配状态 + if (isReconnect) { + Activity activity = BaseApplication.getInstance().getTopActivity(); + if (activity != null) { + if (activity instanceof SpeedDatingActivity) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "connect: ((SpeedDatingActivity) activity).getSpeedType()----------->" + ((SpeedDatingActivity) activity).getSpeedType()); + socketUrl = ConstUrl.SOCKET_SPEED_DATE + DeviceManager.getInstance().getToken() + "&isInSpeedView=1&callType=" + ((SpeedDatingActivity) activity).getSpeedType(); + } else { + socketUrl = ConstUrl.SOCKET_SPEED_DATE + DeviceManager.getInstance().getToken() + "&isInSpeedView=0"; + } + } + } else { + socketUrl = ConstUrl.SOCKET_SPEED_DATE + DeviceManager.getInstance().getToken(); + } + if (ConstUrl.LOGDEBUG) Log.i(TAG, "connect: " + socketUrl); + isReconnect = false; + Request request = new Request.Builder().url(socketUrl).build(); + httpclient.newWebSocket(request, this); + httpclient.dispatcher().executorService().shutdown(); //清除并关闭线程池 + } + + //心跳 + public void heartbeat() { + if (heartbeatDisposable == null) { + heartbeatDisposable = Observable.interval(20, TimeUnit.SECONDS).subscribe(new Consumer() { + @Override + public void accept(Long aLong) throws Exception { + sedText("{\"method\":\"heartbeat\"}"); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "开启延时发送心跳任务"); + } + }); + } + } + + public void stopHeartBeat() { + if (heartbeatDisposable != null) { + heartbeatDisposable.dispose(); + heartbeatDisposable = null; + } + } + + public void sedText(String text) { + if (mSocket != null) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "sedText: text----------->" + text); + mSocket.send(text); + } + } + + public void close() { + if (mSocket != null) { + sedText("{\"method\":\"onlineTimeStop\"}"); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "sedText: close----------->"); + mSocket.cancel(); + mSocket.close(1001, "close"); + mSocket = null; + } + } + + @Override + public void onOpen(WebSocket webSocket, Response response) { + super.onOpen(webSocket, response); + mSocket = webSocket; + connectindex = 0; + if (ConstUrl.LOGDEBUG) Log.i(TAG, "连接成功"); + heartbeat(); + sedText("{\"method\":\"onlineTimeStart\"}"); + } + + @Override + public void onMessage(WebSocket webSocket, String text) { + super.onMessage(webSocket, text); + text = text.replaceAll("@@", ""); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "接收 text:" + text); + try { + JSONObject object = JSON.parseObject(text); + int code = object.getInteger("code"); + String method = object.getString("method"); + String data = object.getString("data"); + String message = object.getString("message"); + if (method.equals("heartbeat")) return; + mHandler.post(new Runnable() { + @Override + public void run() { + mListener.onMessageListener(code, method, data, message); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onMessage(WebSocket webSocket, ByteString bytes) { + super.onMessage(webSocket, bytes); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "接收 bytes:" + bytes.hex()); + } + + @Override + public void onClosing(WebSocket webSocket, int code, String reason) { + super.onClosing(webSocket, code, reason); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "结束:" + reason); + stopHeartBeat(); + } + + @Override + public void onClosed(WebSocket webSocket, int code, String reason) { + super.onClosed(webSocket, code, reason); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "关闭:" + reason); + stopHeartBeat(); + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + super.onFailure(webSocket, t, response); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "失败:" + t.toString() + response); + stopHeartBeat(); + if (mSocket != null) { + reconnection(); + } + } + + //重连 + private void reconnection() { + if (connectindex <= connectSize) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "重连"); + isReconnect = true; + connect(); + connectindex++; + } + }, 20000); + } + } + + public void setListener(SpeedWebSocketListener listener) { + this.mListener = listener; + } + + public interface SpeedWebSocketListener { + void onMessageListener(int code, String type, String data, String msg); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/UserStatisticsWebSocket.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/UserStatisticsWebSocket.java new file mode 100644 index 0000000..226c949 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/UserStatisticsWebSocket.java @@ -0,0 +1,157 @@ +package com.fengliyan.tianlesue.view.base; + +import android.os.Handler; +import android.util.Log; + +import com.google.gson.JsonParser; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; +import okio.ByteString; + +/** + * ying 2021/1/26 + * Describe : + */ + +public class UserStatisticsWebSocket extends WebSocketListener { + private static final String TAG = "UserStatisticsWebSocket"; + private final MyWebSocketListener mListener; + private WebSocket mSocket; + private String heartbeatContent = ""; + Handler mHandler = new Handler(); + private Disposable heartbeatDisposable; + + JsonParser mJsonParser = new JsonParser(); + int connectSize = 5;//重连次数 + int connectindex; + + public UserStatisticsWebSocket(MyWebSocketListener listener) { + mListener = listener; + connect(); + } + + public void connect() { + OkHttpClient httpclient = new OkHttpClient.Builder() + .readTimeout(6, TimeUnit.SECONDS)//设置读取超时时间 + .writeTimeout(6, TimeUnit.SECONDS)//设置写的超时时间 + .connectTimeout(6, TimeUnit.SECONDS)//设置连接超时时间 + .build(); + LoginBean loginBean = (LoginBean) StorageManager.getInstance(BaseApplication.getInstance()).getBean("loginBean", LoginBean.class); + int userId = 0; + if (loginBean != null && loginBean.getUserinfo() != null) { + userId = loginBean.getUserinfo().getUser_id(); + } + String url = String.format("%s%d", ConstUrl.DEBUG ? ConstUrl.SOCKET_USERSTATIS_DEBUG : ConstUrl.SOCKET_USERSTATIS, userId); + Request request = new Request.Builder().url(url).build(); + httpclient.newWebSocket(request, this); + httpclient.dispatcher().executorService().shutdown(); //清除并关闭线程池 + } + + + public void close() { + if (mSocket != null) { + mSocket.cancel(); + mSocket.close(1001, "close"); + mSocket = null; + } + } + + void stopHeartBeat() { + if (heartbeatDisposable != null) { + heartbeatDisposable.dispose(); + } + } + + void startHeartBeat() { + heartbeatDisposable = Observable.interval(30, TimeUnit.SECONDS).subscribe(new Consumer() { + @Override + public void accept(Long aLong) throws Exception { + mSocket.send(heartbeatContent); + } + }); + } + + public void sedText(String text) { + if (mSocket != null) + mSocket.send(text); + } + + @Override + public void onOpen(WebSocket webSocket, Response response) { + super.onOpen(webSocket, response); + mSocket = webSocket; + connectindex = 0; +// Log.i(TAG, "连接成功"); + startHeartBeat(); + } + + @Override + public void onMessage(WebSocket webSocket, ByteString bytes) { + super.onMessage(webSocket, bytes); +// Log.i(TAG, "接收 bytes:" + bytes.hex()); + } + + @Override + public void onMessage(WebSocket webSocket, String text) { + super.onMessage(webSocket, text); + if (heartbeatContent.isEmpty()) { + heartbeatContent = text; + } +// Log.i(TAG, "接收 text:" + text); + } + + @Override + public void onClosed(WebSocket webSocket, int code, String reason) { + super.onClosed(webSocket, code, reason); +// Log.i(TAG, "关闭:" + reason); + stopHeartBeat(); + } + + @Override + public void onClosing(WebSocket webSocket, int code, String reason) { + super.onClosing(webSocket, code, reason); +// Log.i(TAG, "结束:" + reason); + stopHeartBeat(); + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + super.onFailure(webSocket, t, response); +// Log.i(TAG, "失败:" ); + stopHeartBeat(); + if (mSocket != null) { + reconnection(); + } + } + + //重连 + private void reconnection() { + if (connectindex <= connectSize) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "重连"); + connect(); + connectindex++; + } + }, 60000); + } + } + + public interface MyWebSocketListener { + void onMessageListener(String type, String data); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ActionSheetDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ActionSheetDialog.java new file mode 100644 index 0000000..95c1b91 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ActionSheetDialog.java @@ -0,0 +1,211 @@ +package com.fengliyan.tianlesue.view.base.utils; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.view.Display; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ScrollView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; + +import java.util.ArrayList; +import java.util.List; + +public class ActionSheetDialog { + + private Context context; + private Dialog dialog; + private TextView txt_title; + private TextView txt_cancel; + private LinearLayout lLayout_content; + private ScrollView sLayout_content; + private boolean showTitle = false; + private List sheetItemList; + private Display display; + + public ActionSheetDialog(Context context) { + + this.context = context; + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + display = windowManager.getDefaultDisplay(); + } + + public ActionSheetDialog builder() { + + View view = LayoutInflater.from(context).inflate(R.layout.view_actionsheet, null); + + view.setMinimumWidth(display.getWidth()); + + + sLayout_content = (ScrollView) view.findViewById(R.id.sLayout_content); + lLayout_content = (LinearLayout) view.findViewById(R.id.lLayout_content); + txt_title = (TextView) view.findViewById(R.id.txt_title); + txt_cancel = (TextView) view.findViewById(R.id.txt_cancel); + txt_cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + + dialog = new Dialog(context, R.style.ActionSheetDialogStyle); + dialog.setContentView(view); + Window dialogWindow = dialog.getWindow(); + dialogWindow.setGravity(Gravity.LEFT | Gravity.BOTTOM); + WindowManager.LayoutParams lp = dialogWindow.getAttributes(); + lp.x = 0; + lp.y = 0; + dialogWindow.setAttributes(lp); + + return this; + } + + public ActionSheetDialog setTitle(String title) { + showTitle = true; + txt_title.setVisibility(View.VISIBLE); + txt_title.setText(title); + return this; + } + + public ActionSheetDialog setCancelable(boolean cancel) { + dialog.setCancelable(cancel); + return this; + } + + public ActionSheetDialog setCanceledOnTouchOutside(boolean cancel) { + dialog.setCanceledOnTouchOutside(cancel); + return this; + } + + public ActionSheetDialog addSheetItem(String strItem, SheetItemColor color, + OnSheetItemClickListener listener) { + if (sheetItemList == null) { + sheetItemList = new ArrayList(); + } + sheetItemList.add(new SheetItem(strItem, color, listener)); + return this; + } + + public void show() { + setSheetItems(); + dialog.show(); + } + + private void setSheetItems() { + if (sheetItemList == null || sheetItemList.size() <= 0) { + return; + } + + int size = sheetItemList.size(); + + + if (size >= 7) { + LayoutParams params = (LayoutParams) sLayout_content.getLayoutParams(); + params.height = display.getHeight() / 2; + sLayout_content.setLayoutParams(params); + } + + for (int i = 1; i <= size; i++) { + final int index = i; + SheetItem sheetItem = sheetItemList.get(i - 1); + String strItem = sheetItem.name; + SheetItemColor color = sheetItem.color; + final OnSheetItemClickListener listener = (OnSheetItemClickListener) sheetItem.itemClickListener; + + TextView textView = new TextView(context); + textView.setText(strItem); + textView.setTextSize(18); + textView.setGravity(Gravity.CENTER); + + if (size == 1) { + if (showTitle) { + textView.setBackgroundResource(R.drawable.actionsheet_bottom_selector); + } else { + textView.setBackgroundResource(R.drawable.actionsheet_single_selector); + } + } else { + if (showTitle) { + if (i >= 1 && i < size) { + textView.setBackgroundResource(R.drawable.actionsheet_middle_selector); + } else { + textView.setBackgroundResource(R.drawable.actionsheet_bottom_selector); + } + } else { + if (i == 1) { + textView.setBackgroundResource(R.drawable.actionsheet_top_selector); + } else if (i < size) { + textView.setBackgroundResource(R.drawable.actionsheet_middle_selector); + } else { + textView.setBackgroundResource(R.drawable.actionsheet_bottom_selector); + } + } + } + + if (color == null) { + textView.setTextColor(Color.parseColor(SheetItemColor.Blue.getName())); + } else { + textView.setTextColor(Color.parseColor(color.getName())); + } + + float scale = context.getResources().getDisplayMetrics().density; + int height = (int) (45 * scale + 0.5f); + textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, height)); + + textView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + listener.onClick(index); + dialog.dismiss(); + } + }); + + lLayout_content.addView(textView); + } + } + + public enum SheetItemColor { + Blue("#037BFF"), + Red("#FD4A2E"); + + private String name; + + private SheetItemColor(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public interface OnSheetItemClickListener { + void onClick(int which); + } + + public class SheetItem { + String name; + OnSheetItemClickListener itemClickListener; + SheetItemColor color; + + public SheetItem(String name, SheetItemColor color, OnSheetItemClickListener itemClickListener) { + this.name = name; + this.color = color; + this.itemClickListener = itemClickListener; + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/AppStatusCallbacks.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/AppStatusCallbacks.java new file mode 100644 index 0000000..6020a6f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/AppStatusCallbacks.java @@ -0,0 +1,111 @@ +package com.fengliyan.tianlesue.view.base.utils; + +import android.app.Activity; +import android.app.Application; +import android.content.Context; +import android.os.Bundle; + +import com.fengliyan.tianlesue.controller.eventBus.ActiveUpdateEvent; + +import de.greenrobot.event.EventBus; + +public class AppStatusCallbacks implements Application.ActivityLifecycleCallbacks { + + private static AppStatusCallbacks instance; + public int mAppStatus = AppStatusCallbacks.STATUS_KILLED; + private int mFinalCount; + private boolean isFront = true; + public static final int STATUS_NORMAL = 1; + public static final int STATUS_KILLED = -1; + + public static AppStatusCallbacks init(Application application) { + if (instance == null) { + instance = new AppStatusCallbacks(); + application.registerActivityLifecycleCallbacks(instance); + } + return instance; + } + + public static AppStatusCallbacks get(Application application) { + if (instance == null) { + init(application); + } + return instance; + } + + + public int getmAppStatus() { + return mAppStatus; + } + + public void setmAppStatus(int mAppStatus) { + this.mAppStatus = mAppStatus; + } + + public boolean isFront() { + return isFront; + } + + public void setFront(boolean front) { + isFront = front; + } + + public static AppStatusCallbacks get(Context ctx) { + if (instance == null) { + Context appCtx = ctx.getApplicationContext(); + if (appCtx instanceof Application) { + init((Application) appCtx); + } + throw new IllegalStateException("Foreground is not initialised and " + "cannot obtain the Application object"); + } + return instance; + } + + public static AppStatusCallbacks get() { + return instance; + } + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + } + + @Override + public void onActivityStarted(Activity activity) { + mFinalCount++; //如果mFinalCount ==1,说明是从后台到前台 +// Log.e("onActivityStarted", mFinalCount + ""); + if (mFinalCount == 1) {//说明从后台回到了前台 +// Log.d("nail","回到前台"); + EventBus.getDefault().post(new ActiveUpdateEvent(true)); + setFront(true); + } + } + + @Override + public void onActivityResumed(Activity activity) { + } + + @Override + public void onActivityPaused(Activity activity) { + } + + @Override + public void onActivityStopped(Activity activity) { + mFinalCount--; //如果mFinalCount ==0,说明是前台到后台 +// Log.i("onActivityStopped", mFinalCount + ""); + if (mFinalCount == 0) {//说明从前台回到了后台 +// Log.d("nail","退到后台"); + EventBus.getDefault().post(new ActiveUpdateEvent(false)); + setFront(false); + } + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + } + + @Override + public void onActivityDestroyed(Activity activity) { + } + +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/CountDownTimerHelper.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/CountDownTimerHelper.java new file mode 100644 index 0000000..2be6572 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/CountDownTimerHelper.java @@ -0,0 +1,56 @@ +package com.fengliyan.tianlesue.view.base.utils; + +import android.os.CountDownTimer; + +/** + * Created by abby on 2016/12/19. + */ + +public class CountDownTimerHelper { + public static final long LENGTH_OF_TIME = 60000; + public static final long STEP_OF_TIME = 1000; + private long mLength = LENGTH_OF_TIME; + private long mStep = STEP_OF_TIME; + private CountDownTimer mTimer; + private CountDownTimerListener mListener; + + public interface CountDownTimerListener{ + void onTickEvent(long millisUntilFinished); + void onFinishEvent(); + } + + public CountDownTimerHelper setCountDownTimerListener(CountDownTimerListener listener){ + mListener = listener; + return this; + } + + public CountDownTimerHelper setTime(long length, long step){ + mLength = length; + mStep = step; + return this; + } + + public CountDownTimerHelper build(){ + mTimer = new CountDownTimer(mLength, mStep) { + @Override + public void onTick(long l) { + mListener.onTickEvent(l); + } + + @Override + public void onFinish() { + mListener.onFinishEvent(); + } + }; + + return this; + } + + public void start(){ + mTimer.start(); + } + + public void cancel(){ + mTimer.cancel(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ForegroundCallbacks.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ForegroundCallbacks.java new file mode 100644 index 0000000..6a0f2bd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ForegroundCallbacks.java @@ -0,0 +1,135 @@ +package com.fengliyan.tianlesue.view.base.utils; +import android.app.Activity; +import android.app.Application; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class ForegroundCallbacks implements Application.ActivityLifecycleCallbacks { + + private static final long CHECK_DELAY = 600; + private static ForegroundCallbacks instance; + private boolean foreground = false, paused = true; + private Handler handler = new Handler(); + private List listeners = new CopyOnWriteArrayList<>(); + private Runnable check; + + public static ForegroundCallbacks init(Application application) { + if (instance == null) { + instance = new ForegroundCallbacks(); + application.registerActivityLifecycleCallbacks(instance); + } + return instance; + } + + public static ForegroundCallbacks get(Application application) { + if (instance == null) { + init(application); + } + return instance; + } + + public static ForegroundCallbacks get(Context ctx) { + if (instance == null) { + Context appCtx = ctx.getApplicationContext(); + if (appCtx instanceof Application) { + init((Application) appCtx); + } + throw new IllegalStateException("Foreground is not initialised and " + "cannot obtain the Application object"); + } + return instance; + } + + public static ForegroundCallbacks get() { + return instance; + } + + public boolean isForeground() { + return foreground; + } + + public boolean isBackground() { + return !foreground; + } + + public void addListener(Listener listener) { + listeners.add(listener); + } + + public void removeListener(Listener listener) { + listeners.remove(listener); + } + + @Override + public void onActivityResumed(Activity activity) { + paused = false; + boolean wasBackground = !foreground; + foreground = true; + if (check != null) + handler.removeCallbacks(check); + if (wasBackground) { + for (Listener l : listeners) { + try { + l.onBecameForeground(); + } catch (Exception exc) { + if (ConstUrl.LOGDEBUG) Log.i("ForegroundCallbacks",exc.getMessage()); + } + } + } + } + + @Override + public void onActivityPaused(Activity activity) { + paused = true; + if (check != null) handler.removeCallbacks(check); + handler.postDelayed(check = new Runnable() { + @Override + public void run() { + if (foreground && paused) { + foreground = false; + for (Listener l : listeners) { + try { + l.onBecameBackground(); + } catch (Exception exc) { + if (ConstUrl.LOGDEBUG) Log.i("ForegroundCallbacks",exc.getMessage()); + } + } + } + } + }, CHECK_DELAY); + } + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + } + + @Override + public void onActivityStarted(Activity activity) { + } + + @Override + public void onActivityStopped(Activity activity) { + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + } + + @Override + public void onActivityDestroyed(Activity activity) { + } + + public interface Listener { + public void onBecameForeground(); + + public void onBecameBackground(); + } + +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/HttpUiCallBack.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/HttpUiCallBack.java new file mode 100644 index 0000000..565b902 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/HttpUiCallBack.java @@ -0,0 +1,29 @@ +package com.fengliyan.tianlesue.view.base.utils; + + +import com.fengliyan.tianlesue.view.base.BaseActivity; + +/** + * http请求ui回调刷新的接口 + * Created by yangjinbo on 2016/1/13. + */ +public interface HttpUiCallBack { + + /** + * 成功时,刷新ui的回调 + * @param result 成功数据 + * @param tips + */ + void onSuccess(BaseActivity activity, T result, String tips); + + /** + * 失败时,刷新ui的回调 + */ + void onFailure(BaseActivity activity, String tip); + + /** + * 发生异常时的ui回调 + * @param e 抛出的异常 + */ + void onException(BaseActivity activity, Throwable e); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/HttpUiCallBackBase.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/HttpUiCallBackBase.java new file mode 100644 index 0000000..605271c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/HttpUiCallBackBase.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.view.base.utils; + + +import android.text.TextUtils; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +/** + * http请求ui回调刷新的接口 提取 + * ying 2020.7.7 + */ +public abstract class HttpUiCallBackBase implements HttpUiCallBack { + + private String mException; + + public HttpUiCallBackBase() { + + } + + public HttpUiCallBackBase(String exception) { + mException = exception; + } + + @Override + public void onSuccess(BaseActivity activity, T result, String message) { + onSuccessBase(activity, result,message); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, TextUtils.isEmpty(mException) ? "获取失败" : mException); + } + + + public abstract void onSuccessBase(BaseActivity activity, T result, String tips); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ImageUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ImageUtils.java new file mode 100644 index 0000000..e81ca7d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ImageUtils.java @@ -0,0 +1,127 @@ +package com.fengliyan.tianlesue.view.base.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Created by abby on 2017/7/1. + */ + +public class ImageUtils { + public static String compressImage(Context context, String path, int quality, boolean isInfoEdit) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = false; + options.inPurgeable = true; + options.inInputShareable = true; + if (!isInfoEdit) { + options.inSampleSize = 2; + } else { + options.inSampleSize = 1; + } + + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + Bitmap bitmap = BitmapFactory.decodeFile(path, options); + File original = new File(path); + try { + File cacheFile = new File(context.getCacheDir() + "/" + original.getName()); + compressAndGenImage(bitmap, cacheFile.getAbsolutePath(), quality); + return cacheFile.getAbsolutePath(); + } catch (IOException e) { + return null; + } + } + + /** + * 图片压缩 + * + * @param image + * @param outPath + * @throws IOException + */ + public static void compressAndGenImage(Bitmap image, String outPath, int quality) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + // scale + int options = 100; + // Store the bitmap into output stream(no compress) + image.compress(Bitmap.CompressFormat.JPEG, 100, os);//参数100表示不压缩 + int size = os.toByteArray().length / 1024; + + if (size >= 1000 && size < 2000) { + os.reset();//重置baos即清空baos + image.compress(Bitmap.CompressFormat.JPEG, 30, os); + } else if (size >= 2000 && size < 3000) { + os.reset();//重置baos即清空baos + image.compress(Bitmap.CompressFormat.JPEG, 20, os); + } else if (size >= 3000 && size < 4000) { + os.reset();//重置baos即清空baos + image.compress(Bitmap.CompressFormat.JPEG, 15, os); + } else if (size >= 4000) { + os.reset();//重置baos即清空baos + image.compress(Bitmap.CompressFormat.JPEG, 10, os); + } else { + while (os.toByteArray().length / 1024 > quality) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 + os.reset();//重置baos即清空baos + image.compress(Bitmap.CompressFormat.JPEG, options, os);//这里压缩options%,把压缩后的数据存放到baos中 + if (options > 10) { + options -= 10;//每次都减少10 + } + } + } +// image.compress(Bitmap.CompressFormat.JPEG, options, os); +// Log.d("nail","os---" + os.toByteArray().length / 1024); + + // Generate compressed image file + FileOutputStream fos = new FileOutputStream(outPath); + fos.write(os.toByteArray()); + fos.flush(); + fos.close(); + if (image != null && !image.isRecycled()) { + image.recycle(); + } + } + + public static void showSVGA(Context context, String effect, SVGAImageView svgaImageView) { + if (svgaImageView == null || svgaImageView.getContext() == null) { + return; + } + svgaImageView.stopAnimation(); + svgaImageView.clear(); + + SVGAParser mSVGAParser = SVGAParser.Companion.shareParser(); + mSVGAParser.init(context); + try { + mSVGAParser.decodeFromURL(new URL(ConstUrl.IMAGE_URL + effect), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + if (svgaImageView.getContext() != null) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svgaImageView.setImageDrawable(drawable); + svgaImageView.startAnimation(); + } + } + + @Override + public void onError() { + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/NotificationUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/NotificationUtils.java new file mode 100644 index 0000000..4f2c64f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/NotificationUtils.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.view.base.utils; + +import android.app.AppOpsManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.os.Build; +import android.provider.Settings; + +import androidx.annotation.RequiresApi; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Created by abby on 2017/10/28. + */ + +public class NotificationUtils { + @RequiresApi(api = Build.VERSION_CODES.KITKAT) + public static boolean isNotificationEnabled(Context context) { + + String CHECK_OP_NO_THROW = "checkOpNoThrow"; + String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION"; + + AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + ApplicationInfo appInfo = context.getApplicationInfo(); + String pkg = context.getApplicationContext().getPackageName(); + int uid = appInfo.uid; + + Class appOpsClass = null; + /* Context.APP_OPS_MANAGER */ + try { + appOpsClass = Class.forName(AppOpsManager.class.getName()); + Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, + String.class); + Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION); + + int value = (Integer) opPostNotificationValue.get(Integer.class); + return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED); + + } catch (ClassNotFoundException e) { + + } catch (NoSuchMethodException e) { + + } catch (NoSuchFieldException e) { + + } catch (InvocationTargetException e) { + + } catch (IllegalAccessException e) { + + } + return false; + } + + public static void goToSetNotification(Context context){ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BASE) { + Intent intent = new Intent(Settings.ACTION_SETTINGS); + context.startActivity(intent); + return; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {// 运行系统在5.x环境使用 + Intent intent = new Intent(Settings.ACTION_SETTINGS); + context.startActivity(intent); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/PasswordChecker.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/PasswordChecker.java new file mode 100644 index 0000000..eaff16d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/PasswordChecker.java @@ -0,0 +1,34 @@ +package com.fengliyan.tianlesue.view.base.utils; + +/** + * Created by abby on 2016/12/24. + */ + +public class PasswordChecker { + public static int TYPE_NORMAL = 0; + public static int TYPE_TOO_FEW = 1; + public static int TYPE_ILLEGE_CHAR = 2; + public static int check(String password){ + String availableString = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + if(6 > password.length()){ + return TYPE_TOO_FEW; + } + + for(int i = 0; i < password.length(); i++){ + boolean isSpecial = true; + for(int j = 0; j < availableString.length(); j++){ + if(password.charAt(i) == availableString.charAt(j)){ + isSpecial = false; + break; + } + } + + if(isSpecial){ + return TYPE_ILLEGE_CHAR; + } + } + + return TYPE_NORMAL; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ToolKit.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ToolKit.java new file mode 100644 index 0000000..aaf104c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/ToolKit.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.view.base.utils; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +public class ToolKit { + public static String parseTime(String addTime){ + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long postTime = 0; + long nowTime = 0; + long step = 0; + String showTime = null; + postTime = Long.parseLong(addTime); + nowTime = System.currentTimeMillis(); + step = nowTime - postTime; + + if(step < 1000){ + showTime = "刚刚"; + }else if(step > 1000 && step < 60 * 1000){ + showTime = "刚刚"; + }else if(step > 60 * 1000 && step < 60 * 60 * 1000){ + showTime = step/(60 * 1000) + "分钟前"; + }else if(step > 60 * 60 * 1000 && step < 24 * 60 * 60 * 1000){ + showTime = step/(60 * 60 *1000) + "小时前"; + }else if(step > 24 * 60 * 60 * 1000){ + showTime = step/(24 * 60 * 60 * 1000) + "天前"; + } + + return showTime; + } + + public static String parseFormatTime(String addTime){ + long time = Long.parseLong(addTime); + Date date = new Date(time); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + String ampm = calendar.get(Calendar.HOUR_OF_DAY) < 11? "上午":"下午"; + String current = calendar.get(Calendar.HOUR) + ":" + calendar.get(Calendar.MINUTE); + String finalTime = ampm +current; + return finalTime; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/ErrorTips.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/ErrorTips.java new file mode 100644 index 0000000..85c6d7d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/ErrorTips.java @@ -0,0 +1,95 @@ +package com.fengliyan.tianlesue.view.base.utils.http; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * 错误提示类型 + * Created by yangjinbo on 2016/1/15. + */ +public class ErrorTips { + + /** + * 错误tips的显示类型 + * Created by yangjinbo on 2016/1/12. + */ + public enum ErrorTipsType { + /** + * 默认方式,采用toast方式 + */ + @SerializedName("default") + DEFAULT, + /** + * 使用对话框的形式,需要用户点击确认 + */ + @SerializedName("confirm") + CONFIRM, + /** + * 使用错误页面的形式展示错误消息 + */ + @SerializedName("errorPage") + ERROR_PAGE, + + /** + * 挂牌 + */ + @SerializedName("noticePage") + SYS_MAINTAIN, + } + + /** + * 错误信息内容 + */ + @SerializedName("content") + private String content; + + /** + * 错误信息标题 + */ + @SerializedName("title") + private String title; + + /** + * 错误信息按钮文字 + */ + @SerializedName("button") + private String button; + + /** + * 错误显示类型 + */ + @Expose + private ErrorTipsType type; + + public String getContent() { + return content; + } + + public String getTitle() { + return title; + } + + public String getButton() { + return button; + } + + public ErrorTipsType getType() { + return type; + } + + public void setContent(String content) { + this.content = content; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setButton(String button) { + this.button = button; + } + + public void setType(ErrorTipsType type) { + this.type = type; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpRequest.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpRequest.java new file mode 100644 index 0000000..e05838c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpRequest.java @@ -0,0 +1,403 @@ +package com.fengliyan.tianlesue.view.base.utils.http; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.http.httprequest.HttpException; +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.HttpRequestFactory; +import com.fengliyan.http.httprequest.RequestParameter; +import com.fengliyan.http.httprequest.TType; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.utils.AESUtils; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.List; + +/** + * 封装http请求的类,可以用于一般的post,get。上传下载不能使用 + * 通过{@link HttpRequest.Builder}创建 + * Created by yangjinbo on 2016/1/13. + */ +public class HttpRequest { + + private static final String TAG = HttpRequest.class.getSimpleName(); + + private RequestParameter mParams; + + private HttpMethod mHttpMethod; + + private String mUrl; + + private String mExt; + + private TType> mResultType; + + private boolean mCacheEnable = true; + + private UploadFile[] mUploadFiles; + + private HttpRequest(Builder builder) { + mHttpMethod = builder.mHttpMethod; + mParams = builder.mParams; + mUploadFiles = builder.mUploadFiles; + mUrl = builder.mUrl; + mResultType = builder.mResultType; + mCacheEnable = builder.mCacheEnable; + mExt = builder.mExt; + } + + + public HttpMethod getHttpMethod() { + return mHttpMethod; + } + + public String getUrl() { + return mUrl; + } + + public String getExt() { + return mExt; + } + + public TType getResultType() { + return mResultType; + } + + /** + * 根据是否有误缓存结果,判断是否需要发起http请求 + * + * @return 序列化之后请求结果 + * @throws HttpException 网络错误时 + * @throws RuntimeException 数据解析错误时 + */ + public HttpResult request(Context context) { + + HashMap resultMap = null; + if (null != resultMap && resultMap.size() > 0) { + String result = resultMap.get("data"); + boolean keepOn = Integer.parseInt(resultMap.get("needKeepOn")) == 1 ? true : false; + if (TextUtils.isEmpty(result)) { + //没有缓存则发起请求 + return requestWithCache(); + } else { + //有缓存则判断 是否依然需要发起请求 + if (keepOn) { + return requestWithCache(); + } else { + //有缓存 不需要发起请求 + return parse(result); + } + } + } + return requestWithCache(); + } + + /** + * 使用缓存的,真正发起请求 + * + * @return + */ + private HttpResult requestWithCache() { + HttpResult response; + try { + // 由于后台数据返回的data字段是一个json,所以当选择data数据以字符串的形式返回时,需要特殊处理。 + String responseString; + if (mHttpMethod == HttpMethod.GET) { + responseString = HttpRequestFactory.create().get(new TType() { + }, mUrl, mParams, mExt); + } else { + responseString = HttpRequestFactory.create().post(new TType() { + }, mUrl, mParams, mExt); + } + response = parse(responseString); + if (mCacheEnable && response.isSucceed()) { + writeCache(responseString); + } + return response; + } catch (HttpException e) { + // 获取会话超时的事件, + if (e.getHttpStatusCode() == 401) { + + } + throw e; + } + } + + + /** + * 不使用缓存的发起请求,为了兼容以前的不传activity的调用 + * + * @return + */ + public HttpResult request() { + HttpResult response; + try { + // 由于后台数据返回的data字段是一个json,所以当选择data数据以字符串的形式返回时,需要特殊处理。 + String responseString; + if (mHttpMethod == HttpMethod.GET) { + responseString = HttpRequestFactory.create().get(new TType() { + }, mUrl, mParams, mExt); + } else { + responseString = HttpRequestFactory.create().post(new TType() { + }, mUrl, mParams, mExt); + } + + response = parse(responseString); + return response; + } catch (Exception e) { + throw e; + } + } + + public HttpResult upload() { + HttpResult response; + String responseString; + try { + responseString = HttpRequestFactory.create().upload(mUrl, mParams, mUploadFiles); + response = parse(responseString); + return response; + } catch (HttpException e) { + // 获取会话超时的事件, + if (e.getHttpStatusCode() == 401) { + + } + throw e; + } + } + + public HttpResult download(String filePath, boolean shouldOverWritten) { + HttpResult response; + String responseString; + try { + responseString = HttpRequestFactory.create().download(mUrl, filePath, shouldOverWritten); + response = parse(responseString); + return response; + } catch (HttpException e) { + // 获取会话超时的事件, + if (e.getHttpStatusCode() == 401) { + + } + throw e; + } + } + + public void download(String filePath, boolean shouldOverWritten, HttpCallback callback) { + HttpRequestFactory.create().download(mUrl, filePath, shouldOverWritten, callback); + } + + + /* + * 把字符串解析成相应对象 + */ + private HttpResult parse(String responseString) { + //AES解密 +// Log.e("Original Response",responseString); + responseString = AESUtils.decrypt(Constant.AES_PASSWORD, responseString); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "parse : aes " + responseString); + HttpResult response; + Type type = mResultType.getTType(); + boolean isDataOfString = false; + if (type instanceof ParameterizedType) { + Type argType = ((ParameterizedType) type).getActualTypeArguments()[0]; + if (argType != null && argType.equals(String.class)) { + isDataOfString = true; + } + } + if (BuildConfig.DEBUG) { + if (responseString != null) { + int maxLogSize = 2000; // 每次打印的最大长度 + for (int i = 0; i <= responseString.length() / maxLogSize; i++) { + int start = i * maxLogSize; + int end = Math.min(start + maxLogSize, responseString.length()); + if (ConstUrl.LOGDEBUG) Log.e("HTTP-------", responseString.substring(start, end)); + } + } else { + if (ConstUrl.LOGDEBUG) Log.e("HTTP-------", null); + } + } + + Gson gson = new Gson(); + // 由于后台数据返回的data字段是一个json,所以当选择data数据以字符串的形式返回时,需要特殊处理。 + if (isDataOfString) { + response = gson.fromJson(responseString, new TType>() { + }.getTType()); + try { + response.setData((T) new JSONObject(responseString).optString("data")); + } catch (JSONException e) { + throw new RuntimeException("数据解析错误"); + } + } else { + try { + response = gson.fromJson(responseString, mResultType.getTType()); + } catch (Exception e1) { + try { + response = gson.fromJson(responseString, new TType>>() { + }.getTType()); + } catch (Exception e) { + try { + response = gson.fromJson(responseString, new TType>() { + }.getTType()); + if (responseString != null) { + response.setData((T) new JSONObject(responseString).optString("data")); + } + } catch (JSONException e2) { + throw new RuntimeException("数据解析错误"); + } + } + } + } + + return response; + } + + /** + * 读取接口缓存 + * + * @return 接口的缓存,如果没有,返回null + */ + public HttpResult readCache(Context context) { + + HashMap resultMap = null; + if (null != resultMap && resultMap.size() > 0) { + boolean keepOn = Integer.parseInt(resultMap.get("needKeepOn")) == 1 ? true : false; + if (!keepOn) + return null; + + String result = resultMap.get("data"); + if (!TextUtils.isEmpty(result)) { + return parse(result); + } + } + return null; + } + + + /** + * 写入缓存 + */ + private void writeCache(String result) { + + } + + + public static class Builder { + + private RequestParameter mParams = new RequestParameter(); + + private HttpMethod mHttpMethod; + + private String mUrl; + + private String mExt; + + private TType> mResultType; + + private UploadFile[] mUploadFiles = null; + + private boolean mCacheEnable = true; + + + /** + * 设置请求类型 + * + * @param httpMethod {@link HttpMethod#GET}或者{@link HttpMethod#POST} + */ + public Builder setHttpMethod(HttpMethod httpMethod) { + mHttpMethod = httpMethod; + return this; + } + + /** + * 设置请求url,不能为空 + * + * @param url 请求url + */ + public Builder setUrl(String url) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "setUrl: " + url); + mUrl = url; + return this; + } + + public Builder setExt(String ext) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "setExt: " + mExt); + this.mExt = ext; + return this; + } + + /** + * 添加参数 + */ + public Builder addParam(@NonNull String key, @NonNull String value) { + mParams.addParameter(key, value); + return this; + } + + public Builder addUploadFiles(@NonNull UploadFile[] uploadFiles) { + mUploadFiles = uploadFiles; + return this; + } + + /** + * 设置返回结果类型. + * + * @param resultType 返回结果类型 + * 例如,如果data数据为String类型,使用{@code new TType>(){}} 获取 + */ + public Builder setResultType(TType> resultType) { + mResultType = resultType; + return this; + } + + /** + * 设置是否缓存接口,默认缓存 + * 如果接口数据与用户相关,还需要调用{@link #( String )}设置用户的id + * + * @param cacheEnable true 缓存 + */ + public Builder setCacheEnable(boolean cacheEnable) { + mCacheEnable = cacheEnable; + return this; + } + + + /** + * 生成一个{@link HttpRequest}实例 + */ + public HttpRequest build() { + checkStringNotEmpty(mUrl, "url cannot be empty!"); + checkNotNull(mHttpMethod, "HttpMethod cannot be null!"); + checkNotNull(mResultType, "ResultType cannot be null!"); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "build: --------->" + mUrl + mParams.toString()); + return new HttpRequest<>(this); + + } + + private static void checkStringNotEmpty(String str, String errMsg) { + if (TextUtils.isEmpty(str)) { + throw new IllegalArgumentException(errMsg); + } + } + + private static void checkNotNull(Object o, String errMsg) { + if (o == null) { + throw new IllegalArgumentException(errMsg); + } + } + + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpRequestWithCache.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpRequestWithCache.java new file mode 100644 index 0000000..d51bfb9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpRequestWithCache.java @@ -0,0 +1,232 @@ +package com.fengliyan.tianlesue.view.base.utils.http; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import android.text.TextUtils; + +import com.fengliyan.http.httprequest.HttpException; +import com.fengliyan.http.httprequest.HttpMethod; +import com.fengliyan.http.httprequest.HttpRequestFactory; +import com.fengliyan.http.httprequest.RequestParameter; +import com.fengliyan.http.httprequest.TType; +import com.google.gson.Gson; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.HashMap; + +/** + * Created by yuxiaoqiu on 2016/10/24. + */ +public class HttpRequestWithCache { + + private static final String TAG = HttpRequest.class.getSimpleName(); + + private RequestParameter mParams; + + private HttpMethod mHttpMethod; + + private String mUrl; + + private TType> mResultType; + + private boolean mCacheEnable = true; + + private HttpRequestWithCache(Builder builder) { + mHttpMethod = builder.mHttpMethod; + mParams = builder.mParams; + mUrl = builder.mUrl; + mResultType = builder.mResultType; + mCacheEnable = builder.mCacheEnable; + } + + + public HttpMethod getHttpMethod() { + return mHttpMethod; + } + + public String getUrl() { + return mUrl; + } + + public TType getResultType() { + return mResultType; + } + + public RequestParameter getParams() { + return mParams; + } + + /** + * 使用缓存的,真正发起请求 + * + * @return + */ + public HttpResult request() { + HttpResult response; + try { + // 由于后台数据返回的data字段是一个json,所以当选择data数据以字符串的形式返回时,需要特殊处理。 + String responseString; + if (mHttpMethod == HttpMethod.GET) { + responseString = HttpRequestFactory.create().get(new TType() { + }, mUrl, mParams, ""); + } else { + responseString = HttpRequestFactory.create().post(new TType() { + }, mUrl, mParams, ""); + } + response = parse(responseString); + if (mCacheEnable && response.isSucceed()) { + writeCache(responseString); + } + return response; + } catch (HttpException e) { + // 获取会话超时的事件, + if (e.getHttpStatusCode() == 401) { + // 当显示了手势解锁界面时,由于未解锁,此时还未设置cookie,所以不抛出超时事件 + + } + throw e; + } + } + + /* + * 把字符串解析成相应对象 + */ + public HttpResult parse(String responseString) { + HttpResult response; + Type type = mResultType.getTType(); + boolean isDataOfString = false; + if (type instanceof ParameterizedType) { + Type argType = ((ParameterizedType) type).getActualTypeArguments()[0]; + if (argType != null && argType.equals(String.class)) { + isDataOfString = true; + } + } + Gson gson = new Gson(); + // 由于后台数据返回的data字段是一个json,所以当选择data数据以字符串的形式返回时,需要特殊处理。 + if (isDataOfString) { + response = gson.fromJson(responseString, new TType>() { + }.getTType()); + try { + response.setData((T) new JSONObject(responseString).optString("data")); + } catch (JSONException e) { + throw new RuntimeException("数据解析错误"); + } + } else { + response = gson.fromJson(responseString, mResultType.getTType()); + } + return response; + } + + + /** + * 写入缓存 + */ + private void writeCache(String result) { + //NO USAGE + } + + + /** + * 讀取缓存 + */ + public HashMap readCache(Context context) { + return null; + } + + + public static class Builder { + + private RequestParameter mParams = new RequestParameter(); + + private HttpMethod mHttpMethod; + + private String mUrl; + + private TType> mResultType; + + private boolean mCacheEnable = true; + + + /** + * 设置请求类型 + * + * @param httpMethod {@link HttpMethod#GET}或者{@link HttpMethod#POST} + */ + public Builder setHttpMethod(HttpMethod httpMethod) { + mHttpMethod = httpMethod; + return this; + } + + /** + * 设置请求url,不能为空 + * + * @param url 请求url + */ + public Builder setUrl(String url) { + mUrl = url; + return this; + } + + /** + * 添加参数 + */ + public Builder addParam(@NonNull String key, @NonNull String value) { + mParams.addParameter(key, value); + return this; + } + + /** + * 设置返回结果类型. + * + * @param resultType 返回结果类型 + * 例如,如果data数据为String类型,使用{@code new TType>(){}} 获取 + */ + public Builder setResultType(TType> resultType) { + mResultType = resultType; + return this; + } + + /** + * 设置是否缓存接口,默认缓存 + * 如果接口数据与用户相关,还需要调用{@link #( String )}设置用户的id + * + * @param cacheEnable true 缓存 + */ + public Builder setCacheEnable(boolean cacheEnable) { + mCacheEnable = cacheEnable; + return this; + } + + + /** + * 生成一个{@link HttpRequest}实例 + */ + public HttpRequestWithCache build() { + checkStringNotEmpty(mUrl, "url cannot be empty!"); + checkNotNull(mHttpMethod, "HttpMethod cannot be null!"); + checkNotNull(mResultType, "ResultType cannot be null!"); + return new HttpRequestWithCache<>(this); + + } + + private static void checkStringNotEmpty(String str, String errMsg) { + if (TextUtils.isEmpty(str)) { + throw new IllegalArgumentException(errMsg); + } + } + + private static void checkNotNull(Object o, String errMsg) { + if (o == null) { + throw new IllegalArgumentException(errMsg); + } + } + + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpResult.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpResult.java new file mode 100644 index 0000000..7ddb530 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/http/HttpResult.java @@ -0,0 +1,114 @@ +package com.fengliyan.tianlesue.view.base.utils.http; + +import com.google.gson.Gson; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * http 网络请求结果 + *

+ * http 请求结果的正确返回值格式如下 + * { + * "ret": "0", + * "errMsg": null, + * "errCode": null, + * "data": { + * }, + * "tips": { + * "content": null, + * "title": null, + * "button": null, + * "type": "default" + * } + * } + *

+ * Created by yangjinbo on 2016/1/11. + */ +public class HttpResult { + + /** + * http接口返回是否成功的标志,“0”表示成功,其他为失败 + */ + @SerializedName("code") + private String code; + + /** + * 失败时的错误信息 + */ + @SerializedName("message") + private String message; + + @SerializedName("time") + private String time; + + /** + * 有效的数据 + */ + @Expose + private T data; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + /** + * 判断请求是否成功 + * + * @return true 成功 + */ + public boolean isSucceed() { + return "0".equals(code); + } + + public boolean notEnoughMoney() { + return "1002".equals(code); + } + + public boolean notLogin() { + return "1001".equals(code); + } + + public boolean banned() { + return "1004".equals(code); + } + + public boolean notEnoughCoin() { + return "1003".equals(code); + } + + + @Override + public String toString() { + Gson gson = new Gson(); + return gson.toJson(this); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/DefaultHttpCallBack.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/DefaultHttpCallBack.java new file mode 100644 index 0000000..e29b103 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/DefaultHttpCallBack.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.view.base.utils.task; + +import com.fengliyan.http.httprequest.HttpCallback; + +/** + * HttpCallback的默认实现 + * Created by neuyuandaima on 2016/8/29. + */ +public class DefaultHttpCallBack extends HttpCallback { + @Override + public void onFailure(int httpStatusCode, String message, Throwable throwable) { + + } + + @Override + public void onSuccess(int httpStatusCode, T responseObject) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/DefaultHttpUiCallBack.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/DefaultHttpUiCallBack.java new file mode 100644 index 0000000..d27f601 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/DefaultHttpUiCallBack.java @@ -0,0 +1,26 @@ +package com.fengliyan.tianlesue.view.base.utils.task; + + +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +/** + * Created by neuyuandaima on 2016/9/2. + */ +public class DefaultHttpUiCallBack implements HttpUiCallBack { + + @Override + public void onSuccess(BaseActivity activity, T result, String message) { + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/GeneralHttpUiHandler.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/GeneralHttpUiHandler.java new file mode 100644 index 0000000..f8bf7c9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/GeneralHttpUiHandler.java @@ -0,0 +1,106 @@ +package com.fengliyan.tianlesue.view.base.utils.task; + +import android.view.View; + +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.BaseView; +import com.fengliyan.http.httprequest.HttpException; + + +/** + * 通用的httpUI回调 + * Created by yangjinbo on 2016/1/14. + */ +public abstract class GeneralHttpUiHandler implements HttpUiCallBack { + + private String mTipsType; + + /** + * 绑定的task,当发生错误时,重新执行此任务 + */ + private HttpWithUiTask mBindTask; + + private BaseView mBaseView; + + public GeneralHttpUiHandler() { + this("", null); + } + + /** + * 构造方法 + * + * @param type http链接发生异常时的错误处理类型 + */ + public GeneralHttpUiHandler(String type) { + this(type, null); + } + + public GeneralHttpUiHandler(BaseView baseView) { + this("", baseView); + } + + public GeneralHttpUiHandler(String type, BaseView baseView) { + mBaseView = baseView; + mTipsType = type; + } + + public void setBindTask(HttpWithUiTask bindTask) { + mBindTask = bindTask; + } + + public HttpWithUiTask getBindTask() { + return mBindTask; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (tip == null) { + return; + } + } + + + @Override + public void onException(BaseActivity activity, Throwable e) { + String errMsg; + + View.OnClickListener clickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + GeneralHttpUiHandler.this.refreshHandler(); + } + }; + + if (e instanceof HttpException) { + if (((HttpException) e).getHttpStatusCode() == 401) { + errMsg = "会话超时,请重新登录"; + } else { + errMsg = "网络异常"; + + return; + } + } else { + + } + } + + /** + * 当出现错误页面时的,按钮的处理方法 + */ + public void refreshHandler() { + if (mBindTask != null) { + mBindTask.doAgain(); + BaseActivity activity = mBindTask.getLivedActivity(); + if (activity != null) { + + } + if (mBaseView == null) { + + } else { + mBaseView.hideLoading(); + } + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/HttpWithUiTask.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/HttpWithUiTask.java new file mode 100644 index 0000000..8a77c5c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/HttpWithUiTask.java @@ -0,0 +1,247 @@ +package com.fengliyan.tianlesue.view.base.utils.task; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.blankj.utilcode.util.ActivityUtils; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.login.bean.CustomerTipBean; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.news.IMCostBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.http.HttpResult; +import com.fengliyan.tianlesue.view.base.utils.view.BannedTipsDialog; +import com.fengliyan.tianlesue.view.base.utils.view.HelpTipsDialog; +import com.mobile.auth.gatewayauth.LoginAuthActivity; + +import java.util.ArrayList; +import java.util.concurrent.Executor; + +/** + * 自带请求错误时的UI处理的Http异步请求。如果自带的处理不能符合要求,可以使用{@link #HttpWithUiTask(BaseActivity, HttpUiCallBack)} + * 构造自己处理UI的task. + * 在{@link #run()}方法里面实现http请求,在{@link HttpUiCallBack#onSuccess(BaseActivity, Object, String)}中刷新成功时的UI。 + *

+ * NOTE: 此类中的 {@link HttpUiCallBack#onSuccess(BaseActivity, Object, String)} 仅在activity还存活的时候回调, + * 如果需要刷新某些本地的全局的数据,请在{@link #run()}方法得到服务器数据后直接更新本地数据或重载{@link #onResultSuccess(HttpResult)}来更新数据. + *

+ * 例如: + *

+ *  pubic class TestActivity extends Activity {
+ *      ....
+ *      new HttpWithUiTask(this) {
+ *
+ *          public void onSuccess(BaseActivity activity, Object data) {
+ *              ToastUtil.showMessage(activity, "登录成功");
+ *          }
+ *
+ *          protected HttpResult run() throws Exception {
+ *              HttpRequest request = LoginManager.getLoginRequest("123", "123");
+ *              return request.request();
+ *          }
+ *      }.start();
+ *      ...
+ *  }
+ *
+ * 
+ * Created by yangjinbo on 2016/1/13. + */ +public abstract class HttpWithUiTask extends ProgressTask> { + + private static final String TAG = "HttpWithUiTask"; + + private HttpUiCallBack mUiHandler; + + private boolean mHasCache = false; + + /** + * 构造方法 + * + * @param activity ui附属的activity + */ + public HttpWithUiTask(@NonNull BaseActivity activity) { + super(activity); + init(null); + setRefresh(activity.getRefresh()); + } + + /** + * 构造方法 + * + * @param activity ui附属的activity + * @param uiCallBack 自定义ui回调。 + * 注意:回调中只能用于刷新UI和Activity内部,不能用于刷新全局数据 + */ + public HttpWithUiTask(@NonNull BaseActivity activity, HttpUiCallBack uiCallBack) { + super(activity); + init(uiCallBack); + setRefresh(activity.getRefresh()); + } + + /** + * 构造方法 + * + * @param activity ui附属的activity + * @param uiCallBack 自定义ui回调 + * 注意:回调中只能用于刷新UI和Activity内部,不能用于刷新全局数据 + * @param executor 任务运行的线程池。若为null,则默认使用{@link #} + */ + public HttpWithUiTask(@NonNull BaseActivity activity, HttpUiCallBack uiCallBack, Executor executor) { + super(activity, executor); + init(uiCallBack); + setRefresh(activity.getRefresh()); + } + + + /** + * 初始化方法 + * + * @param uiCallBack 自定义ui回调 + */ + private void init(final HttpUiCallBack uiCallBack) { + + if (uiCallBack == null) { + mUiHandler = new DefaultHttpUiCallBack(); + return; + } + + if (uiCallBack instanceof GeneralHttpUiHandler) { + mUiHandler = uiCallBack; + if (((GeneralHttpUiHandler) uiCallBack).getBindTask() == null) { + ((GeneralHttpUiHandler) uiCallBack).setBindTask(this); + } + } else { + mUiHandler = uiCallBack; + } + } + + @Override + public void start() { + BaseActivity activity = getLivedActivity(); + if (activity != null) { + super.start(); + } + } + + @Override + public void start(boolean refresh) { + BaseActivity activity = getLivedActivity(); + if (activity != null) { + super.start(refresh); + } + } + + private class DefaultHttpUiCallBack extends GeneralHttpUiHandler { + + public DefaultHttpUiCallBack() { + } + + @Override + public void onSuccess(BaseActivity activity, T result, String message) { + HttpWithUiTask.this.onSuccess(activity, result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + } + + + @Override + protected void onResultSuccess(HttpResult result) { + BaseActivity activity = getLivedActivity(); + if (activity != null) { + try { + //activity.dimissNoNetView(); + if ("".equals(result.getData())) { + result.setData(null); + } + if (result.getData() instanceof ArrayList) { + if (((ArrayList) result.getData()).size() == 0) { + result.setData(null); + } + } + if (result.isSucceed()) { + mUiHandler.onSuccess(activity, result.getData(), result.getMessage()); + } else if (result.notLogin()) { + UserManager.getInstance().notifyUserInfoChanged(new BaseUserInfo()); + mUiHandler.onFailure(activity, result.getMessage()); + } else if (result.notEnoughMoney() || result.notEnoughCoin()) { + if (result.getData() instanceof IMCostBean) { + IMCostBean bean = (IMCostBean) result.getData(); + if (StrU.equals("send_msg", bean.getType())) { + BaseApplication.getInstance().getRechargeInfo(activity, 1); + } else { + BaseApplication.getInstance().getRechargeInfo(activity, 0); + } + } else { + BaseApplication.getInstance().getRechargeInfo(activity, 0); + } +// Intent intent = new Intent(activity, CaibeiRechargeActivity.class); +// activity.startActivity(intent); + mUiHandler.onFailure(activity, result.getMessage()); + } else if (result.banned()) { + if (result.getData() instanceof CustomerTipBean) { + CustomerTipBean bean = (CustomerTipBean) result.getData(); + HelpTipsDialog dialog = new HelpTipsDialog(activity, bean); + dialog.show(); + } else { + LoginBean bean = (LoginBean) result.getData(); + if (ActivityUtils.getTopActivity() instanceof LoginAuthActivity) { + if (bean.getContent() != null && bean.getContent().size() > 0) { + mUiHandler.onFailure(activity, result.getMessage()); + } + } + BannedTipsDialog dialog = new BannedTipsDialog(activity, bean); + dialog.show(); + } + } else { + mUiHandler.onFailure(activity, result.getMessage()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + protected void onResultException(Throwable e) { + if (mHasCache) { + return; + } + BaseActivity activity = getLivedActivity(); + if (activity != null) { + try { + //activity.showNoNetView(); + //activity.setRetryButton(new View.OnClickListener() { + // @Override + // public void onClick(View view) { + // doAgain(); + // } + //}); + + mUiHandler.onException(activity, e); + Log.e(TAG, "onResultException: e----->", e); + } catch (Exception e1) { + + } + } + } + + /** + * 成功的回调,当没有设置自定义的{@link HttpUiCallBack}时调用 + * + * @param activity 所在activity + * @param result 成功数据 + * @see HttpUiCallBack#onSuccess(BaseActivity, Object, String) + */ + protected void onSuccess(BaseActivity activity, T result) { + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/ProgressTask.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/ProgressTask.java new file mode 100644 index 0000000..b3cef95 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/task/ProgressTask.java @@ -0,0 +1,329 @@ +package com.fengliyan.tianlesue.view.base.utils.task; + +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import java.lang.ref.WeakReference; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 通用的自带等待框的异步任务。 + * 调用{@link #start()}开始任务 + * 可重复执行,在运行结束后调用{@link #doAgain()}会再一次执行整个任务 + * Created by yangjinbo on 2016/1/13. + */ +public abstract class ProgressTask { + + private static final String TAG = "ProgressTask"; + + private static final Executor DEFAULT_THREAD_POOL = Executors.newCachedThreadPool(new ThreadFactory() { + private final AtomicInteger mCount = new AtomicInteger(1); + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, TAG + " Thread #" + mCount.getAndIncrement()); + } + }); + + private static Handler sHandler; + + private WeakReference mActivityWeakReference; + + private Executor mExecutor; + + private CharSequence mTip; + + private Runnable mRunnable; + + private SwipeRefreshLayout mRefresh; + + private boolean mShowWaitingDialog = false; + + /* + * 对此参数的赋值都在UI线程中,故不需要同步 + */ + private Status mStatus = Status.PENDING; + + /** + * Indicates the current status of the task. Each status will be set only once + * during the lifetime of a task. + */ + public enum Status { + /** + * Indicates that the task has not been executed yet. + */ + PENDING, + /** + * Indicates that the task is running. + */ + RUNNING, + /** + * Indicates that has finished. + */ + FINISHED, + } + + private class TaskResult { + boolean mState; + T mData; + Throwable mThrowable; + } + + protected void setRefresh(SwipeRefreshLayout refresh) { + mRefresh = refresh; + } + + protected static Handler getHandler() { + if (sHandler == null) { + synchronized (ProgressTask.class) { + if (sHandler == null) { + sHandler = new Handler(Looper.getMainLooper()); + } + } + } + return sHandler; + } + + /** + * 构造方法 + * + * @param activity ui附属的activity + */ + public ProgressTask(@NonNull BaseActivity activity) { + this(activity, null); + } + + + /** + * 构造方法 + * + * @param activity ui附属的activity + * @param executor 任务运行的线程池。若为null,则默认使用{@link #DEFAULT_THREAD_POOL} + */ + public ProgressTask(@NonNull BaseActivity activity, Executor executor) { + DeviceManager.getInstance().init(activity); + mActivityWeakReference = new WeakReference<>(activity); + if (mExecutor != null) { + mExecutor = executor; + } else { + mExecutor = DEFAULT_THREAD_POOL; + } + + mRunnable = new Runnable() { + + @Override + public void run() { + final TaskResult result = new TaskResult(); + try { + result.mData = ProgressTask.this.run(); + result.mState = true; + } catch (Throwable e) { + if (ConstUrl.LOGDEBUG) Log.e(TAG, "run:----------> ", e); + result.mThrowable = e; + result.mState = false; + } + getHandler().post(new Runnable() { + @Override + public void run() { + finish(result); + } + }); + } + }; + } + + /** + * 返回任务的当前状态 + * + * @return 任务状态 + */ + public Status getStatus() { + return mStatus; + } + + private void finish(TaskResult taskResult) { + mStatus = Status.FINISHED; + + if (taskResult.mState) { + onResultSuccess(taskResult.mData); + } else { + if (ConstUrl.LOGDEBUG) Log.e(TAG, "finish: ---------->", taskResult.mThrowable); + onResultException(taskResult.mThrowable.getCause()); + } + + stopRefresh(); + //dismissProgress(); + } + + public void stopRefresh() { + if (null != mRefresh) { + mRefresh.setRefreshing(false); + mRefresh.setEnabled(false); + } + } + + /** + * 设置等待框上提示语,不设置默认显示“请稍等...”,调用此方法必须在任务运行前调用 + * + * @param tip 提示语 + * @throws IllegalStateException 在任务运行后(调用了{@link #start()})再调用此方法时抛出 + */ + public void setWaitingTip(CharSequence tip) { + if (mStatus != Status.PENDING) { + throw new IllegalStateException("You cannot invoke this method after running!"); + } + mTip = tip; + } + + /** + * 设置是否显示对话框,调用此方法必须在任务运行前调用。默认显示等待对话框 + * + * @param showWaitingDialog true 显示 + * @throws IllegalStateException 在任务运行后(调用了{@link #start()})再调用此方法时抛出 + */ + public void setShowWaitingDialog(boolean showWaitingDialog) { + if (mStatus != Status.PENDING) { + throw new IllegalStateException("You cannot invoke this method after running!"); + } + mShowWaitingDialog = showWaitingDialog; + } + + /** + * 销毁等待框 + */ + /*protected void dismissProgress() { + if (!mShowWaitingDialog) { + return; + } + + BaseActivity activity = getLivedActivity(); + if (activity != null && mProgressDialog != null) { + mProgressDialog.dismiss(); + mProgressDialog = null; + } + }*/ + + /** + * 启动任务 + * 此方法必须在UI线程中调用 + * + * @throws RuntimeException 在非主线程调用时抛出 + * @throws IllegalStateException 在任务运行中又重复调用 + */ + public void start() { + if (Looper.getMainLooper().getThread() != Thread.currentThread()) { + throw new RuntimeException("start must be invoked in ui thread!"); + } + + if (mStatus != Status.PENDING) { + throw new IllegalStateException("Cannot start task: the task is already running."); + } + mStatus = Status.RUNNING; + //showIndeterminate(); + startRefresh(); + + mExecutor.execute(mRunnable); + } + + public void start(boolean refresh) { + if (Looper.getMainLooper().getThread() != Thread.currentThread()) { + throw new RuntimeException("start must be invoked in ui thread!"); + } + + if (mStatus != Status.PENDING) { + throw new IllegalStateException("Cannot start task: the task is already running."); + } + mStatus = Status.RUNNING; + //showIndeterminate(); + + if (refresh) { + startRefresh(); + } + mExecutor.execute(mRunnable); + } + + //开始刷新动画 + public void startRefresh() { + if (null != mRefresh) { + mRefresh.setEnabled(true); + mRefresh.setRefreshing(true); + } + } + + /** + * 再次执行此任务,必须当此任务已执行完后才能再次执行 + * + * @throws IllegalStateException 任务未运行完时调用此方法. + */ + protected void doAgain() { + if (mStatus != Status.FINISHED) { + throw new IllegalStateException("Cannot do again task: the task has not finished."); + } + getHandler().post(new Runnable() { + @Override + public void run() { + mStatus = Status.PENDING; + start(); + } + }); + } + + /** + * 任务执行完成后的回调,此方法在主线中执行。 + */ + protected void onResultSuccess(T result) { + + } + + /** + * 任务执行中抛出了异常的回调,此方法在主线程中执行 + * + * @param e 失败的异常 + */ + protected void onResultException(Throwable e) { + + } + + /** + * 执行具体任务的方法 + * + * @return 返回任务的有效数据 + * @throws Exception + */ + protected abstract T run() throws Exception; + + /** + * 获取ui附属的activity + * + * @return 当原附属的activity被销毁后或不可用后,返回null。 + */ + protected BaseActivity getLivedActivity() { + BaseActivity activity = mActivityWeakReference.get(); + if (activity != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (!activity.isDestroyed()) { + return activity; + } else { + return null; + } + } + + return activity; + } else { + return null; + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/AttentionDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/AttentionDialog.java new file mode 100644 index 0000000..98716cd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/AttentionDialog.java @@ -0,0 +1,170 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.OneKeyAttentionAdapter; +import com.fengliyan.tianlesue.model.main.AttentionBean; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/9. + */ + +public class AttentionDialog extends Dialog implements View.OnClickListener { + + private TextView mTvChange; + private RecyclerView mRvAttention; + private TextView mBtAttention; + private TextView tv_no_recommend; + private Context mContext; + private OneKeyAttentionAdapter mOneKeyAttentionAdapter; + private List recommendAttentionList = new ArrayList<>(); + private List attentionList = new ArrayList<>(); + + public AttentionDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public AttentionDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected AttentionDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_attention); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + mTvChange = findViewById(R.id.tv_change); + mRvAttention = findViewById(R.id.rv_attention); + mBtAttention = findViewById(R.id.bt_attention); + tv_no_recommend = findViewById(R.id.tv_no_recommend); + + mOneKeyAttentionAdapter = new OneKeyAttentionAdapter(mContext); + mOneKeyAttentionAdapter.setRecommendAttentionList(recommendAttentionList); + + mRvAttention.setAdapter(mOneKeyAttentionAdapter); + mRvAttention.setLayoutManager(new StaggeredGridLayoutManager(3, + StaggeredGridLayoutManager.VERTICAL)); + + mOneKeyAttentionAdapter.setOnClickItem(new OneKeyAttentionAdapter.OnClickItem() { + @Override + public void onClickItem(int position) { + AttentionBean attentionBean = recommendAttentionList.get(position); + if (attentionBean.getSelect() == 0) { + attentionBean.setSelect(1); + attentionList.remove(attentionBean); + }else if (attentionBean.getSelect() == 1) { + attentionBean.setSelect(0); + attentionList.add(attentionBean); + } + +// if (0 != attentionList.size()) { +// mBtAttention.setEnabled(true); +// } else { +// mBtAttention.setEnabled(false); +// } + + mOneKeyAttentionAdapter.notifyDataSetChanged(); + } + }); + + mTvChange.setOnClickListener(this); + mBtAttention.setOnClickListener(this); + tv_no_recommend.setOnClickListener(this); + } + + public void setData(List recommendAttentionList) { + this.recommendAttentionList = recommendAttentionList; + attentionList.clear(); //先清空 + attentionList.addAll(recommendAttentionList); + if (null != mOneKeyAttentionAdapter) { + mOneKeyAttentionAdapter.setRecommendAttentionList(recommendAttentionList); + mOneKeyAttentionAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onClick(View view) { + if (view == mTvChange) { //换一批 + if (null != mOnClickAttention) { + mOnClickAttention.onClickChange(); + } + }else if (view == mBtAttention) { //一键关注 + + if (null != mOnClickAttention) { + Iterator iterator = attentionList.iterator(); + StringBuilder stringBuilder = new StringBuilder(); + int count = 0; + while (iterator.hasNext()) { + AttentionBean bean = iterator.next(); + if (count != 0) { + stringBuilder.append(","); + } + + stringBuilder.append(bean.getUserid() + ""); + count++; + } + mOnClickAttention.onClickOneKeyAttention(stringBuilder.toString()); + } + }else if(view==tv_no_recommend){ + dismiss(); + } + } + + private OnClickAttention mOnClickAttention; + + public void setOnClickAttention(OnClickAttention onClickAttention) { + mOnClickAttention = onClickAttention; + } + + public interface OnClickAttention { + void onClickChange(); + void onClickOneKeyAttention(String uids); + } + +// @Override +// public void show() { +// super.show(); +// /** +// * 设置宽度全屏,要设置在show的后面 +// */ +// WindowManager.LayoutParams layoutParams = getWindow().getAttributes(); +// layoutParams.gravity=Gravity.BOTTOM; +// layoutParams.width= WindowManager.LayoutParams.MATCH_PARENT; +// layoutParams.height= WindowManager.LayoutParams.WRAP_CONTENT; +// +// getWindow().getDecorView().setPadding(0, 0, 0, 0); +// +// getWindow().setAttributes(layoutParams); +// +// } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/BannedTipsDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/BannedTipsDialog.java new file mode 100644 index 0000000..057bbee --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/BannedTipsDialog.java @@ -0,0 +1,88 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.blankj.utilcode.util.ClipboardUtils; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.uikit.toast.MaleToast; + +/** + * Created by zhangbin on 2019/5/22. + */ + +public class BannedTipsDialog extends Dialog { + private Context mContext; + private TextView tv_dialog_tips_title; + private TextView tv_dialog_tips_email; + private TextView tv_dialog_tips_msg1; + private TextView tv_dialog_tips_msg2; + private TextView tv_dialog_tips_sure; + + private LoginBean bean; + + public BannedTipsDialog(@NonNull Context context, LoginBean bean) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.bean = bean; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_banned_tips); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + tv_dialog_tips_title = findViewById(R.id.tv_dialog_tips_title); + tv_dialog_tips_msg1 = findViewById(R.id.tv_dialog_tips_msg1); + tv_dialog_tips_msg2 = findViewById(R.id.tv_dialog_tips_msg2); + tv_dialog_tips_email = findViewById(R.id.tv_dialog_tips_email); + tv_dialog_tips_sure = findViewById(R.id.tv_dialog_tips_sure); + + if (bean != null) { + tv_dialog_tips_title.setText(bean.getTitle()); + if (bean.getContent() != null && bean.getContent().size() > 0) { + tv_dialog_tips_msg1.setText(bean.getContent().get(0)); + tv_dialog_tips_msg2.setText(bean.getContent().get(1)); + tv_dialog_tips_email.setText(bean.getContent().get(2)); + String s = bean.getContent().get(2); + StrU.setSpanTextColor(bean.getContent().get(2), s.indexOf(bean.getColor_text()), (s.indexOf(bean.getColor_text()) + bean.getColor_text().length()), tv_dialog_tips_email, R.color.email_color, mContext); + tv_dialog_tips_email.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (bean != null) { + ClipboardUtils.copyText(bean.getColor_text()); + MaleToast.showMessage(mContext, "复制成功"); + } + } + }); + } + } + + tv_dialog_tips_sure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/BaseView.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/BaseView.java new file mode 100644 index 0000000..fba4e97 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/BaseView.java @@ -0,0 +1,51 @@ + +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.view.View; + +/** + * 错误处理、挂牌接口 + * Created by wuchunlei on 2016-03-01. + */ + +public interface BaseView { + + /** + * show loading message + * + * @param msg + */ + void showLoading(String msg); + + /** + * hide loading + */ + void hideLoading(); + /** + * show error message + * @param msg + * @param onClickListener + */ + void showError(String msg, View.OnClickListener onClickListener); + + /** + * how exception message + * @param msg + * @param onClickListener + */ + void showException(String msg, View.OnClickListener onClickListener); + + /** + * showNetError + * @param onClickListener + */ + void showNetError(View.OnClickListener onClickListener); + + /** + * showEmpty + * @param msg + * @param onClickListener + */ + void showEmpty(String msg, View.OnClickListener onClickListener); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/DefaultMessageDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/DefaultMessageDialog.java new file mode 100644 index 0000000..16579d9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/DefaultMessageDialog.java @@ -0,0 +1,179 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.uikit.toast.MaleToast; + +/** + * Created by zhangbin on 2019/1/18. + */ + +public class DefaultMessageDialog extends Dialog implements View.OnClickListener { + + private Context mContext; + private ImageView mIvFinishDialog; + private EditText mEtInputMessage; + private TextView mTvInputCount; + private Button mBtSave; + private Button mBtSaveSend; + private RelativeLayout mRlEdit; + + public DefaultMessageDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public DefaultMessageDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected DefaultMessageDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_default_message); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + mIvFinishDialog = findViewById(R.id.iv_finish_dialog); + mEtInputMessage = findViewById(R.id.et_input_message); + mTvInputCount = findViewById(R.id.tv_input_count); + mBtSave = findViewById(R.id.bt_save); + mBtSaveSend = findViewById(R.id.bt_save_send); + mRlEdit = findViewById(R.id.rl_edit); + initEdit(); + + mIvFinishDialog.setOnClickListener(this); + mBtSave.setOnClickListener(this); + mBtSaveSend.setOnClickListener(this); + mRlEdit.setOnClickListener(this); + } + + private void initEdit() { + + mEtInputMessage.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + String str = s.toString(); + if (!TextUtils.isEmpty(str)) { + if (str.length() <= 200) { + mTvInputCount.setText(str.length() + ""); + mText = str.trim(); + }else { + MaleToast.showMessage(mContext, "最多输入200字"); + } + } + + } + }); + } + + private String mText = ""; + + @Override + public void onClick(View view) { + if (view == mIvFinishDialog) { + hideKeyBoard(); + if (null != mOnClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog.onClickFinishDialog(); + } + }else if (view == mBtSave) { + if (!TextUtils.isEmpty(mText)) { + hideKeyBoard(); + if (null != mOnClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog.onClickSave(mText); + } + }else { + MaleToast.showMessage(mContext, "不得为空"); + } + + }else if (view == mBtSaveSend) { + if (!TextUtils.isEmpty(mText)) { + hideKeyBoard(); + if (null != mOnClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog.onClickSaveSend(mText); + } + }else { + MaleToast.showMessage(mContext, "不得为空"); + } + }else if (view == mRlEdit) { + InputMethodManager inputMethodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); + mEtInputMessage.requestFocus();//setFocus方法无效 //addAddressRemarkInfo is EditText + } + } + + private void hideKeyBoard() { + InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mEtInputMessage.getWindowToken(), 0); + } + + private OnClickDefaultMessageDialog mOnClickDefaultMessageDialog; + + public void setOnClickDefaultMessageDialog(OnClickDefaultMessageDialog onClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog = onClickDefaultMessageDialog; + } + + public interface OnClickDefaultMessageDialog { + void onClickFinishDialog(); + void onClickSave(String text); + void onClickSaveSend(String text); + } + + + +// @Override +// public void show() { +// super.show(); +// /** +// * 设置宽度全屏,要设置在show的后面 +// */ +// WindowManager.LayoutParams layoutParams = getWindow().getAttributes(); +// layoutParams.gravity=Gravity.BOTTOM; +// layoutParams.width= WindowManager.LayoutParams.MATCH_PARENT; +// layoutParams.height= WindowManager.LayoutParams.WRAP_CONTENT; +// +// getWindow().getDecorView().setPadding(0, 0, 0, 0); +// +// getWindow().setAttributes(layoutParams); +// +// } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/EditDefaultMessageDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/EditDefaultMessageDialog.java new file mode 100644 index 0000000..8c7d5f5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/EditDefaultMessageDialog.java @@ -0,0 +1,186 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.List; + +/** + * Created by zhangbin on 2019/1/19. + */ + +public class EditDefaultMessageDialog extends Dialog implements View.OnClickListener { + private Context mContext; + private ImageView mIvFinishDialog; + private EditText mEtInputMessage; + private TextView mTvInputCount; + private Button mBtSave; + private Button mBtSaveSend; + private RelativeLayout mRlEdit; + + public EditDefaultMessageDialog(@NonNull Context context, List defaultMessageList, int position) { + super(context); + this.mContext = context; + this.mDefaultMessageList = defaultMessageList; + this.mPosition = position; + } + + public EditDefaultMessageDialog(@NonNull Context context, List defaultMessageList, int position, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + this.mDefaultMessageList = defaultMessageList; + this.mPosition = position; + } + + protected EditDefaultMessageDialog(@NonNull Context context, List defaultMessageList, int position, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + this.mDefaultMessageList = defaultMessageList; + this.mPosition = position; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_default_message); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + + } + + private void initView() { + mIvFinishDialog = findViewById(R.id.iv_finish_dialog); + mEtInputMessage = findViewById(R.id.et_input_message); + mTvInputCount = findViewById(R.id.tv_input_count); + mBtSave = findViewById(R.id.bt_save); + mBtSaveSend = findViewById(R.id.bt_save_send); + mRlEdit = findViewById(R.id.rl_edit); + + initEdit(); + + mIvFinishDialog.setOnClickListener(this); + mBtSave.setOnClickListener(this); + mBtSaveSend.setOnClickListener(this); + mRlEdit.setOnClickListener(this); + } + + private void initEdit() { + + mText = mDefaultMessageList.get(mPosition); + mEtInputMessage.setText(mText); + mTvInputCount.setText(mText.length() + ""); + mEtInputMessage.setSelection(mText.length()); //光标放在文字后面 + + mEtInputMessage.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + String str = s.toString(); + if (!TextUtils.isEmpty(str)) { + if (str.length() <= 200) { + mTvInputCount.setText(str.length() + ""); + mText = str.trim(); + }else { + MaleToast.showMessage(mContext, "最多输入200字"); + } + } + + } + }); + } + + private String mText = ""; + + private List mDefaultMessageList; + private int mPosition; + + @Override + public void onClick(View view) { + if (view == mIvFinishDialog) { + hideKeyBoard(); + if (null != mOnClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog.onClickFinishDialog(); + } + }else if (view == mBtSave) { + + if (!TextUtils.isEmpty(mText)) { + hideKeyBoard(); + + mDefaultMessageList.remove(mPosition); + mDefaultMessageList.add(mPosition, mText); + if (null != mOnClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog.onClickSave(mDefaultMessageList, mText); + } + }else { + MaleToast.showMessage(mContext, "不得为空"); + } + }else if (view == mBtSaveSend) { + if (!TextUtils.isEmpty(mText)) { + hideKeyBoard(); + + mDefaultMessageList.remove(mPosition); + mDefaultMessageList.add(mPosition, mText); + if (null != mOnClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog.onClickSaveSend(mDefaultMessageList, mText); + } + } else { + MaleToast.showMessage(mContext, "不得为空"); + } + + }else if (view == mRlEdit) { + InputMethodManager inputMethodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); + mEtInputMessage.requestFocus();//setFocus方法无效 //addAddressRemarkInfo is EditText + } + } + + private void hideKeyBoard() { + InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mEtInputMessage.getWindowToken(), 0); + } + + private OnClickDefaultMessageDialog mOnClickDefaultMessageDialog; + + public void setOnClickDefaultMessageDialog(OnClickDefaultMessageDialog onClickDefaultMessageDialog) { + mOnClickDefaultMessageDialog = onClickDefaultMessageDialog; + } + + public interface OnClickDefaultMessageDialog { + void onClickFinishDialog(); + void onClickSave(List defaultMessages, String text); + void onClickSaveSend(List defaultMessages, String text); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/FirstChargeGiftDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/FirstChargeGiftDialog.java new file mode 100644 index 0000000..886e08c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/FirstChargeGiftDialog.java @@ -0,0 +1,447 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; + +import com.alipay.sdk.app.PayTask; +import com.blankj.utilcode.util.SizeUtils; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.eventBus.PayEvent; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.settings.PayBean; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.model.settings.WXPayTypeBean; +import com.fengliyan.tianlesue.model.settings.WeChatPayInfoBean; +import com.fengliyan.tianlesue.utils.BuriedPointUtils; +import com.fengliyan.tianlesue.utils.PayUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.PayWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.toast.MaleToast; +import com.sand.qzf.paytypesdk.base.CallBack; +import com.sand.qzf.paytypesdk.base.PayTypeSdk; +import com.sand.qzf.paytypesdk.base.Resp; +import com.tencent.mm.opensdk.modelpay.PayReq; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.Map; + +import de.greenrobot.event.EventBus; + + +public class FirstChargeGiftDialog extends Dialog implements View.OnClickListener { + private final Activity mContext; + private ConstraintLayout cl_first_recharge; + private TextView mConfirm; + private TextView mTvDescOne; + private TextView mIconLimitOne; + private TextView mTvDescOne1; + private TextView mIconLimitOne1; + private TextView tv_first_ailpay; + private TextView tv_first_wechat; + private TextView tv_dialog_recharge_hint; + private TextView tv_first_one; + private TextView tv_first_two; + private TextView tv_first_three; + + private final List mGiftBagList; + private int selectLevelIndex = 0; + private String selectPayType = "wechat"; + private String mOrderInfo; + private int show_wx_pay_type = 1;//显示微信支付 1显示0不显示 + private int show_alipay_pay_type = 1; + + public FirstChargeGiftDialog(Activity context, List bean, int show_wx_pay_type, int show_alipay_pay_type) { + super(context); + mContext = context; + mGiftBagList = bean; + this.show_wx_pay_type = show_wx_pay_type; + this.show_alipay_pay_type = show_alipay_pay_type; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_first_charge_gift); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.getDecorView().setPadding(0, 0, 0, 0); + WindowManager.LayoutParams lp = window.getAttributes(); + lp.width = LinearLayout.LayoutParams.MATCH_PARENT; + lp.height = LinearLayout.LayoutParams.MATCH_PARENT; + window.setAttributes(lp); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + BuriedPointUtils.buriedPoint((BaseActivity) mContext, BuriedPointUtils.BURIED1); + } + + private void initView() { + cl_first_recharge = findViewById(R.id.cl_first_recharge); + mConfirm = findViewById(R.id.confirm); + tv_first_one = findViewById(R.id.tv_first_one); + tv_first_two = findViewById(R.id.tv_first_two); + tv_first_three = findViewById(R.id.tv_first_three); + mTvDescOne = findViewById(R.id.tv_desc_one); + mIconLimitOne = findViewById(R.id.icon_limit_one); + mTvDescOne1 = findViewById(R.id.tv_desc_one1); + mIconLimitOne1 = findViewById(R.id.icon_limit_one1); + tv_first_ailpay = findViewById(R.id.tv_first_ailpay); + tv_first_wechat = findViewById(R.id.tv_first_wechat); + tv_dialog_recharge_hint = findViewById(R.id.tv_dialog_recharge_hint); + tv_first_one.setText(mGiftBagList.get(0).getName()); + tv_first_two.setText(mGiftBagList.get(1).getName()); + tv_first_three.setText(mGiftBagList.get(2).getName()); + + cl_first_recharge.setOnClickListener(this); + tv_first_one.setOnClickListener(this); + tv_first_two.setOnClickListener(this); + tv_first_three.setOnClickListener(this); + tv_first_ailpay.setOnClickListener(this); + tv_first_wechat.setOnClickListener(this); + mConfirm.setOnClickListener(this); + changeLevel(0); + mHandler = new MyHandler(mContext); + if (show_wx_pay_type == 0 && show_alipay_pay_type == 0) { + tv_dialog_recharge_hint.setVisibility(View.VISIBLE); + mConfirm.setVisibility(View.INVISIBLE); + } else { + tv_dialog_recharge_hint.setVisibility(View.GONE); + mConfirm.setVisibility(View.VISIBLE); + if (show_wx_pay_type == 0) { + tv_first_wechat.setVisibility(View.GONE); + selectPayType = "alipay"; + tv_first_ailpay.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_true1), null, null, null); + tv_first_wechat.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_false), null, null, null); + } else { + tv_first_wechat.setVisibility(View.VISIBLE); + } + if (show_alipay_pay_type == 0) { + tv_first_ailpay.setVisibility(View.GONE); + selectPayType = "wechat"; + tv_first_wechat.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_true1), null, null, null); + tv_first_ailpay.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_false), null, null, null); + } else { + tv_first_ailpay.setVisibility(View.VISIBLE); + } + } + } + + private void changeLevel(int index) { + switch (index) { + case 0: + tv_first_one.setShadowLayer(3, 1, 1, Color.parseColor("#ff9d3e")); + tv_first_one.setPadding(SizeUtils.dp2px(46), SizeUtils.dp2px(18), 0, 0); + tv_first_two.setPadding(SizeUtils.dp2px(73), SizeUtils.dp2px(18), 0, 0); + tv_first_three.setPadding(SizeUtils.dp2px(80), SizeUtils.dp2px(18), 0, 0); + tv_first_one.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + tv_first_two.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_first_three.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_first_one.setBackgroundResource(R.drawable.ic_first_one); + tv_first_two.setBackgroundResource(R.drawable.ic_first_two); + tv_first_three.setBackgroundResource(R.drawable.ic_first_three); + tv_first_two.bringToFront(); + tv_first_one.bringToFront(); + setTextData(0); + selectLevelIndex = 0; + break; + case 1: + tv_first_two.setShadowLayer(3, 1, 1, Color.parseColor("#ff9d3e")); + tv_first_one.setPadding(SizeUtils.dp2px(16), SizeUtils.dp2px(18), 0, 0); + tv_first_two.setPadding(SizeUtils.dp2px(41), SizeUtils.dp2px(18), 0, 0); + tv_first_three.setPadding(SizeUtils.dp2px(80), SizeUtils.dp2px(18), 0, 0); + tv_first_two.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + tv_first_one.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_first_three.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_first_one.setBackgroundResource(R.drawable.ic_first_one2); + tv_first_two.setBackgroundResource(R.drawable.ic_first_two2); + tv_first_three.setBackgroundResource(R.drawable.ic_first_three2); + tv_first_two.bringToFront(); + setTextData(1); + + selectLevelIndex = 1; + break; + case 2: + tv_first_three.setShadowLayer(3, 1, 1, Color.parseColor("#ff9d3e")); + tv_first_one.setPadding(SizeUtils.dp2px(16), SizeUtils.dp2px(18), 0, 0); + tv_first_two.setPadding(SizeUtils.dp2px(30), SizeUtils.dp2px(18), 0, 0); + tv_first_three.setPadding(SizeUtils.dp2px(40), SizeUtils.dp2px(18), 0, 0); + tv_first_three.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + tv_first_one.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_first_two.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_first_one.setBackgroundResource(R.drawable.ic_first_one3); + tv_first_two.setBackgroundResource(R.drawable.ic_first_two3); + tv_first_three.setBackgroundResource(R.drawable.ic_first_three3); + tv_first_two.bringToFront(); + tv_first_three.bringToFront(); + setTextData(2); + + selectLevelIndex = 2; + break; + } + } + + private void setTextData(int i) { + mTvDescOne.setText(mGiftBagList.get(i).getExtend().get(0).getGive_new()); + mTvDescOne1.setText(mGiftBagList.get(i).getExtend().get(1).getGive()); + if (mGiftBagList.get(i).getExtend().get(0).getIs_limit_time() == 1) { + mIconLimitOne.setVisibility(View.VISIBLE); + } else { + mIconLimitOne.setVisibility(View.GONE); + } + if (mGiftBagList.get(i).getExtend().get(1).getIs_limit_time() == 1) { + mIconLimitOne1.setVisibility(View.VISIBLE); + } else { + mIconLimitOne1.setVisibility(View.GONE); + } + } + + private MyHandler mHandler; + + private static class MyHandler extends Handler { + WeakReference reference; + + public MyHandler(Activity activity) { + reference = new WeakReference<>(activity); + } + + @Override + public void handleMessage(Message msg) { + if (reference != null) { + if (msg.what == 101) { + EventBus.getDefault().post(new PayEvent(0)); + } + } + } + } + + private boolean isWXHF; + private String ghOriId; + private int mini_program_type; + + private void getWXPayType() { + SettingManager.getWechatPaySite((BaseActivity) mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WXPayTypeBean result, String tips) { + isWXHF = result.getWechat_type() == 3; + ghOriId = result.getGh_ori_id(); + mini_program_type = result.getMini_program_type(); + firstCharge(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void firstCharge() { + final RechargeListBean.GiftBagListBean rechargeBean = mGiftBagList.get(selectLevelIndex); + if (isWXHF && selectPayType.equals("wechat")) { + PayUtils.wxminiPay(mContext, rechargeBean.getId(), 2, ghOriId, mini_program_type); + StorageManager.getInstance(mContext).putString(Constans.FIRST_CHARGE_TYPE, selectPayType); + return; + } + SettingManager.payToRecharge((BaseActivity) mContext, selectPayType, mGiftBagList.get(selectLevelIndex).getId() + "", 2, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayBean result, String message) { + StorageManager.getInstance(mContext).putString(Constans.FIRST_CHARGE_TYPE, selectPayType); + if ("alipay".equals(selectPayType)) { + if (result.getPay_platform_type() == 1) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + Thread thread = new Thread(() -> { + PayTask alipay = new PayTask(activity); + Map result1 = alipay.payV2(mOrderInfo, true); + Message msg = new Message(); + msg.what = 101; + msg.obj = result1; + mHandler.sendMessage(msg); + }); + thread.start(); + } + } else if (result.getPay_platform_type() == 2) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + PayUtils.ailWeb(mOrderInfo, mContext); + } + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(mContext, PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + mContext.startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(mContext, result.getPayinfo()); + } else { + PayTypeSdk.getInstance().cashierPay(mContext, result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + } + }); + } + } else if ("wechat".equals(selectPayType)) { + if (result.getPay_platform_type() == 1) { + IWXAPI wxapi = WXAPIFactory.createWXAPI(mContext, Constant.WECHAT_APP_ID, false); + WeChatPayInfoBean wechatpayinfo = result.getWechatpayinfo(); + PayReq req = new PayReq(); + req.appId = Constant.WECHAT_APP_ID; + req.partnerId = wechatpayinfo.getMch_id(); //商户号 + req.prepayId = wechatpayinfo.getPrepay_id(); //预付款id + req.nonceStr = wechatpayinfo.getNonce_str(); + req.timeStamp = wechatpayinfo.getTimestamp() + ""; + req.packageValue = "Sign=WXPay"; //固定值 + req.sign = wechatpayinfo.getPaySign(); + boolean isWXAppInstalledAndSupported = wxapi.isWXAppInstalled(); + if (isWXAppInstalledAndSupported) { + wxapi.registerApp(Constant.WECHAT_APP_ID); + wxapi.sendReq(req); + } else { + MaleToast.showMessage(mContext, "未安装微信,不能支付"); + } + } else if (result.getPay_platform_type() == 2) { + PayTypeSdk.getInstance().cashierPay(mContext, result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + } + } + }); + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(activity, PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + activity.startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(mContext, result.getPayinfo()); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + Toast.makeText(activity, tip, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + Toast.makeText(activity, "支付出错", Toast.LENGTH_SHORT).show(); + } + }); +// new Handler().postDelayed(new Runnable() { +// @Override +// public void run() { +// dismiss(); +// } +// }, 2 * 1000); //延迟2秒执行 + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.cl_first_recharge: + dismiss(); + break; + case R.id.tv_first_one: + changeLevel(0); + break; + case R.id.tv_first_two: + changeLevel(1); + break; + case R.id.tv_first_three: + changeLevel(2); + break; + case R.id.tv_first_wechat: + selectPayType = "wechat"; + tv_first_wechat.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_true1), null, null, null); + tv_first_ailpay.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_false), null, null, null); + break; + case R.id.tv_first_ailpay: + selectPayType = "alipay"; + tv_first_ailpay.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_true1), null, null, null); + tv_first_wechat.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(mContext, R.drawable.ic_check_false), null, null, null); + break; + case R.id.confirm: + if (StrU.equals("wechat", selectPayType)) { + getWXPayType(); + } else { + firstCharge(); + } +// PayConfigBean result = new PayConfigBean(); +// result.setAlipay_switch("1"); +// result.setWechat_switch("1"); +// PayDialog mPayDialog = new PayDialog(mContext, R.style.SelectiveDialog, result); +// mPayDialog.setOnClickPayListener(new PayDialog.OnClickPayListener() { +// @Override +// public void onClickWeixinPayListener() { +// selectPayType = "wechat"; +// getWXPayType(); +// mPayDialog.dismiss(); +// FirstChargeGiftDialog.this.dismiss(); +// } +// +// @Override +// public void onClickAliPayListener() { +// selectPayType = "alipay"; +// firstCharge(); +// mPayDialog.dismiss(); +// FirstChargeGiftDialog.this.dismiss(); +// } +// }); +// mPayDialog.show(); + break; + } + } + + private void showTipsDialog() { +// Activity currActivity = ActivityStackManager.getInstance().currentActivity(); +// if (currActivity instanceof CoinRechargeActivity) { +// return; +// } +// CustomAlertDialog dialog = new CustomAlertDialog(currActivity); +// dialog.setLeftBtnText("去充值"); +// dialog.setRightBtnText("免费领金币"); +// dialog.setContent("放弃充值将错过与TA的缘分哦~\n\n还可通过做任务领取金币"); +// dialog.setTitle("免费领金币"); +// dialog.setOnDialogClickListener(new CustomAlertDialog.OnDialogLeftClickListener() { +// @Override +// public void leftClick() { +// Intent intent = new Intent(currActivity, CoinRechargeActivity.class); +// ActivityStackManager.getInstance().currentActivity().startActivity(intent); +// } +// }, new CustomAlertDialog.OnDialogRightClickListener() { +// @Override +// public void rightClick() { +// Intent intent = new Intent(currActivity, TaskCenterActivity.class); +// ActivityStackManager.getInstance().currentActivity().startActivity(intent); +// } +// }); +// dialog.show(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/GuardDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/GuardDialog.java new file mode 100644 index 0000000..46b08e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/GuardDialog.java @@ -0,0 +1,174 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.utils.StrU; + +/** + * Created by zhangbin on 2019/12/16. + */ +public class GuardDialog extends Dialog implements View.OnClickListener { + + private Context mContext; + private SimpleDraweeView iv_guard_user_avatar1; + private SimpleDraweeView iv_guard_user_avatar; + private ImageView iv_guard_top; + private View mIv_finish_dialog; + private TextView mTv_title1; + private TextView mTv_count1; + private TextView mTv_count2; + private TextView mTv_count3; + private TextView mTv_rank; + private Button mBt_guard; + + private int count = 1; + private int price; + private String rank; + private String toAvatar; + private String fromAvatar; + + public GuardDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public GuardDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected GuardDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_guard); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + + mIv_finish_dialog = findViewById(R.id.rl_finish); + mTv_title1 = findViewById(R.id.tv_title1); + mTv_count1 = findViewById(R.id.tv_count1); + mTv_count2 = findViewById(R.id.tv_count2); + mTv_count3 = findViewById(R.id.tv_count3); + mTv_rank = findViewById(R.id.tv_rank); + mBt_guard = findViewById(R.id.bt_guard); + iv_guard_user_avatar1 = findViewById(R.id.iv_guard_user_avatar1); + iv_guard_user_avatar = findViewById(R.id.iv_guard_user_avatar); + iv_guard_top = findViewById(R.id.iv_guard_top); + + mIv_finish_dialog.setOnClickListener(this); + mBt_guard.setOnClickListener(this); + mTv_count1.setOnClickListener(this); + mTv_count2.setOnClickListener(this); + mTv_count3.setOnClickListener(this); + + if (null != mTv_title1) { + String s = "花费" + price + "金币给Ta 1 个守护符"; + StrU.setSpanTextColor(s, s.length() - 6, s.length() - 5, mTv_title1, R.color.guard_color1, mContext); + } + + if (null != mTv_rank) { + String s = "我距离成为Ta的守护天使还差" + rank + "个"; + StrU.setSpanTextColor(s, s.length() - rank.length() - 1, s.length() - 1, mTv_rank, R.color.guard_color1, mContext); + } + + if (!StrU.isEmpty(toAvatar)) { + iv_guard_user_avatar.setImageURI(StrU.getResourcePath(toAvatar, mContext)); + } + if (!StrU.isEmpty(fromAvatar)) { + iv_guard_user_avatar1.setImageURI(StrU.getResourcePath(fromAvatar, mContext)); + iv_guard_top.setImageResource(R.drawable.ic_guard_top); + } else { + iv_guard_top.setImageResource(R.drawable.guard_0060); + } + } + + public void setData(int price, String rank, String toAvatar, String fromAvatar) { + this.price = price; + this.rank = rank; + this.toAvatar = toAvatar; + this.fromAvatar = fromAvatar; + } + + @Override + public void onClick(View view) { + if (view == mIv_finish_dialog) { + dismiss(); + } else if (view == mTv_count1) { + count = 1; + mTv_count1.setBackgroundResource(R.drawable.shape_guard_select_bg); + mTv_count2.setBackgroundResource(R.drawable.shape_guard_select_no_bg); + mTv_count3.setBackgroundResource(R.drawable.shape_guard_select_no_bg); + + mTv_count1.setTextColor(mContext.getResources().getColor(R.color.guard_color1)); + mTv_count2.setTextColor(mContext.getResources().getColor(R.color.three_text)); + mTv_count3.setTextColor(mContext.getResources().getColor(R.color.three_text)); + int allPrice = price * count; + String s = "花费" + allPrice + "金币给Ta " + count + " 个守护符"; + StrU.setSpanTextColor(s, s.length() - 5 - String.valueOf(count).length(), s.length() - 5, mTv_title1, R.color.guard_color1, mContext); + } else if (view == mTv_count2) { + count = 52; + mTv_count1.setBackgroundResource(R.drawable.shape_guard_select_no_bg); + mTv_count2.setBackgroundResource(R.drawable.shape_guard_select_bg); + mTv_count3.setBackgroundResource(R.drawable.shape_guard_select_no_bg); + + mTv_count1.setTextColor(mContext.getResources().getColor(R.color.three_text)); + mTv_count2.setTextColor(mContext.getResources().getColor(R.color.guard_color1)); + mTv_count3.setTextColor(mContext.getResources().getColor(R.color.three_text)); + + int allPrice = price * count; + String s = "花费" + allPrice + "金币给Ta " + count + " 个守护符"; + StrU.setSpanTextColor(s, s.length() - 5 - String.valueOf(count).length(), s.length() - 5, mTv_title1, R.color.guard_color1, mContext); + } else if (view == mTv_count3) { + count = 99; + mTv_count1.setBackgroundResource(R.drawable.shape_guard_select_no_bg); + mTv_count2.setBackgroundResource(R.drawable.shape_guard_select_no_bg); + mTv_count3.setBackgroundResource(R.drawable.shape_guard_select_bg); + + mTv_count1.setTextColor(mContext.getResources().getColor(R.color.three_text)); + mTv_count2.setTextColor(mContext.getResources().getColor(R.color.three_text)); + mTv_count3.setTextColor(mContext.getResources().getColor(R.color.guard_color1)); + + int allPrice = price * count; + String s = "花费" + allPrice + "金币给Ta " + count + " 个守护符"; + StrU.setSpanTextColor(s, s.length() - 5 - String.valueOf(count).length(), s.length() - 5, mTv_title1, R.color.guard_color1, mContext); + } else if (view == mBt_guard) { + if (null != mOnClickGuard) { + mOnClickGuard.onClickGuard(count, price + ""); + } + } + } + + private OnClickGuard mOnClickGuard; + + public void setOnClickGuard(OnClickGuard onClickGuard) { + mOnClickGuard = onClickGuard; + } + + public interface OnClickGuard { + void onClickGuard(int count, String price); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/HangUpDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/HangUpDialog.java new file mode 100644 index 0000000..f9ee9bf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/HangUpDialog.java @@ -0,0 +1,101 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.utils.StrU; + +/** + * Created by zhangbin on 2019/5/22. + */ + +public class HangUpDialog extends Dialog { + private Context mContext; + private TextView tv_dialog_tips_title; + private TextView tv_dialog_tips_sure; + private TextView tv_dialog_tips_cancel; + + private OnHangUpListener listener; + private String title, sure, cancel; + + public HangUpDialog(@NonNull Context context, OnHangUpListener listener, String title, String sure, String cancel) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.listener = listener; + this.title = title; + this.sure = sure; + this.cancel = cancel; + } + + public HangUpDialog(@NonNull Context context, OnHangUpListener listener) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.listener = listener; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_hang_up); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + setCancelable(true); + } + + private void initView() { + tv_dialog_tips_title = findViewById(R.id.tv_dialog_tips_title); + tv_dialog_tips_cancel = findViewById(R.id.tv_dialog_tips_cancel); + tv_dialog_tips_sure = findViewById(R.id.tv_dialog_tips_sure); + + if (!StrU.isEmpty(title)) { + tv_dialog_tips_title.setText(title); + } + if (!StrU.isEmpty(sure)) { + tv_dialog_tips_sure.setText(sure); + } + if (!StrU.isEmpty(cancel)) { + tv_dialog_tips_cancel.setText(cancel); + } + + tv_dialog_tips_cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + tv_dialog_tips_sure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onHangUp(); + } + dismiss(); + } + }); + } + + public void setTitle(String title, String sure, String cancel) { + tv_dialog_tips_title.setText(title); + tv_dialog_tips_sure.setText(sure); + tv_dialog_tips_cancel.setText(cancel); + } + + public interface OnHangUpListener { + void onHangUp(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/HelpTipsDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/HelpTipsDialog.java new file mode 100644 index 0000000..24593c6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/HelpTipsDialog.java @@ -0,0 +1,83 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.blankj.utilcode.util.ClipboardUtils; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.login.bean.CustomerTipBean; +import com.fengliyan.uikit.toast.MaleToast; + +/** + * Created by zhangbin on 2019/5/22. + */ + +public class HelpTipsDialog extends Dialog { + private Context mContext; + private TextView tv_dialog_tips_title; + private TextView tv_dialog_tips_email; + private TextView tv_dialog_tips_msg1; + private TextView tv_dialog_tips_msg2; + private TextView tv_dialog_tips_sure; + + private CustomerTipBean bean; + + public HelpTipsDialog(@NonNull Context context, CustomerTipBean bean) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.bean = bean; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_help_tips); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + tv_dialog_tips_title = findViewById(R.id.tv_dialog_tips_title); + tv_dialog_tips_msg1 = findViewById(R.id.tv_dialog_tips_msg1); + tv_dialog_tips_msg2 = findViewById(R.id.tv_dialog_tips_msg2); + tv_dialog_tips_email = findViewById(R.id.tv_dialog_tips_email); + tv_dialog_tips_sure = findViewById(R.id.tv_dialog_tips_sure); + + if (bean != null) { + tv_dialog_tips_title.setText(bean.getTitle()); + if (bean.getContent() != null && bean.getContent().size() > 0) { + tv_dialog_tips_msg1.setText(bean.getContent().get(0)); + tv_dialog_tips_email.setText(bean.getContent().get(1)); + tv_dialog_tips_msg2.setText(bean.getContent().get(2)); + } + } + tv_dialog_tips_email.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ClipboardUtils.copyText(tv_dialog_tips_email.getText()); + MaleToast.showMessage(mContext, "复制成功"); + } + }); + + tv_dialog_tips_sure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/KidDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/KidDialog.java new file mode 100644 index 0000000..81ee522 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/KidDialog.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.main.KidModelActivity; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class KidDialog extends Dialog implements View.OnClickListener { + + private Context mContext; + private TextView mTv_set_kid; + private Button mBt_know; + + public KidDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public KidDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected KidDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_kid); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + + mTv_set_kid = findViewById(R.id.tv_set_kid); + mBt_know = findViewById(R.id.bt_know); + + mTv_set_kid.setOnClickListener(this); + mBt_know.setOnClickListener(this); + + } + + + @Override + public void onClick(View view) { + if (view == mBt_know) { + dismiss(); + }else if (view == mTv_set_kid) { + dismiss(); + Intent intent = new Intent(mContext, KidModelActivity.class); + mContext.startActivity(intent); + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/KidOpenDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/KidOpenDialog.java new file mode 100644 index 0000000..1c27145 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/KidOpenDialog.java @@ -0,0 +1,74 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.main.KidForgetPasswordActivity; +import com.fengliyan.tianlesue.view.main.KidInputPasswordActivity; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class KidOpenDialog extends Dialog implements View.OnClickListener { + + private Context mContext; + private TextView tv_forget; + private TextView mBt_know; + + public KidOpenDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public KidOpenDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected KidOpenDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_kid_open); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + + tv_forget = findViewById(R.id.tv_forget); + mBt_know = findViewById(R.id.bt_know); + + tv_forget.setOnClickListener(this); + mBt_know.setOnClickListener(this); + + } + + + @Override + public void onClick(View view) { + if (view == mBt_know) { //关闭青少年模式 + Intent intent = new Intent(mContext, KidInputPasswordActivity.class); + mContext.startActivity(intent); + }else if (view == tv_forget) { + Intent intent = new Intent(mContext, KidForgetPasswordActivity.class); + mContext.startActivity(intent); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryNineDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryNineDialog.java new file mode 100644 index 0000000..3aededb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryNineDialog.java @@ -0,0 +1,257 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.view.Window; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.PrizeBean; +import com.fengliyan.tianlesue.model.main.VideoRequestDataBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.Random; + + +public class LotteryNineDialog extends Dialog implements View.OnClickListener { + private static final String TAG = "LotteryNineDialog"; + private Activity mContext; + + private ConstraintLayout cl_prize; + private ImageView[] itemViews = new ImageView[9]; + private ImageView iv_prize_bg; + private ImageView startLotteryBtn; + private ImageView iv_rules; + private boolean isRunning = false; // 抽奖是否正在进行 + private final VideoRequestDataBean dataBean; + private int prize_type; + private String prize_title, prize_name, prize_url; + + // 奖品资源数组(可以根据实际奖品调整) + private int[] prizeResources = { + R.drawable.ic_video_gift, + R.drawable.ic_video_gift, + R.drawable.ic_video_gift, + R.drawable.ic_video_gift, + R.drawable.ic_video_gift, + R.drawable.ic_video_gift, + R.drawable.ic_video_gift, + R.drawable.ic_video_gift + }; + + public LotteryNineDialog(@NonNull Activity context, VideoRequestDataBean dataBean) { + super(context); + mContext = context; + this.dataBean = dataBean; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_lottery); + Window window = this.getWindow(); + if (window != null) { + window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + setCanceledOnTouchOutside(true); + initView(); + } + + private void initView() { + // 初始化九宫格视图 + cl_prize = findViewById(R.id.cl_prize); + itemViews[0] = findViewById(R.id.item_0); + itemViews[1] = findViewById(R.id.item_1); + itemViews[2] = findViewById(R.id.item_2); + itemViews[3] = findViewById(R.id.item_3); + itemViews[4] = findViewById(R.id.item_4); + itemViews[5] = findViewById(R.id.item_5); + itemViews[6] = findViewById(R.id.item_6); + itemViews[7] = findViewById(R.id.item_7); + itemViews[8] = findViewById(R.id.item_8); + startLotteryBtn = findViewById(R.id.start_lottery_btn); + iv_rules = findViewById(R.id.iv_rules); + iv_prize_bg = findViewById(R.id.iv_prize_bg); + iv_prize_bg.setOnClickListener(this); + cl_prize.setOnClickListener(this); + iv_rules.setOnClickListener(this); + startLotteryBtn.setOnClickListener(this); + } + + private void startTurntable() { + MainManager.startTreasureHunt((BaseActivity) mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PrizeBean result, String message) { + //奖品类型0=谢谢参与1=金币2=免费视频卡3=免费聊天卡4超级会员 + prize_type = result.getPrize_type(); + switch (prize_type) { + case 0: + prize_title = "谢谢参与"; + break; + case 1: + prize_title = "恭喜抽中福气红包"; + break; + case 2: + prize_title = "恭喜抽中视频卡"; + break; + case 3: + prize_title = "恭喜抽中聊天卡"; + break; + case 4: + prize_title = "恭喜抽中会员卡"; + break; + } + prize_name = result.getPrize_name(); + if (!StrU.isEmpty(result.getPrize_url())) { + prize_url = ConstUrl.BASE_ROOT + result.getPrize_url(); + } + if (!isRunning) { + startLottery(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + startLotteryBtn.setEnabled(true); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + startLotteryBtn.setEnabled(true); + } + }); + } + + + private void startLottery() { + isRunning = true; + // 重置所有项目的背景色(清除上一次的高亮状态) + resetAllItemBackgrounds(); + // 随机选择获奖位置 + Random random = new Random(); + int winningPosition = random.nextInt(9); // 0-8 + // 开始滚动动画 + runRollingAnimationWithPropertyAnim(winningPosition); + } + + // 添加重置所有项目背景的方法 + private void resetAllItemBackgrounds() { + for (int i = 0; i < 9; i++) { + itemViews[i].setBackgroundResource(0); + } + } + + private void runRollingAnimationWithPropertyAnim(final int winningPosition) { + ValueAnimator animator = ValueAnimator.ofInt(0, 27 + winningPosition); + animator.setDuration(3000); // 总动画时间3秒 + animator.setInterpolator(new AccelerateDecelerateInterpolator()); + + final int[] lastHighlighted = {-1}; // 记录上一个高亮的位置 + animator.addUpdateListener(animation -> { + int value = (int) animation.getAnimatedValue(); + int position = value % 9; + // 清除之前的高亮 + if (lastHighlighted[0] >= 0 && lastHighlighted[0] != position) { + itemViews[lastHighlighted[0]].setBackgroundResource(0); + } + + // 高亮当前位置 + itemViews[position].setBackgroundResource(R.drawable.ic_prize_select); + + lastHighlighted[0] = position; + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + // 动画结束后执行闪烁效果 + performBlinkingEffect(winningPosition); + } + }); + animator.start(); + } + + /** + * 执行闪烁效果:闪烁两次后再设置最终高亮状态 + */ + private void performBlinkingEffect(final int winningPosition) { + final Handler handler = new Handler(); + Runnable blinkingRunnable = new Runnable() { + private int count = 0; + private final int maxBlinks = 4; // 闪烁2次,每次包含亮起和熄灭两个状态 + + @Override + public void run() { + if (count < maxBlinks) { + if (count % 2 == 0) { + // 亮起状态 - 绿色高亮 + itemViews[winningPosition].setBackgroundResource(R.drawable.ic_prize_select); + } else { + // 熄灭状态 - 透明背景 + itemViews[winningPosition].setBackgroundResource(0); + } + count++; + // 每200毫秒切换一次状态,实现闪烁效果 + handler.postDelayed(this, 200); + } else { + // 闪烁完成后设置最终的高亮状态 + itemViews[winningPosition].setBackgroundResource(R.drawable.ic_prize_select); + + // 恢复按钮状态 + isRunning = false; + startLotteryBtn.setEnabled(true); + LotteryWinDialog dialog = new LotteryWinDialog(mContext, prize_type == 0 ? 1 : 0, prize_title, prize_name, prize_url, ConstUrl.BASE_ROOT + dataBean.getPrize_url()); + dialog.show(); + isType = !isType; + } + } + }; + // 开始闪烁 + handler.post(blinkingRunnable); + } + + private boolean isType; + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.cl_prize: + dismiss(); + break; + case R.id.iv_rules: + Intent intentH5 = new Intent(mContext, BaseWebViewActivity.class); + intentH5.putExtra("ClickUrl", ConstUrl.BASE_ROOT + dataBean.getRule_url()); + mContext.startActivity(intentH5); + break; + case R.id.start_lottery_btn: + startLotteryBtn.setEnabled(false); + startTurntable(); +// if (!isRunning) { +// startLottery(); +// } + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryView.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryView.java new file mode 100644 index 0000000..80c5e16 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryView.java @@ -0,0 +1,203 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.DecelerateInterpolator; + +import com.fengliyan.tianlesue.view.diooto.tools.Utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + + +public class LotteryView extends View { + + private List prizeNames = new ArrayList<>(); + private List prizeIcons = new ArrayList<>(); + + private Paint sectorPaint, textPaint; + private int itemCount = 6; + private float startAngle = 0; + private boolean isRotating = false; + private int selectedIndex = -1; + private OnLotteryEndListener listener; + + // 闪烁动画状态 + private boolean flashing = false; + private boolean flashRedPhase = false; + + // 参数 + private int imageSize = Utils.dip2px(getContext(), 30); + private int textArcRadiusOffset = Utils.dip2px(getContext(), 22); + private int imageRadiusOffset = Utils.dip2px(getContext(), 50); // 图片更靠外 + private int textSize = Utils.dip2px(getContext(), 14); + + public LotteryView(Context context, AttributeSet attrs) { + super(context, attrs); + initPaints(); + + // 默认数据 + for (int i = 0; i < itemCount; i++) { + prizeNames.add("奖品" + (i + 1)); + prizeIcons.add(null); + } + } + + private void initPaints() { + sectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + sectorPaint.setStyle(Paint.Style.FILL); + + textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(Color.BLACK); + textPaint.setTextSize(textSize); + textPaint.setTextAlign(Paint.Align.CENTER); + } + + /** + * 设置奖品数据 + */ + public void setPrizeData(List names, List icons) { + this.prizeNames = names; + this.prizeIcons = icons; + this.itemCount = names.size(); + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + int cx = getWidth() / 2; + int cy = getHeight() / 2; + int radius = Math.min(cx, cy) - 10; + float sweep = 360f / itemCount; + + // === 绘制每个奖项 === + for (int i = 0; i < itemCount; i++) { + boolean isWinner = flashing && i == selectedIndex; + + // 红色闪烁 + if (isWinner && flashRedPhase) { + sectorPaint.setColor(Color.parseColor("#EAAA90")); + } else { + sectorPaint.setColor(i % 2 == 0 ? + Color.parseColor("#FFF6E2") : Color.parseColor("#FFECBF")); + } + + // 绘制扇形 + canvas.save(); + canvas.rotate(startAngle + i * sweep, cx, cy); + canvas.drawArc(cx - radius, cy - radius, cx + radius, cy + radius, + 0, sweep, true, sectorPaint); + canvas.restore(); + + // 当前扇形中心角 + float midAngle = startAngle + i * sweep + sweep / 2; + + // ===== 绘制奖品图片(在文字上方) ===== + Bitmap bmp = prizeIcons.size() > i ? prizeIcons.get(i) : null; + if (bmp != null) { + Bitmap scaled = Bitmap.createScaledBitmap(bmp, imageSize, imageSize, false); + + float rad = (float) Math.toRadians(midAngle); + float imgCenterX = (float) (cx + (radius - imageRadiusOffset) * Math.cos(rad)); + float imgCenterY = (float) (cy + (radius - imageRadiusOffset) * Math.sin(rad)); + + canvas.save(); + // 旋转画布使图片方向与扇形一致 + canvas.rotate(midAngle + 90, imgCenterX, imgCenterY); + canvas.drawBitmap(scaled, imgCenterX - imageSize / 2f, imgCenterY - imageSize / 2f, null); + canvas.restore(); + } + + // ===== 绘制文字(沿弧形方向,在图片下方) ===== + float textArcRadius = radius - textArcRadiusOffset; + RectF arcRect = new RectF(cx - textArcRadius, cy - textArcRadius, + cx + textArcRadius, cy + textArcRadius); + + Path textPath = new Path(); + textPath.addArc(arcRect, midAngle - sweep / 2 + 10, sweep - 20); + canvas.drawTextOnPath(prizeNames.get(i), textPath, 0, 0, textPaint); + } + } + + /** + * 🎯 开始旋转 + * + * @param winIndex 可指定中奖索引(0 ~ itemCount-1),传 -1 表示随机 + */ + public void startSpin(int winIndex) { + if (isRotating) return; + isRotating = true; + + if (winIndex >= 0 && winIndex < itemCount) { + selectedIndex = winIndex; + } else { + selectedIndex = new Random().nextInt(itemCount); + } + + float sweep = 360f / itemCount; + // 停止时中奖扇形居于正上方(270°) + float targetAngle = 360 * 6 + (270 - (selectedIndex * sweep + sweep / 2)); + + ObjectAnimator animator = ObjectAnimator.ofFloat(this, "rotation", 0, targetAngle); + animator.setDuration(5000); + animator.setInterpolator(new DecelerateInterpolator()); + + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isRotating = false; + startRedFlash(selectedIndex); + if (listener != null) listener.onLotteryEnd(selectedIndex); + } + }); + animator.start(); + } + + /** + * 🔥 红色闪烁动画 + */ + private void startRedFlash(int index) { + flashing = true; + ValueAnimator flash = ValueAnimator.ofInt(0, 5); + flash.setDuration(1000); + flash.addUpdateListener(a -> { + int phase = (int) a.getAnimatedValue(); + flashRedPhase = (phase % 2 == 0); + invalidate(); + }); + flash.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + flashing = false; + invalidate(); + } + }); + flash.start(); + } + + public boolean isRotating() { + return isRotating; + } + + public void setOnLotteryEndListener(OnLotteryEndListener l) { + this.listener = l; + } + + public interface OnLotteryEndListener { + void onLotteryEnd(int index); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryWinDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryWinDialog.java new file mode 100644 index 0000000..5e8c11b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LotteryWinDialog.java @@ -0,0 +1,102 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; + + +public class LotteryWinDialog extends Dialog implements View.OnClickListener { + private static final String TAG = "LotteryWinDialog"; + private Activity mContext; + private FrameLayout fl_prize; + private LinearLayout lin_win_prize; + private ImageView iv_prize_img; + private TextView tv_win_prize_title; + private TextView tv_win_prize_name; + private TextView tv_prize; + private ImageView iv_win_prize_sure; + private LinearLayout lin_thank_you; + private int type; + private String title; + private String name; + private String img; + private String prize_url; + + public LotteryWinDialog(@NonNull Activity context, int type, String title, String name, String img, String prize_url) { + super(context); + mContext = context; + this.type = type; + this.title = title; + this.name = name; + this.img = img; + this.prize_url = prize_url; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_lottery_win_prize); + Window window = this.getWindow(); + if (window != null) { + window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + setCanceledOnTouchOutside(true); + initView(); + } + + private void initView() { + fl_prize = findViewById(R.id.fl_prize); + lin_win_prize = findViewById(R.id.lin_win_prize); + iv_prize_img = findViewById(R.id.iv_prize_img); + tv_win_prize_title = findViewById(R.id.tv_win_prize_title); + tv_win_prize_name = findViewById(R.id.tv_win_prize_name); + tv_prize = findViewById(R.id.tv_prize); + iv_win_prize_sure = findViewById(R.id.iv_win_prize_sure); + lin_thank_you = findViewById(R.id.lin_thank_you); + fl_prize.setOnClickListener(this); + tv_prize.setOnClickListener(this); + iv_win_prize_sure.setOnClickListener(this); + + if (type == 1) { + lin_thank_you.setVisibility(View.VISIBLE); + lin_win_prize.setVisibility(View.GONE); + } else { + lin_win_prize.setVisibility(View.VISIBLE); + lin_thank_you.setVisibility(View.GONE); + tv_win_prize_title.setText(title); + tv_win_prize_name.setText(name); + Glide.with(mContext).load(img).into(iv_prize_img); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.fl_prize: + case R.id.iv_win_prize_sure: + dismiss(); + break; + case R.id.tv_prize: + Intent intentH5 = new Intent(mContext, BaseWebViewActivity.class); + intentH5.putExtra("ClickUrl", prize_url); + mContext.startActivity(intentH5); + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LuckPrizeDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LuckPrizeDialog.java new file mode 100644 index 0000000..c78fb64 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LuckPrizeDialog.java @@ -0,0 +1,84 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Activity; +import android.app.Dialog; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; + + +public class LuckPrizeDialog extends Dialog implements View.OnClickListener { + private static final String TAG = "LuckPrizeDialog"; + private Activity mContext; + private LinearLayout lin_win_prize; + private ImageView iv_prize_img; + private TextView tv_win_prize_name; + private ImageView iv_win_prize_sure; + private LinearLayout lin_thank_you; + private ImageView iv_close; + private int type; + private String name; + private String img; + + public LuckPrizeDialog(@NonNull Activity context, int type, String name, String img) { + super(context); + mContext = context; + this.type = type; + this.name = name; + this.img = img; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_luck_win_prize); + Window window = this.getWindow(); + if (window != null) { + window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + setCanceledOnTouchOutside(false); + initView(); + } + + private void initView() { + lin_win_prize = findViewById(R.id.lin_win_prize); + iv_prize_img = findViewById(R.id.iv_prize_img); + tv_win_prize_name = findViewById(R.id.tv_win_prize_name); + iv_win_prize_sure = findViewById(R.id.iv_win_prize_sure); + lin_thank_you = findViewById(R.id.lin_thank_you); + iv_close = findViewById(R.id.iv_close); + iv_win_prize_sure.setOnClickListener(this); + iv_close.setOnClickListener(this); + + if (type == 1) { + lin_thank_you.setVisibility(View.VISIBLE); + lin_win_prize.setVisibility(View.GONE); + } else { + lin_win_prize.setVisibility(View.VISIBLE); + lin_thank_you.setVisibility(View.GONE); + tv_win_prize_name.setText(name); + Glide.with(mContext).load(img).into(iv_prize_img); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_win_prize_sure: + case R.id.iv_close: + dismiss(); + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LuckWheelDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LuckWheelDialog.java new file mode 100644 index 0000000..368f20a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/LuckWheelDialog.java @@ -0,0 +1,234 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.CustomTarget; +import com.bumptech.glide.request.transition.Transition; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.PrizeBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.settings.MyItemsActivity; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + + +public class LuckWheelDialog extends Dialog implements View.OnClickListener { + private static final String TAG = "LuckWheelDialog"; + private Activity mContext; + private TextView tvCount; + private ImageView iv_msg; + private TextView tv_rules; + private TextView tv_item; + private LotteryView wheel_view; + private ImageView start; + private ImageView iv_close; + private List mListBitmap = new ArrayList<>(); + private List mPrizeList = new ArrayList<>(); + private String ruleUrl; + private String activityUrl; + private int surplusNum; + + public LuckWheelDialog(@NonNull Activity context) { + super(context); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_luck_wheel); + Window window = this.getWindow(); + if (window != null) { + window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + setCanceledOnTouchOutside(false); + initView(); + getTurntable(); + } + + private void initView() { + wheel_view = findViewById(R.id.wheel_view); + iv_msg = findViewById(R.id.iv_msg); + tv_rules = findViewById(R.id.tv_rules); + tv_item = findViewById(R.id.tv_item); + tvCount = findViewById(R.id.tv_count); + start = findViewById(R.id.start); + iv_close = findViewById(R.id.iv_close); + wheel_view.setOnClickListener(this); + tv_rules.setOnClickListener(this); + tv_item.setOnClickListener(this); + start.setOnClickListener(this); + iv_close.setOnClickListener(this); + } + + private void getTurntable() { + MainManager.getTurntable((BaseActivity) mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PrizeBean result, String message) { + if (result != null) { + surplusNum = result.getSurplus_num(); + tvCount.setText("剩余" + result.getSurplus_num() + "次"); + ruleUrl = ConstUrl.BASE_ROOT + result.getRule_url(); + activityUrl = ConstUrl.BASE_ROOT + result.getActivity_url(); + Glide.with(mContext).load(ConstUrl.BASE_ROOT + result.getBg()).into(iv_msg); + if (result.getPrize_detail() != null && result.getPrize_detail().size() > 0) { + mPrizeList = result.getPrize_detail(); + mListBitmap.clear(); + List names = new ArrayList<>(); + for (int i = 0; i < mPrizeList.size(); i++) { + //文字 + names.add(mPrizeList.get(i).getPrize_name()); + //图标 + Glide.with(mContext) + .asBitmap() + .load(ConstUrl.BASE_ROOT + mPrizeList.get(i).getPrize_url()) + .into(new CustomTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, + @Nullable Transition transition) { + mListBitmap.add(resource); + if (mListBitmap.size() == mPrizeList.size()) { + wheel_view.setPrizeData(names, mListBitmap); + } + } + + @Override + public void onLoadCleared(@Nullable Drawable placeholder) { + } + }); + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private void startTurntable() { + MainManager.startTurntable((BaseActivity) mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PrizeBean result, String message) { + if (result != null) { + surplusNum = result.getSurplus_num(); + tvCount.setText("剩余" + result.getSurplus_num() + "次"); + for (int i = 0; i < mPrizeList.size(); i++) { + if (StrU.equals(mPrizeList.get(i).getPrize_id(), result.getPrize_id())) { + wheel_view.startSpin(i); + break; + } + } + wheel_view.setOnLotteryEndListener(new LotteryView.OnLotteryEndListener() { + @Override + public void onLotteryEnd(int index) { + LuckPrizeDialog luckPrizeDialog; + if (StrU.equals("1", result.getPrize_id())) { + luckPrizeDialog = new LuckPrizeDialog(activity, 1, result.getPrize_name(), ConstUrl.BASE_ROOT + result.getPrize_url()); + } else { + luckPrizeDialog = new LuckPrizeDialog(activity, 0, result.getPrize_name(), ConstUrl.BASE_ROOT + result.getPrize_url()); + } + luckPrizeDialog.show(); + } + }); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_rules: + Intent intentH5 = new Intent(mContext, BaseWebViewActivity.class); + intentH5.putExtra("ClickUrl", ruleUrl); + mContext.startActivity(intentH5); + break; + case R.id.start: + if (StrU.isFastClick()) { + if (surplusNum > 0) { + int index = new Random().nextInt(6); + if (!wheel_view.isRotating()) { +// wheel_view.startSpin(index); + startTurntable(); + } +// wheel_view.setOnLotteryEndListener(new LotteryView.OnLotteryEndListener() { +// @Override +// public void onLotteryEnd(int index) { +// LuckPrizeDialog luckPrizeDialog; +// if (index == 1) { +// luckPrizeDialog = new LuckPrizeDialog(mContext, 1, mPrizeList.get(index).getPrize_name(), ConstUrl.BASE_ROOT + mPrizeList.get(index).getPrize_url()); +// } else { +// luckPrizeDialog = new LuckPrizeDialog(mContext, 0, mPrizeList.get(index).getPrize_name(), ConstUrl.BASE_ROOT + mPrizeList.get(index).getPrize_url()); +// } +// luckPrizeDialog.show(); +// } +// }); + } else { + Intent intent = new Intent(mContext, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", activityUrl); + mContext.startActivity(intent); + } + } + break; + case R.id.iv_close: + dismiss(); + break; + case R.id.wheel_view: + if (StrU.isFastClick()) { + if (surplusNum == 0) { + Intent intent = new Intent(mContext, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", activityUrl); + mContext.startActivity(intent); + } + } + break; + case R.id.tv_item: + Intent intent = new Intent(mContext, MyItemsActivity.class); + mContext.startActivity(intent); + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MaleToastUtil.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MaleToastUtil.java new file mode 100644 index 0000000..e23f0c5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MaleToastUtil.java @@ -0,0 +1,41 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.content.Context; + +import com.fengliyan.uikit.toast.MaleToast; + +/** + * Created by ChenQihong on 2016/12/17. + */ + +public class MaleToastUtil { + + /** + * 弹出消息 + * + * @param msg 消息内容 + */ + public static void showMessage(Context context, CharSequence msg) { + MaleToast.showMessage(context, msg); + } + + + /** + * 显示一个成功的消息 + * + * @param msg 消息内容,由于需要图标和文字显示比较协调美观,请不要显示过长的消息 + */ + public static void showSuccessMsg(Context context, CharSequence msg) { + MaleToast.showSuccessMsg(context, msg); + } + + /** + * 显示一个带失败图标的消息 + * + * @param msg 消息内容,由于需要图标和文字显示比较协调美观,请不要显示过长的消息 + */ + public static void showFailureMsg(Context context, CharSequence msg) { + MaleToast.showFailureMsg(context, msg); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberPayDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberPayDialog.java new file mode 100644 index 0000000..fd84f3d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberPayDialog.java @@ -0,0 +1,174 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.CheckBox; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.settings.PayConfigBean; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; + +/** + * Created by zhangbin on 2019/5/22. + */ + +public class MemberPayDialog extends Dialog { + + private Context mContext; + private LinearLayout selector_layout; + private TextView tv_member_pay_name; + private LinearLayout ll_weixin; + private CheckBox cb_wechat_pay; + private LinearLayout ll_alipay; + private CheckBox cb_alipay; + private LinearLayout ll_member_check; + private CheckBox cb_member_check; + private TextView tv_member_content; + private TextView tv_dialog_member_hint; + private TextView tv_member_pay; + + private PayConfigBean config; + private String mSelectedPayMethod = "alipay"; + private String goodsName; + + public MemberPayDialog(@NonNull Context context, PayConfigBean config, String goodsName) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.config = config; + this.goodsName = goodsName; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_member_pay); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + selector_layout = findViewById(R.id.selector_layout); + tv_member_pay_name = findViewById(R.id.tv_member_pay_name); + ll_weixin = findViewById(R.id.ll_weixin); + cb_wechat_pay = findViewById(R.id.cb_wechat_pay); + ll_alipay = findViewById(R.id.ll_alipay); + cb_alipay = findViewById(R.id.cb_alipay); + ll_member_check = findViewById(R.id.ll_member_check); + cb_member_check = findViewById(R.id.cb_member_check); + tv_member_content = findViewById(R.id.tv_member_content); + tv_dialog_member_hint = findViewById(R.id.tv_dialog_member_hint); + tv_member_pay = findViewById(R.id.tv_member_pay); + if (!"1".equals(config.getWechat_switch()) && !"1".equals(config.getAlipay_switch())) { + tv_dialog_member_hint.setVisibility(View.VISIBLE); + tv_member_pay.setVisibility(View.GONE); + } else { + tv_dialog_member_hint.setVisibility(View.GONE); + tv_member_pay.setVisibility(View.VISIBLE); + if (!"1".equals(config.getWechat_switch())) { + ll_weixin.setVisibility(View.GONE); + mSelectedPayMethod = "alipay"; + cb_wechat_pay.setChecked(false); + cb_alipay.setChecked(true); + } + if (!"1".equals(config.getAlipay_switch())) { + ll_alipay.setVisibility(View.GONE); + mSelectedPayMethod = "wechat"; + cb_wechat_pay.setChecked(true); + cb_alipay.setChecked(false); + } + } + tv_member_pay_name.setText(goodsName); +// cb_member_check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { +// @Override +// public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { +// tv_member_pay.setEnabled(isChecked); +// } +// }); +// ll_member_check.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// cb_member_check.setChecked(!cb_member_check.isChecked()); +// } +// }); + tv_member_content.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(mContext, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.VIP_AGREEMENT_URL); + mContext.startActivity(intent); + } + }); + + tv_member_pay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { +// if (cb_member_check.isChecked()) { + if (null != mOnClickPayListener) { + mOnClickPayListener.onClickPayListener(mSelectedPayMethod); + } + dismiss(); +// } else { +// MaleToast.showMessage(mContext, "请先同意会员服务协议"); +// } + } + }); + cb_wechat_pay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mSelectedPayMethod = "wechat"; + cb_wechat_pay.setChecked(true); + cb_alipay.setChecked(false); + } + }); + ll_weixin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mSelectedPayMethod = "wechat"; + cb_wechat_pay.setChecked(true); + cb_alipay.setChecked(false); + } + }); + cb_alipay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mSelectedPayMethod = "alipay"; + cb_wechat_pay.setChecked(false); + cb_alipay.setChecked(true); + } + }); + ll_alipay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mSelectedPayMethod = "alipay"; + cb_wechat_pay.setChecked(false); + cb_alipay.setChecked(true); + } + }); + } + + private OnClickPayListener mOnClickPayListener; + + public void setOnClickPayListener(OnClickPayListener onClickPayListener) { + mOnClickPayListener = onClickPayListener; + } + + public interface OnClickPayListener { + void onClickPayListener(String selectedPayMethod); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberRechargeDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberRechargeDialog.java new file mode 100644 index 0000000..fd286d3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberRechargeDialog.java @@ -0,0 +1,56 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.MemberRechargeAdapter; +import com.fengliyan.tianlesue.model.settings.RechargeBean; + +import java.util.List; + +/** + * Created by zhangbin on 2019/5/22. + */ + +public class MemberRechargeDialog extends Dialog { + private Context mContext; + private RecyclerView rv_member_recharge; + private List list; + private MemberRechargeAdapter mAdapter; + + public MemberRechargeDialog(@NonNull Context context, List list) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.list = list; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_member_recharge); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + rv_member_recharge = findViewById(R.id.rv_member_recharge); + mAdapter = new MemberRechargeAdapter(mContext); + mAdapter.setRechargeList(list); + rv_member_recharge.setAdapter(mAdapter); + rv_member_recharge.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberTipsDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberTipsDialog.java new file mode 100644 index 0000000..0a4332b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/MemberTipsDialog.java @@ -0,0 +1,59 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; + +/** + * Created by zhangbin on 2019/5/22. + */ + +public class MemberTipsDialog extends Dialog { + private Context mContext; + private TextView tv_dialog_tips_title; + private TextView tv_dialog_tips_msg; + private TextView tv_dialog_tips_sure; + + private String msg; + + public MemberTipsDialog(@NonNull Context context, String msg) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.msg = msg; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_member_tips); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + tv_dialog_tips_title = findViewById(R.id.tv_dialog_tips_title); + tv_dialog_tips_msg = findViewById(R.id.tv_dialog_tips_msg); + tv_dialog_tips_sure = findViewById(R.id.tv_dialog_tips_sure); + tv_dialog_tips_msg.setText(msg); + tv_dialog_tips_sure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/OtherGuardDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/OtherGuardDialog.java new file mode 100644 index 0000000..e878831 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/OtherGuardDialog.java @@ -0,0 +1,144 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.GuardOtherBean; +import com.fengliyan.tianlesue.utils.StrU; + +/** + * Created by zhangbin on 2019/12/16. + */ +public class OtherGuardDialog extends Dialog implements View.OnClickListener { + + private Context mContext; + private View mIv_finish_dialog; + private Button mBt_guard; + private SimpleDraweeView mSv_other_photo; + private SimpleDraweeView mSv_photo; + private TextView mTv_name; + private TextView mTv_value; + + private GuardOtherBean mGuardOtherBean; + private String mAvatar; + private String mName; + + public OtherGuardDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public OtherGuardDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected OtherGuardDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_other_guard); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + + mSv_other_photo = findViewById(R.id.sv_other_photo); + mSv_photo = findViewById(R.id.sv_photo); + mTv_name = findViewById(R.id.tv_name); + mTv_value = findViewById(R.id.tv_value); + mIv_finish_dialog = findViewById(R.id.rl_finish); + mBt_guard = findViewById(R.id.bt_guard); + + if (null != mGuardOtherBean) { + mSv_other_photo.setImageURI(StrU.getResourcePath(mGuardOtherBean.getAvatar(), mContext)); + mSv_photo.setImageURI(StrU.getResourcePath(mAvatar, mContext)); + mTv_name.setText(mGuardOtherBean.getNickname() + "&" + mName); + setTextMoney(mTv_value, mGuardOtherBean.getIntimate_num()); + } + + mIv_finish_dialog.setOnClickListener(this); + mBt_guard.setOnClickListener(this); + + } + + public void setData(GuardOtherBean guardOtherBean, String avatar, String name) { + this.mGuardOtherBean = guardOtherBean; + this.mAvatar = avatar; + this.mName = name; + + + if (null != mSv_other_photo) { + mSv_other_photo.setImageURI(StrU.getResourcePath(mGuardOtherBean.getAvatar(), mContext)); + } + + if (null != mSv_photo) { + mSv_photo.setImageURI(StrU.getResourcePath(mAvatar, mContext)); + } + + if (null != mTv_name) { + mTv_name.setText(mGuardOtherBean.getNickname() + "&" + mName); + } + + if (null != mTv_value) { + setTextMoney(mTv_value, mGuardOtherBean.getIntimate_num()); + } + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, double totalMoney) { + if (totalMoney >= 10000) { + double money = totalMoney / 10000; + view.setText(String.format("%.1f", money) + "万"); + } else { + view.setText(String.format("%.0f", totalMoney)); + } + } + + + @Override + public void onClick(View view) { + if (view == mIv_finish_dialog) { + dismiss(); + } else if (view == mBt_guard) { + dismiss(); + if (null != mOnClickOtherGuard) { + mOnClickOtherGuard.onClickOtherGuard(); + } + } + } + + private OnClickOtherGuard mOnClickOtherGuard; + + public void setOnClickOtherGuard(OnClickOtherGuard onClickOtherGuard) { + mOnClickOtherGuard = onClickOtherGuard; + } + + public interface OnClickOtherGuard { + void onClickOtherGuard(); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/PayDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/PayDialog.java new file mode 100644 index 0000000..bf4453e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/PayDialog.java @@ -0,0 +1,107 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.settings.PayConfigBean; + +/** + * Created by zhangbin on 2019/5/22. + */ + +public class PayDialog extends Dialog { + + private Context mContext; + private TextView mCancelButton; + private PayConfigBean config; + public PayDialog(@NonNull Context context, PayConfigBean config) { + super(context); + mContext = context; + this.config = config; + } + + public PayDialog(@NonNull Context context, int themeResId, PayConfigBean config) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.config = config; + } + + protected PayDialog(@NonNull Context context, boolean cancelable, + @Nullable OnCancelListener cancelListener, + PayConfigBean config) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.config = config; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_pay); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.BOTTOM); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView(){ + + LinearLayout llWeixin = findViewById(R.id.ll_weixin); + LinearLayout llAlipay = findViewById(R.id.ll_alipay); + mCancelButton = findViewById(R.id.selector_cancel); + if (!"1".equals(config.getWechat_switch())){ + llWeixin.setVisibility(View.GONE); + } + if (!"1".equals(config.getAlipay_switch())){ + llAlipay.setVisibility(View.GONE); + } + mCancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + dismiss(); + } + }); + + llWeixin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != mOnClickPayListener) { + mOnClickPayListener.onClickWeixinPayListener(); + } + } + }); + + llAlipay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != mOnClickPayListener) { + mOnClickPayListener.onClickAliPayListener(); + } + } + }); + } + + private OnClickPayListener mOnClickPayListener; + + public void setOnClickPayListener(OnClickPayListener onClickPayListener) { + mOnClickPayListener = onClickPayListener; + } + + public interface OnClickPayListener { + void onClickWeixinPayListener(); + void onClickAliPayListener(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/SignInDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/SignInDialog.java new file mode 100644 index 0000000..3321ebe --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/SignInDialog.java @@ -0,0 +1,150 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.SignInListAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.SignDataListBean; +import com.fengliyan.tianlesue.utils.GridDecoration; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +public class SignInDialog extends Dialog { + private BaseActivity mContext; + private RecyclerView recyclerView; + private TextView tv_dialog_sign_sure; + private SignInListAdapter mAdapter; + private int status; + private String coin; + + public SignInDialog(@NonNull BaseActivity context, String coin) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.coin = coin; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_sign_in); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + recyclerView = findViewById(R.id.recyclerView); + tv_dialog_sign_sure = findViewById(R.id.tv_dialog_sign_sure); + mAdapter = new SignInListAdapter(mContext); + GridLayoutManager layoutManager = new GridLayoutManager(mContext, 4); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(mAdapter); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (position == 6) { + return 2; + } else { + return 1; + } + } + }); + recyclerView.addItemDecoration(new GridDecoration().setSizeDp(5f, 8f)); + + + tv_dialog_sign_sure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + switch (status) { + case 0: + BaseApplication.getInstance().getRechargeInfo(mContext, 0); + break; + case 1: + signIn(); + break; + case 2: + break; + } + dismiss(); + } + }); + signData(); + } + + public void signData() { + SettingManager.signData(mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SignDataListBean result, String message) { + if (result != null) { + //按钮状态0去充值1立即签到2已签到 + status = result.getButton_status(); + switch (status) { + case 0: + tv_dialog_sign_sure.setText("去充值"); + break; + case 1: + tv_dialog_sign_sure.setText("立即签到"); + break; + case 2: + tv_dialog_sign_sure.setText("已签到"); + break; + } + if (result.getSign_info() != null && result.getSign_info().size() > 0) { + mAdapter.setList(result.getSign_info()); + for (int i = 0; i < result.getSign_info().size(); i++) { + if (result.getSign_info().get(i).getIs_selected() == 1) { + coin = result.getSign_info().get(i).getGold_coin(); + } + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + public void signIn() { + SettingManager.signIn(mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + SignInRewardsDialog dialog = new SignInRewardsDialog(activity, coin); + dialog.show(); + signData(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/SignInRewardsDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/SignInRewardsDialog.java new file mode 100644 index 0000000..2a57f1c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/SignInRewardsDialog.java @@ -0,0 +1,59 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.utils.StrU; + +public class SignInRewardsDialog extends Dialog { + private Context mContext; + private TextView tv_dialog_tips_msg; + private TextView tv_dialog_tips_sure; + + private String coin; + + public SignInRewardsDialog(@NonNull Context context, String coin) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.coin = coin; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_sign_in_rewards); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + tv_dialog_tips_msg = findViewById(R.id.tv_dialog_tips_msg); + tv_dialog_tips_sure = findViewById(R.id.tv_dialog_tips_sure); + + if (!StrU.isEmpty(coin)) { + tv_dialog_tips_msg.setText("恭喜获得" + coin + "金币"); + } + + tv_dialog_tips_sure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/ToastNoticeDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/ToastNoticeDialog.java new file mode 100644 index 0000000..072f03a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/ToastNoticeDialog.java @@ -0,0 +1,133 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.user.bean.UserLiteBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +/** + * Created by zhangbin on 2019/3/18. + */ + +public class ToastNoticeDialog extends Dialog implements View.OnClickListener { + private Context mContext; + private View mRlDismiss; + private SimpleDraweeView mSvPhoto; + private TextView mTvName; + private TextView mTvInfo; + private TextView mTvConsumed; + private TextView mTvWealth; + private UserLiteBean mLiteBean; + private TextView mTvAge; + private TextView mTvValue; + + public ToastNoticeDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public ToastNoticeDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected ToastNoticeDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_toast_notice); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + + mRlDismiss = findViewById(R.id.rl_dismiss); + mSvPhoto = findViewById(R.id.sv_photo); + mTvName = findViewById(R.id.tv_name); + mTvInfo = findViewById(R.id.tv_info); + mTvAge = findViewById(R.id.tv_age); + mTvValue = findViewById(R.id.tv_value); + mTvConsumed = findViewById(R.id.tv_consumed); + mTvWealth = findViewById(R.id.tv_wealth); + + mSvPhoto.setImageURI(StrU.getResourcePath(mLiteBean.getAvatar(), mContext)); + mTvName.setText(mLiteBean.getNickname()); + + mTvConsumed.setText(setTextMoney(mLiteBean.getWealth_value())); + mTvWealth.setText(setTextMoney(mLiteBean.getAccount_value())); + mTvInfo.setText(mLiteBean.getCity()); + mTvAge.setText(mLiteBean.getAge() + "岁"); + + + if (mLiteBean.getIs_anchor() == 1) { //大咖 + mTvValue.setText("魅力值: " + setTextMoney(mLiteBean.getLove_value())); + } else { + mTvValue.setText("富豪值: " + setTextMoney(mLiteBean.getWealth_value())); + } + + if (mLiteBean.getGender() == 1) { + mTvAge.setTextColor(Color.RED); + } else { + mTvAge.setTextColor(mContext.getResources().getColor(R.color.mainColor)); + } + + mRlDismiss.setOnClickListener(this); + mSvPhoto.setOnClickListener(this); + } + + public void setData(UserLiteBean liteBean) { + this.mLiteBean = liteBean; + } + + /** + * 大于一万,用小数表示 + * + * @param totalMoney + */ + private String setTextMoney(double totalMoney) { + String value = ""; + if (totalMoney >= 10000) { + double money = totalMoney / 10000; + value = String.format("%.1f", money) + "万"; + } else { + value = String.format("%.0f", totalMoney); + } + + return value; + } + + + @Override + public void onClick(View view) { + if (view == mRlDismiss) { //换一批 + dismiss(); + } else if (view == mSvPhoto) { + dismiss(); + Intent intent = new Intent(mContext, MainPageActivity.class); + intent.putExtra("userId", mLiteBean.getUserid()); + mContext.startActivity(intent); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/VipGuideDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/VipGuideDialog.java new file mode 100644 index 0000000..91b10ec --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/VipGuideDialog.java @@ -0,0 +1,291 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.alipay.sdk.app.PayTask; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.MemberBean; +import com.fengliyan.tianlesue.model.settings.MemberInfoList; +import com.fengliyan.tianlesue.model.settings.PayBean; +import com.fengliyan.tianlesue.model.settings.PayConfigBean; +import com.fengliyan.tianlesue.model.settings.WXPayTypeBean; +import com.fengliyan.tianlesue.model.settings.WeChatPayInfoBean; +import com.fengliyan.tianlesue.utils.PayUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.PayWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.settings.QuickRechargeActivity; +import com.fengliyan.uikit.toast.MaleToast; +import com.sand.qzf.paytypesdk.base.CallBack; +import com.sand.qzf.paytypesdk.base.PayTypeSdk; +import com.sand.qzf.paytypesdk.base.Resp; +import com.tencent.mm.opensdk.modelpay.PayReq; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +import java.util.List; +import java.util.Map; + +/** + * vip引导弹窗 + */ +public class VipGuideDialog extends Dialog implements View.OnClickListener { + private Activity mContext; + private TextView tv_buy_vip; + private int type = 0; + + public VipGuideDialog(@NonNull Activity context) { + super(context); + this.mContext = context; + } + + public VipGuideDialog(@NonNull Activity context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected VipGuideDialog(@NonNull Activity context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_vip); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + tv_buy_vip = findViewById(R.id.tv_buy_vip); + tv_buy_vip.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (view == tv_buy_vip) { + type = 1; + if (mOnClickBuyVip != null) { + mOnClickBuyVip.onClickBuyVip(); + } + showPay(); + dismiss(); + } + } + + @Override + public void dismiss() { + super.dismiss(); + if (type != 1) { + Intent intent = new Intent(mContext, QuickRechargeActivity.class); + mContext.startActivity(intent); + } + } + + private OnClickBuyVip mOnClickBuyVip; + + public void setOnClickBuyVip(OnClickBuyVip onClickBuyVip) { + mOnClickBuyVip = onClickBuyVip; + } + + public interface OnClickBuyVip { + void onClickBuyVip(); + } + + private String price; + private int goodsId; + private String mSelectedPayMethod = "wechat"; //默认微信 + private boolean isWXHF; + private String ghOriId; + private int mini_program_type; + private String mOrderInfo; + + private final Runnable mPayRunnable = new Runnable() { + + @Override + public void run() { + PayTask alipay = new PayTask(mContext); + Map result = alipay.payV2(mOrderInfo, true); + String code = result.get("resultStatus"); + if (!TextUtils.isEmpty(code)) { + if ("9000".equals(code)) { + MaleToast.showMessage(mContext, "支付成功"); + } + } + } + }; + + /** + * 支付方式 + */ + public void showPay() { + SettingManager.getWechatPaySite((BaseActivity) mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WXPayTypeBean result, String tips) { + isWXHF = result.getWechat_type() == 3; + ghOriId = result.getGh_ori_id(); + mini_program_type = result.getMini_program_type(); + SettingManager.getMemberInfo((BaseActivity) mContext, 6, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MemberBean result, String message) { + if (result.getInfo() != null) { + List list = result.getInfo().getList(); + if (list != null && list.size() > 0) { + price = (int) Double.parseDouble(list.get(0).getPrice()) + list.get(0).getExpires_title(); + goodsId = list.get(0).getId(); + SettingManager.payConfig((BaseActivity) mContext, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayConfigBean result, String tips) { + MemberPayDialog mPayDialog = new MemberPayDialog(mContext, result, "VIP " + price); + mPayDialog.setOnClickPayListener(new MemberPayDialog.OnClickPayListener() { + @Override + public void onClickPayListener(String selectedPayMethod) { + mSelectedPayMethod = selectedPayMethod; + confirmToPay(goodsId); + mPayDialog.dismiss(); + } + }); + mPayDialog.show(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "获取支付信息失败"); + } + }); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void confirmToPay(int id) { + if (isWXHF && mSelectedPayMethod.equals("wechat")) { + PayUtils.wxminiPay(mContext, id, 1, ghOriId, mini_program_type); + return; + } + + SettingManager.payToRecharge((BaseActivity) mContext, mSelectedPayMethod, + id + "", 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayBean result, String message) { + if ("alipay".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + Thread payThread = new Thread(mPayRunnable); + payThread.start(); + } + } else if (result.getPay_platform_type() == 2) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + PayUtils.ailWeb(mOrderInfo, mContext); + } + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(mContext, PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + mContext.startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(mContext, result.getPayinfo()); + } else { + PayTypeSdk.getInstance().cashierPay(mContext, result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + } + } + }); + } + } else if ("wechat".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + IWXAPI wxapi = WXAPIFactory.createWXAPI(mContext, Constant.WECHAT_APP_ID, false); + WeChatPayInfoBean wechatpayinfo = result.getWechatpayinfo(); + PayReq req = new PayReq(); + req.appId = Constant.WECHAT_APP_ID; + req.partnerId = wechatpayinfo.getMch_id(); //商户号 + req.prepayId = wechatpayinfo.getPrepay_id(); //预付款id + req.nonceStr = wechatpayinfo.getNonce_str(); + req.timeStamp = wechatpayinfo.getTimestamp() + ""; + req.packageValue = "Sign=WXPay"; //固定值 + req.sign = wechatpayinfo.getPaySign(); + boolean isWXAppInstalledAndSupported = wxapi.isWXAppInstalled(); + if (isWXAppInstalledAndSupported) { + wxapi.registerApp(Constant.WECHAT_APP_ID); + wxapi.sendReq(req); + } else { + MaleToast.showMessage(mContext, "未安装微信,不能支付"); + } + } else if (result.getPay_platform_type() == 2) { + PayTypeSdk.getInstance().cashierPay(mContext, result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + } + } + }); + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(mContext, PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + mContext.startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(mContext, result.getPayinfo()); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WeChatAccountsDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WeChatAccountsDialog.java new file mode 100644 index 0000000..cda37ab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WeChatAccountsDialog.java @@ -0,0 +1,86 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import static android.content.Context.CLIPBOARD_SERVICE; + +import android.app.Dialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; + +/** + * Created by zhangbin on 2019/3/19. + */ + +public class WeChatAccountsDialog extends Dialog implements View.OnClickListener { + + private Context mContext; + private String weixinId; + private TextView mTvWinxinId; + private Button mBtCopy; + + public WeChatAccountsDialog(@NonNull Context context, String weixinId) { + super(context); + this.mContext = context; + this.weixinId = weixinId; + } + + public WeChatAccountsDialog(@NonNull Context context, String weixinId, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + this.weixinId = weixinId; + } + + protected WeChatAccountsDialog(@NonNull Context context, String weixinId, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + this.weixinId = weixinId; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_wechat_accounts); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + + mTvWinxinId = findViewById(R.id.tv_weixin_id); + mBtCopy = findViewById(R.id.bt_copy); + + mTvWinxinId.setText("私语 " + weixinId); + mBtCopy.setOnClickListener(this); + } + + + @Override + public void onClick(View view) { + if (view == mBtCopy) { + copyToClipboard(mContext, weixinId + ""); + MaleToastUtil.showMessage(mContext, "已复制到剪切板,请打开微信粘贴搜索"); + dismiss(); + } + } + + public void copyToClipboard(Context context, String text) { + ClipboardManager cm = (ClipboardManager) + context.getSystemService(CLIPBOARD_SERVICE); + + cm.setPrimaryClip(ClipData.newPlainText("Label", text)); + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WechatDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WechatDialog.java new file mode 100644 index 0000000..8380c7e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WechatDialog.java @@ -0,0 +1,109 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.uikit.toast.MaleToast; + +public class WechatDialog extends Dialog implements View.OnClickListener { + private BaseActivity mContext; + private SimpleDraweeView iv_user_avatar1; + private SimpleDraweeView iv_user_avatar2; + private TextView tv_wechat_msg1; + private LinearLayout lin_wechat_msg2; + private TextView tv_wechat_copy; + private TextView tv_wechat_msg3; + private TextView tv_dialog_wechat_sure; + private MainPageBean mMainPageBean; + + public WechatDialog(@NonNull BaseActivity context, MainPageBean mMainPageBean) { + super(context, R.style.SelectiveDialog); + mContext = context; + this.mMainPageBean = mMainPageBean; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_wechat); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + } + + private void initView() { + iv_user_avatar1 = findViewById(R.id.iv_user_avatar1); + iv_user_avatar2 = findViewById(R.id.iv_user_avatar2); + tv_wechat_msg1 = findViewById(R.id.tv_wechat_msg1); + lin_wechat_msg2 = findViewById(R.id.lin_wechat_msg2); + tv_wechat_copy = findViewById(R.id.tv_wechat_copy); + tv_wechat_msg3 = findViewById(R.id.tv_wechat_msg3); + tv_dialog_wechat_sure = findViewById(R.id.tv_dialog_wechat_sure); + tv_dialog_wechat_sure.setOnClickListener(this); + tv_wechat_copy.setOnClickListener(this); + tv_wechat_msg3.setOnClickListener(this); + iv_user_avatar1.setImageURI(StrU.getResourcePath(UserManager.getUserInfo().getAvatar(), mContext)); + iv_user_avatar2.setImageURI(StrU.getResourcePath(mMainPageBean.getInfo().getAvatar(), mContext)); + try { + if (mMainPageBean.getInfo().getGender() == 1 && mMainPageBean.getContact() != null) { + if (mMainPageBean.getContact().getWechat().getStatus() != 1) { + tv_wechat_msg3.setText("暂未填写"); + } else { + int wechatPrice = Integer.parseInt(mMainPageBean.getContact().getWechat().getWechat_price()); + if (mMainPageBean.getContact().getWechat().getGiftCoin() < wechatPrice) { + tv_wechat_msg1.setText(String.format("再送%d金币礼物可查看微信", (wechatPrice - mMainPageBean.getContact().getWechat().getGiftCoin()))); + tv_wechat_msg1.setVisibility(View.VISIBLE); + lin_wechat_msg2.setVisibility(View.GONE); + tv_wechat_msg3.setVisibility(View.GONE); + } else { + tv_wechat_msg1.setVisibility(View.GONE); + lin_wechat_msg2.setVisibility(View.VISIBLE); + tv_wechat_msg3.setVisibility(View.VISIBLE); + tv_wechat_msg3.setText(mMainPageBean.getContact().getWechat().getContent()); + } + } + } else { + tv_wechat_msg3.setText("暂未填写"); + } + } catch (NumberFormatException ignored) { + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_wechat_msg3: + case R.id.tv_wechat_copy: + ClipboardManager cm = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(null, mMainPageBean.getContact().getWechat().getContent())); + MaleToast.showMessage(mContext, "复制成功"); + dismiss(); + break; + case R.id.tv_dialog_wechat_sure: + dismiss(); + break; + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WechatToCopyDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WechatToCopyDialog.java new file mode 100644 index 0000000..5be6c45 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/base/utils/view/WechatToCopyDialog.java @@ -0,0 +1,106 @@ +package com.fengliyan.tianlesue.view.base.utils.view; + +import android.app.Dialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; + +/** + * Created by zhangbin on 2020/3/6. + */ +public class WechatToCopyDialog extends Dialog implements View.OnClickListener { + + private Context mContext; + private Button mBt_guard; + private TextView mTv_title2; + private String copy; + + public WechatToCopyDialog(@NonNull Context context) { + super(context); + this.mContext = context; + } + + public WechatToCopyDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + protected WechatToCopyDialog(@NonNull Context context, boolean cancelable, @Nullable DialogInterface.OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_wechat_copy); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + + } + + private void initView() { + + mTv_title2 = findViewById(R.id.tv_title2); + mBt_guard = findViewById(R.id.bt_guard); + + mTv_title2.setText(copy); + + mBt_guard.setOnClickListener(this); + } + + public void setData(String copy) { + this.copy = copy; + + if (null != mTv_title2) { + mTv_title2.setText(copy); + } + } + + + @Override + public void onClick(View view) { + if (view == mBt_guard) { + ClipboardManager cm = (ClipboardManager) + mContext.getSystemService(Context.CLIPBOARD_SERVICE); + + cm.setPrimaryClip(ClipData.newPlainText(null, "注意:请复制下面链接后,用手机浏览器打开!微信中直接打开无法下载\n" + copy)); + MaleToast.showMessage(mContext, "链接复制成功,快去微信粘贴发送吧!"); + + Intent intent =mContext.getPackageManager().getLaunchIntentForPackage("com.tencent.mm"); + + mContext.startActivity(intent); + + if (null != mOnCLickCopy) { + mOnCLickCopy.onClickCopy(); + } + + dismiss(); + } + } + + private OnCLickCopy mOnCLickCopy; + + public void setOnCLickCopy(OnCLickCopy onCLickCopy) { + mOnCLickCopy = onCLickCopy; + } + + public interface OnCLickCopy { + void onClickCopy(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/config/BaseUIConfig.java b/app/src/main/java/com/fengliyan/tianlesue/view/config/BaseUIConfig.java new file mode 100644 index 0000000..4daf900 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/config/BaseUIConfig.java @@ -0,0 +1,79 @@ +package com.fengliyan.tianlesue.view.config; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.util.TypedValue; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper; + +import static me.jessyan.autosize.utils.AutoSizeUtils.dp2px; + + +public abstract class BaseUIConfig { + public Activity mActivity; + public Context mContext; + public PhoneNumberAuthHelper mAuthHelper; + public int mScreenWidthDp; + public int mScreenHeightDp; + + /*public static BaseUIConfig init(int type, Activity activity, PhoneNumberAuthHelper authHelper) { + switch (type) { + case Constant.FULL_PORT: + return new FullPortConfig(activity, authHelper); + case Constant.FULL_LAND: + return new FullLandConfig(activity, authHelper); + case Constant.DIALOG_PORT: + return new DialogPortConfig(activity, authHelper); + case Constant.DIALOG_LAND: + return new DialogLandConfig(activity, authHelper); + case Constant.DIALOG_BOTTOM: + return new DialogBottomConfig(activity, authHelper); + case Constant.CUSTOM_VIEW: + return new CustomViewConfig(activity, authHelper); + case Constant.CUSTOM_XML: + return new CustomXmlConfig(activity, authHelper); + case Constant.CUSTOM_GIF: + return new CustomGifConfig(activity, authHelper); + case Constant.CUSTOM_MOV: + return new CustomMovConfig(activity, authHelper); + case Constant.CUSTOM_PIC: + return new CustomPicConfig(activity, authHelper); + default: + return null; + } + }*/ + + protected View initSwitchView(int marginTop) { + TextView switchTV = new TextView(mActivity); + RelativeLayout.LayoutParams mLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, dp2px(mActivity, 50)); + //一键登录按钮默认marginTop 270dp + mLayoutParams.setMargins(0, dp2px(mContext, marginTop), 0, 0); + mLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE); + switchTV.setText("R.string.switch_msg"); + switchTV.setTextColor(Color.BLACK); + switchTV.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13.0F); + switchTV.setLayoutParams(mLayoutParams); + return switchTV; + } + + public BaseUIConfig(Activity activity, PhoneNumberAuthHelper authHelper) { + mActivity = activity; + mContext = activity.getApplicationContext(); + mAuthHelper = authHelper; + } + + + public abstract void configAuthPage(); + + /** + * 在横屏APP弹竖屏一键登录页面或者竖屏APP弹横屏授权页时处理特殊逻辑 + * Android8.0只能启动SCREEN_ORIENTATION_BEHIND模式的Activity + */ + public void onResume() { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/config/CustomXmlConfig.java b/app/src/main/java/com/fengliyan/tianlesue/view/config/CustomXmlConfig.java new file mode 100644 index 0000000..cf58c0b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/config/CustomXmlConfig.java @@ -0,0 +1,214 @@ +package com.fengliyan.tianlesue.view.config; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.graphics.Color; +import android.os.Build; +import android.view.View; + +import androidx.core.content.ContextCompat; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.uikit.toast.MaleToast; +import com.mobile.auth.gatewayauth.ActivityResultListener; +import com.mobile.auth.gatewayauth.AuthRegisterXmlConfig; +import com.mobile.auth.gatewayauth.AuthUIConfig; +import com.mobile.auth.gatewayauth.AuthUIControlClickListener; +import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper; +import com.mobile.auth.gatewayauth.ui.AbstractPnsViewDelegate; +import com.tencent.mm.opensdk.utils.Log; +import com.xinlingwu.share.ShareManager; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * xml文件方便预览 + * -0-------- 可以通过addAuthRegisterXmlConfig一次性统一添加授权页的所有自定义view + */ +public class CustomXmlConfig extends BaseUIConfig { + + private Activity activity; + private OnOneKeyCustomClickListener onOneKeyCustomClickListener; + private boolean isOneKeyIsPricyChecked; + + public CustomXmlConfig(Activity activity, PhoneNumberAuthHelper authHelper, OnOneKeyCustomClickListener onOneKeyCustomClickListener) { + super(activity, authHelper); + this.activity = activity; + this.onOneKeyCustomClickListener = onOneKeyCustomClickListener; + } + + @Override + public void configAuthPage() { + mAuthHelper.removeAuthRegisterXmlConfig(); + mAuthHelper.removeAuthRegisterViewConfig(); + isOneKeyIsPricyChecked = false; + int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; + if (Build.VERSION.SDK_INT == 26) { + authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND; + } + mAuthHelper.setUIClickListener(new AuthUIControlClickListener() { + @Override + public void onClick(String s, Context context, String s1) { + if (ConstUrl.LOGDEBUG) Log.i("一键登录页", "CustomXmlConfig s:" + s + ";s1" + s1); + if (s.equals("700003")) { + //隐私政策勾选回调 + JSONObject jsonObject = null; + try { + jsonObject = new JSONObject(s1); + isOneKeyIsPricyChecked = jsonObject.getBoolean("isChecked"); + if (ConstUrl.LOGDEBUG) Log.i("一键登录页", "CustomXmlConfig isChecked:" + isOneKeyIsPricyChecked); + } catch (JSONException e) { + e.printStackTrace(); + } + + } else if (s.equals("700000")) { + if (ConstUrl.LOGDEBUG) Log.i("一键登录页", "CustomXmlConfig s1:" + s1); + } + } + }); + mAuthHelper.addAuthRegisterXmlConfig(new AuthRegisterXmlConfig.Builder() + .setLayout(R.layout.layout_login_one_key, new AbstractPnsViewDelegate() { + @Override + public void onViewCreated(View view) { + findViewById(R.id.rtv_change_login_type).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOneKeyCustomClickListener != null) { + onOneKeyCustomClickListener.onChangeLoginType(); + } + //mAuthHelper.quitLoginPage(); + } + }); + + findViewById(R.id.login_weixin).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOneKeyCustomClickListener != null) { + if (isOneKeyIsPricyChecked) { + onOneKeyCustomClickListener.onThirdLogin(1); + } else { + MaleToast.showMessage(mActivity, "请勾选《用户协议》和《隐私协议》"); + } + + } + } + }); + + findViewById(R.id.login_qq).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOneKeyCustomClickListener != null) { + if (isOneKeyIsPricyChecked) { + onOneKeyCustomClickListener.onThirdLogin(2); +// mAuthHelper.quitLoginPage(); + } else { + MaleToast.showMessage(mActivity, "请勾选《用户协议》和《隐私协议》"); + } + + } + } + }); + findViewById(R.id.lin_login_help).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOneKeyCustomClickListener != null) { + onOneKeyCustomClickListener.onCustomerTip(); + } + } + }); + /*findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mAuthHelper.quitLoginPage(); + } + }); + + findViewById(R.id.tv_switch).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(mContext, "切换到短信登录方式", Toast.LENGTH_SHORT).show(); + Intent pIntent = new Intent(mActivity, MessageActivity.class); + mActivity.startActivityForResult(pIntent, 1002); + mAuthHelper.quitLoginPage(); + } + });*/ + } + }) + .build()); + mAuthHelper.setActivityResultListener(new ActivityResultListener() { + @Override + public void onActivityResult(int i, int i1, Intent intent) { + ShareManager.getInstance().onActivityResult(activity, i, i1, intent); + + } + }); + mAuthHelper.setAuthUIConfig(new AuthUIConfig.Builder() + .setNavHidden(true) + .setLightColor(true) + .setStatusBarColor(Color.TRANSPARENT) + .setLogoHidden(true) + .setHiddenLoading(true) + .setStatusBarUIFlag(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) + .setNumFieldOffsetY(168) //号码栏距离顶部168dp + .setNumberColor(Color.parseColor("#ff333333")) + .setNumberSizeDp(32) + .setSloganOffsetY(221) + .setSloganTextSizeDp(14) + .setSloganTextColor(Color.parseColor("#ff999999")) + .setLogBtnText("本机号码一键登录") + .setLogBtnHeight(54) + .setLogBtnTextColor(Color.WHITE) + .setLogBtnTextSizeDp(16) + .setLogBtnBackgroundDrawable(ContextCompat.getDrawable(activity, R.drawable.shape_button_enable)) + .setSwitchAccHidden(true) + .setPrivacyOffsetY(430) + .setPrivacyMargin(36) + .setUncheckedImgDrawable(ContextCompat.getDrawable(activity, R.mipmap.check_normal)) + .setCheckedImgDrawable(ContextCompat.getDrawable(activity, R.mipmap.check_check)) + .setAppPrivacyColor(Color.parseColor("#333333"), Color.parseColor("#6B2CC4")) + .setVendorPrivacyPrefix("《") + .setVendorPrivacySuffix("》") + .setPrivacyTextSizeDp(12) + .setPrivacyState(false) + .setAppPrivacyOne("《用户协议》", ConstUrl.AGREEMENT_URL) + .setAppPrivacyTwo("《隐私协议》", ConstUrl.USER_PRIVACY_URL) + .setWebViewStatusBarColor(Color.TRANSPARENT) + .setWebNavTextSizeDp(20) + .setWebNavColor(Color.TRANSPARENT) + .setWebNavTextColor(Color.parseColor("#ff333333")) + .setPackageName(activity.getPackageName()) + .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) + .create()); + + /*mAuthHelper.setAuthUIConfig(new AuthUIConfig.Builder() + .setAppPrivacyOne("《自定义隐私协议》", "https://test.h5.app.tbmao.com/user") + .setAppPrivacyTwo("《百度》", "https://www.baidu.com") + .setAppPrivacyColor(Color.GRAY, Color.parseColor("#002E00")) + .setNavHidden(true) + .setLogoHidden(true) + .setSloganHidden(true) + .setSwitchAccHidden(true) + .setPrivacyState(false) + .setCheckboxHidden(true) + .setLightColor(true) + .setWebViewStatusBarColor(Color.TRANSPARENT) + .setStatusBarColor(Color.TRANSPARENT) + .setStatusBarUIFlag(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) + .setWebNavTextSizeDp(20) + .setNumberSizeDp(20) + .setNumberColor(Color.BLACK) + .setAuthPageActIn("in_activity", "out_activity") + .setAuthPageActOut("in_activity", "out_activity") + .setVendorPrivacyPrefix("《") + .setVendorPrivacySuffix("》") + .setPageBackgroundPath("page_background_color") + .setLogoImgPath("mytel_app_launcher") + .setLogBtnBackgroundPath("login_btn_bg") + .setScreenOrientation(authPageOrientation) + .create());*/ + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/config/FullPortConfig.java b/app/src/main/java/com/fengliyan/tianlesue/view/config/FullPortConfig.java new file mode 100644 index 0000000..94a79e5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/config/FullPortConfig.java @@ -0,0 +1,125 @@ +package com.fengliyan.tianlesue.view.config; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.graphics.Color; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; + +import com.mobile.auth.gatewayauth.AuthRegisterViewConfig; +import com.mobile.auth.gatewayauth.AuthUIConfig; +import com.mobile.auth.gatewayauth.AuthUIControlClickListener; +import com.mobile.auth.gatewayauth.CustomInterface; +import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper; +import com.mobile.auth.gatewayauth.ResultCode; + +import org.json.JSONException; +import org.json.JSONObject; + +public class FullPortConfig extends BaseUIConfig { + private final String TAG = "全屏竖屏样式"; + + public FullPortConfig(Activity activity, PhoneNumberAuthHelper authHelper) { + super(activity, authHelper); + } + + @Override + public void configAuthPage() { + mAuthHelper.setUIClickListener(new AuthUIControlClickListener() { + @Override + public void onClick(String code, Context context, String jsonString) { + JSONObject jsonObj = null; + try { + if(!TextUtils.isEmpty(jsonString)) { + jsonObj = new JSONObject(jsonString); + } + } catch (JSONException e) { + jsonObj = new JSONObject(); + } + switch (code) { + //点击授权页默认样式的返回按钮 + case ResultCode.CODE_ERROR_USER_CANCEL: + Log.e(TAG, "点击了授权页默认返回按钮"); + mAuthHelper.quitLoginPage(); + mActivity.finish(); + break; + //点击授权页默认样式的切换其他登录方式 会关闭授权页 + //如果不希望关闭授权页那就setSwitchAccHidden(true)隐藏默认的 通过自定义view添加自己的 + case ResultCode.CODE_ERROR_USER_SWITCH: + Log.e(TAG, "点击了授权页默认切换其他登录方式"); + break; + //点击一键登录按钮会发出此回调 + //当协议栏没有勾选时 点击按钮会有默认toast 如果不需要或者希望自定义内容 setLogBtnToastHidden(true)隐藏默认Toast + //通过此回调自己设置toast + case ResultCode.CODE_ERROR_USER_LOGIN_BTN: + if (!jsonObj.optBoolean("isChecked")) { + //Toast.makeText(mContext, R.string.custom_toast, Toast.LENGTH_SHORT).show(); + } + break; + //checkbox状态改变触发此回调 + case ResultCode.CODE_ERROR_USER_CHECKBOX: + Log.e(TAG, "checkbox状态变为" + jsonObj.optBoolean("isChecked")); + break; + //点击协议栏触发此回调 + case ResultCode.CODE_ERROR_USER_PROTOCOL_CONTROL: + Log.e(TAG, "点击协议," + "name: " + jsonObj.optString("name") + ", url: " + jsonObj.optString("url")); + break; + default: + break; + + } + + } + }); + mAuthHelper.removeAuthRegisterXmlConfig(); + mAuthHelper.removeAuthRegisterViewConfig(); + //添加自定义切换其他登录方式 + mAuthHelper.addAuthRegistViewConfig("switch_msg", new AuthRegisterViewConfig.Builder() + .setView(initSwitchView(350)) + .setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_BODY) + .setCustomInterface(new CustomInterface() { + @Override + public void onClick(Context context) { + /*Toast.makeText(mContext, "切换到短信登录方式", Toast.LENGTH_SHORT).show(); + Intent pIntent = new Intent(mActivity, MessageActivity.class); + mActivity.startActivityForResult(pIntent, 1002); + mAuthHelper.quitLoginPage();*/ + } + }).build()); + int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; + if (Build.VERSION.SDK_INT == 26) { + authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND; + } + mAuthHelper.setAuthUIConfig(new AuthUIConfig.Builder() + .setAppPrivacyOne("《自定义隐私协议》", "https://test.h5.app.tbmao.com/user") + .setAppPrivacyTwo("《百度》", "https://www.baidu.com") + .setAppPrivacyColor(Color.GRAY, Color.parseColor("#002E00")) + //隐藏默认切换其他登录方式 + .setSwitchAccHidden(true) + //隐藏默认Toast + .setLogBtnToastHidden(true) + //沉浸式状态栏 + .setNavColor(Color.parseColor("#026ED2")) + .setStatusBarColor(Color.parseColor("#026ED2")) + .setWebViewStatusBarColor(Color.parseColor("#026ED2")) + + + .setLightColor(false) + .setWebNavTextSizeDp(20) + //图片或者xml的传参方式为不包含后缀名的全称 需要文件需要放在drawable或drawable-xxx目录下 in_activity.xml, mytel_app_launcher.png + .setAuthPageActIn("in_activity", "out_activity") + .setAuthPageActOut("in_activity", "out_activity") + .setVendorPrivacyPrefix("《") + .setVendorPrivacySuffix("》") + .setPageBackgroundPath("page_background_color") + .setLogoImgPath("mytel_app_launcher") + //一键登录按钮三种状态背景示例login_btn_bg.xml + .setLogBtnBackgroundPath("login_btn_bg") + .setScreenOrientation(authPageOrientation) + .create()); + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/config/OnOneKeyCustomClickListener.java b/app/src/main/java/com/fengliyan/tianlesue/view/config/OnOneKeyCustomClickListener.java new file mode 100644 index 0000000..c16f85f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/config/OnOneKeyCustomClickListener.java @@ -0,0 +1,7 @@ +package com.fengliyan.tianlesue.view.config; + +public interface OnOneKeyCustomClickListener { + void onChangeLoginType(); + void onThirdLogin(int type); + void onCustomerTip(); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/Diooto.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/Diooto.java new file mode 100644 index 0000000..59c23a1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/Diooto.java @@ -0,0 +1,263 @@ +package com.fengliyan.tianlesue.view.diooto; + +import android.app.Activity; +import android.content.Context; +import android.content.ContextWrapper; +import android.os.Build; +import android.view.ContextThemeWrapper; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.view.diooto.config.ContentViewOriginModel; +import com.fengliyan.tianlesue.view.diooto.config.DiootoConfig; +import com.fengliyan.tianlesue.view.diooto.interfaces.CircleIndexIndicator; +import com.fengliyan.tianlesue.view.diooto.interfaces.DefaultPercentProgress; +import com.fengliyan.tianlesue.view.diooto.interfaces.IIndicator; +import com.fengliyan.tianlesue.view.diooto.interfaces.IProgress; +import com.fengliyan.tianlesue.view.diooto.tools.Fucking; +import com.fengliyan.uikit.sketch.Sketch; +import com.fengliyan.uikit.sketch.SketchImageView; + +import java.util.ArrayList; +import java.util.List; + +public class Diooto { + Context mContext; + + public Diooto(Context context) { + mContext = context; + diootoConfig = new DiootoConfig(); + } + + private DiootoConfig diootoConfig; + + public Diooto urls(String imageUrl) { + this.diootoConfig.setImageUrls(new String[]{imageUrl}); + return this; + } + + public Diooto fullscreen(boolean isFullScreen) { + this.diootoConfig.setFullScreen(isFullScreen); + return this; + } + + public Diooto urls(String[] imageUrls) { + this.diootoConfig.setImageUrls(imageUrls); + return this; + } + + public Diooto type(int type) { + this.diootoConfig.setType(type); + return this; + } + + public Diooto immersive(boolean immersive) { + this.diootoConfig.setImmersive(immersive); + return this; + } + + public Diooto position(int position) { + return position(position, 0); + } + + public Diooto position(int position, int headerSize) { + this.diootoConfig.setPosition(position - headerSize); + return this; + } + + public Diooto views(View view) { + View[] views = new View[1]; + views[0] = view; + return views(views); + } + + + public Diooto views(RecyclerView recyclerView, @IdRes int viewId, int childCount) { + List originImageList = new ArrayList<>(); + for (int i = 0; i < childCount; i++) { + View originImage = (recyclerView.getChildAt(i) + .findViewById(viewId)); + if (originImage != null) { + originImageList.add(originImage); + } + } + RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + int firstPos = 0, lastPos = 0; + int totalCount = layoutManager.getItemCount(); + if (layoutManager instanceof GridLayoutManager) { + GridLayoutManager gridLayMan = (GridLayoutManager) layoutManager; + firstPos = gridLayMan.findFirstVisibleItemPosition(); + lastPos = gridLayMan.findLastVisibleItemPosition(); + } else if (layoutManager instanceof LinearLayoutManager) { + LinearLayoutManager linLayMan = (LinearLayoutManager) layoutManager; + firstPos = linLayMan.findFirstVisibleItemPosition(); + lastPos = linLayMan.findLastVisibleItemPosition(); + } + fillPlaceHolder(originImageList, totalCount - 1, firstPos , lastPos ); + View[] views = new View[originImageList.size()]; + for (int i = 0; i < originImageList.size(); i++) { + views[i] = originImageList.get(i); + } + return views(views); + } + + private void fillPlaceHolder(List originImageList, int totalCount, int firstPos, int lastPos) { + if (firstPos > 0) { + for (int pos = firstPos; pos > 0; pos--) { + originImageList.add(0, null); + } + } + if (lastPos < totalCount) { + for (int i = (totalCount - 1 - lastPos); i > 0; i--) { + originImageList.add(null); + } + } + } + + public Diooto views(View[] views) { + List list = new ArrayList<>(); + for (View imageView : views) { + ContentViewOriginModel imageBean = new ContentViewOriginModel(); + if (imageView == null) { + imageBean.left = 0; + imageBean.top = 0; + imageBean.width = 0; + imageBean.height = 0; + } else { + int location[] = new int[2]; + imageView.getLocationOnScreen(location); + imageBean.left = location[0]; + imageBean.top = location[1] - Fucking.getFuckHeight(getWindow(imageView.getContext())); + imageBean.width = imageView.getWidth(); + imageBean.height = imageView.getHeight(); + } + list.add(imageBean); + } + diootoConfig.setContentViewOriginModels(list); + return this; + } + + + public Diooto start() { + if (!diootoConfig.isImmersive()) { + Window window = getWindow(mContext); + if ((window.getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) + == WindowManager.LayoutParams.FLAG_FULLSCREEN) { + diootoConfig.setFullScreen(true); + } + if (!diootoConfig.isFullScreen()) { + window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + } + } + + if (ImageActivity.iIndicator == null) { + setIndicator(new CircleIndexIndicator()); + } + if (ImageActivity.iProgress == null) { + setProgress(new DefaultPercentProgress()); + } + ImageActivity.startImageActivity(scanForActivity(mContext), diootoConfig); + return this; + } + + Window getWindow(Context context) { + if (getAppCompActivity(context) != null) { + return getAppCompActivity(context).getWindow(); + } else { + return scanForActivity(context).getWindow(); + } + } + + AppCompatActivity getAppCompActivity(Context context) { + if (context == null) return null; + if (context instanceof AppCompatActivity) { + return (AppCompatActivity) context; + } else if (context instanceof ContextThemeWrapper) { + return getAppCompActivity(((ContextThemeWrapper) context).getBaseContext()); + } + return null; + } + + Activity scanForActivity(Context context) { + if (context == null) return null; + + if (context instanceof Activity) { + return (Activity) context; + } else if (context instanceof ContextWrapper) { + return scanForActivity(((ContextWrapper) context).getBaseContext()); + } + return null; + } + + public Diooto setProgress(IProgress on) { + ImageActivity.iProgress = on; + return this; + } + + public Diooto setIndicator(IIndicator on) { + ImageActivity.iIndicator = on; + return this; + } + + public Diooto loadPhotoBeforeShowBigImage(OnLoadPhotoBeforeShowBigImageListener on) { + onLoadPhotoBeforeShowBigImageListener = on; + return this; + } + + public Diooto onVideoLoadEnd(OnShowToMaxFinishListener on) { + onShowToMaxFinishListener = on; + return this; + } + + public Diooto onFinish(OnFinishListener on) { + onFinishListener = on; + return this; + } + + public Diooto onProvideVideoView(OnProvideViewListener on) { + onProvideViewListener = on; + return this; + } + + public static OnLoadPhotoBeforeShowBigImageListener onLoadPhotoBeforeShowBigImageListener; + public static OnShowToMaxFinishListener onShowToMaxFinishListener; + public static OnProvideViewListener onProvideViewListener; + public static OnFinishListener onFinishListener; + + public interface OnLoadPhotoBeforeShowBigImageListener { + void loadView(SketchImageView sketchImageView, int position); + } + + public interface OnProvideViewListener { + View provideView(); + } + + public interface OnShowToMaxFinishListener { + void onShowToMax(DragDiootoView dragDiootoView, SketchImageView sketchImageView, View progressView); + } + + public interface OnFinishListener { + void finish(DragDiootoView dragDiootoView); + } + + public static void cleanMemory(@NonNull Context context) { + Sketch.with(context).getConfiguration().getDiskCache().clear(); + Sketch.with(context).getConfiguration().getBitmapPool().clear(); + Sketch.with(context).getConfiguration().getMemoryCache().clear(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/DragDiootoView.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/DragDiootoView.java new file mode 100644 index 0000000..1172c4b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/DragDiootoView.java @@ -0,0 +1,816 @@ +package com.fengliyan.tianlesue.view.diooto; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.fengliyan.uikit.sketch.SketchImageView; +import com.fengliyan.uikit.sketch.decode.ImageSizeCalculator; +import com.fengliyan.tianlesue.R; + + + +/** + * Created by moyokoo. + * Date: 2017/2/17 + */ +public class DragDiootoView extends FrameLayout { + private float mAlpha = 0; + private float mDownX; + private float mDownY; + private float mYDistanceTraveled; + private float mXDistanceTraveled; + private float mTranslateY; + private float mTranslateX; + + private final float DEFAULT_MIN_SCALE = 0.3f; + private int MAX_TRANSLATE_Y = 0; + private int MAX_Y = 0; + + FrameLayout contentLayout; + View backgroundView; + + private final long DEFAULT_DURATION = 300; + long animationDuration = DEFAULT_DURATION; + private int mOriginLeft; + private int mOriginTop; + private int mOriginHeight; + private int mOriginWidth; + + private int screenWidth; + private int screenHeight; + private int targetImageTop; + private int targetImageWidth; + private int targetImageHeight; + + private int mLastY; + + int minWidth = 0; + int minHeight = 0; + + int releaseLeft = 0; + float releaseY = 0; + int releaseWidth = 0; + int releaseHeight = 0; + int realWidth; + int realHeight; + int touchSlop = ViewConfiguration.getTouchSlop(); + + int imageLeftOfAnimatorEnd = 0; + int imageTopOfAnimatorEnd = 0; + int imageWidthOfAnimatorEnd = 0; + int imageHeightOfAnimatorEnd = 0; + + MarginViewWrapper imageWrapper; + boolean isMulitFinger = false; + boolean isDrag = false; + boolean isLongHeightImage = false;//是否是高度长图 + boolean isLongWidthImage = false;//是否是宽度长图 + boolean isAnimating = false;//是否在动画中 + boolean isPhoto = false; + + public DragDiootoView(Context context) { + this(context, null); + } + + public DragDiootoView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DragDiootoView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + screenWidth = getResources().getDisplayMetrics().widthPixels; + screenHeight = getResources().getDisplayMetrics().heightPixels; + MAX_TRANSLATE_Y = screenHeight / 6; + MAX_Y = screenHeight - screenHeight / 8; + + addView(LayoutInflater.from(getContext()).inflate(R.layout.content_item_for_display, null), 0); + contentLayout = findViewById(R.id.contentLayout); + backgroundView = findViewById(R.id.backgroundView); + imageWrapper = new MarginViewWrapper(contentLayout); + } + + void dragAnd2Normal(float currentY, boolean isDrag) { + float nodeMarginPercent = (MAX_Y - currentY + targetImageTop) / MAX_Y; + float widthPercent = DEFAULT_MIN_SCALE + (1f - DEFAULT_MIN_SCALE) * nodeMarginPercent; + int originLeftOffset = (screenWidth - targetImageWidth) / 2; + int leftOffset = (int) ((targetImageWidth - targetImageWidth * widthPercent) / 2); + + float left; + if (nodeMarginPercent >= 1) { + //处于拖动到正常大小上方 + imageWrapper.setWidth(targetImageWidth); + imageWrapper.setHeight(targetImageHeight); + left = mTranslateX; + mAlpha = nodeMarginPercent; + } else { + imageWrapper.setWidth(targetImageWidth * widthPercent); + imageWrapper.setHeight(targetImageHeight * widthPercent); + left = mTranslateX + leftOffset; + } + if (!isDrag) { + left = (currentY - targetImageTop) / (releaseY - targetImageTop) * releaseLeft; + } + backgroundView.setAlpha(mAlpha); + imageWrapper.setMarginLeft(Math.round(left + originLeftOffset)); + imageWrapper.setMarginTop((int) (currentY)); + } + + void backToNormal() { + isAnimating = true; + releaseLeft = imageWrapper.getMarginLeft() - (screenWidth - targetImageWidth) / 2; + releaseY = imageWrapper.getMarginTop(); + ValueAnimator valueAnimator = ValueAnimator.ofFloat(imageWrapper.getMarginTop(), targetImageTop); + valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float value = (float) animation.getAnimatedValue(); + dragAnd2Normal(value, false); + } + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimating = false; + } + }); + valueAnimator.setDuration(animationDuration).start(); + if (onReleaseListener != null) { + onReleaseListener.onRelease(true, false); + } + changeBackgroundViewAlpha(false); + } + + void min2NormalAndDrag2Min(float currentY, float startY, float endY, float startLeft, float endLeft, + float startWidth, float endWidth, float startHeight, float endHeight) { + min2NormalAndDrag2Min(false, currentY, startY, endY, startLeft, endLeft, startWidth, endWidth, startHeight, endHeight); + } + + void min2NormalAndDrag2Min(float endY, float endLeft, float endWidth, float endHeight) { + min2NormalAndDrag2Min(true, 0, 0, endY, 0, endLeft, 0, endWidth, 0, endHeight); + } + + void min2NormalAndDrag2Min(boolean showImmediately, float currentY, float startY, float endY, float startLeft, float endLeft, + float startWidth, float endWidth, float startHeight, float endHeight) { + if (endY == startY) { + return; + } + if (showImmediately) { + imageWrapper.setWidth(endWidth); + imageWrapper.setHeight(endHeight); + imageWrapper.setMarginLeft((int) (endLeft)); + imageWrapper.setMarginTop((int) endY); + return; + } + float yPercent = (currentY - startY) / (endY - startY); + float xOffset = yPercent * (endLeft - startLeft); + float widthOffset = yPercent * (endWidth - startWidth); + float heightOffset = yPercent * (endHeight - startHeight); + imageWrapper.setWidth(startWidth + widthOffset); + imageWrapper.setHeight(startHeight + heightOffset); + imageWrapper.setMarginLeft((int) (startLeft + xOffset)); + imageWrapper.setMarginTop((int) currentY); + } + + public void backToMin() { + if (isAnimating) { + return; + } + //到最小时,先把imageView的大小设置为imageView可见的大小,而不是包含黑色空隙部分 + if (isPhoto) { + // 注意:这里 imageWrapper.getHeight() 获取的高度 是经过拖动缩放后的 + float draggingToReleaseScale = imageWrapper.getHeight() / (float) screenHeight; + if (imageWrapper.getHeight() != imageHeightOfAnimatorEnd) { + releaseHeight = (int) (draggingToReleaseScale * imageHeightOfAnimatorEnd); + } else { + releaseHeight = imageWrapper.getHeight(); + } + if (imageWrapper.getWidth() != imageWidthOfAnimatorEnd) { + releaseWidth = (int) (draggingToReleaseScale * imageWidthOfAnimatorEnd); + } else { + releaseWidth = imageWrapper.getWidth(); + } + if (imageWrapper.getMarginTop() != imageTopOfAnimatorEnd) { + releaseY = imageWrapper.getMarginTop() + (int) (draggingToReleaseScale * imageTopOfAnimatorEnd); + } else { + releaseY = imageWrapper.getMarginTop(); + } + if (imageWrapper.getMarginLeft() != imageLeftOfAnimatorEnd) { + releaseLeft = imageWrapper.getMarginLeft() + (int) (draggingToReleaseScale * imageLeftOfAnimatorEnd); + } else { + releaseLeft = imageWrapper.getMarginLeft(); + } + imageWrapper.setWidth(releaseWidth); + imageWrapper.setHeight(releaseHeight); + imageWrapper.setMarginTop((int) releaseY); + imageWrapper.setMarginLeft(releaseLeft); + } else { + releaseLeft = imageWrapper.getMarginLeft(); + releaseY = imageWrapper.getMarginTop(); + releaseWidth = imageWrapper.getWidth(); + releaseHeight = imageWrapper.getHeight(); + } + + if ((isLongHeightImage || isLongWidthImage) && getContentView() instanceof SketchImageView) { + SketchImageView sketchImageView = (SketchImageView) getContentView(); + if (sketchImageView.getZoomer() != null) { + //如果是长图 则重新更改宽高 因为长图缩放到最小时需要大小变化 + float ratio = sketchImageView.getZoomer().getZoomScale() / sketchImageView.getZoomer().getMaxZoomScale(); + if (isLongHeightImage) { + int tempWidth = (int) (screenWidth * ratio); + releaseLeft = releaseLeft + (releaseWidth - tempWidth) / 2; + releaseWidth = tempWidth; + } else { + int tempHeight = (int) (screenHeight * ratio); + releaseY = releaseY + (releaseHeight - tempHeight) / 2; + releaseHeight = tempHeight; + } + changeImageViewToCenterCrop(); + } + } + changeImageViewToCenterCrop(); + ValueAnimator valueAnimator = ValueAnimator.ofFloat(releaseY, mOriginTop); + valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float value = (float) animation.getAnimatedValue(); + min2NormalAndDrag2Min(value, releaseY, mOriginTop, releaseLeft, mOriginLeft, releaseWidth, mOriginWidth, releaseHeight, mOriginHeight); + } + }); + valueAnimator.setDuration(animationDuration).start(); + if (onReleaseListener != null) { + onReleaseListener.onRelease(false, true); + } + changeBackgroundViewAlpha(true); + } + + + /** + * 配置更改后 重新更新大小 根据存储的原宽高进行更新 + */ + public void notifySizeConfig() { + screenWidth = getResources().getDisplayMetrics().widthPixels; + screenHeight = getResources().getDisplayMetrics().heightPixels; + notifySize(realWidth, realHeight); + } + + public void notifySize(int width, int height) { + notifySize(width, height, false); + } + + public void notifySize(int width, int height, boolean showRightNow) { + realWidth = width; + realHeight = height; + + + if (realWidth == 0 || realHeight == 0) { + return; + } + + int newWidth; + int newHeight; + ImageSizeCalculator sizeCalculator = new ImageSizeCalculator(); + if (sizeCalculator.canUseReadModeByHeight(realWidth, realHeight) || + sizeCalculator.canUseReadModeByWidth(realWidth, realHeight) || + screenWidth / (float) screenHeight < realWidth / (float) realHeight + ) { + isLongHeightImage = sizeCalculator.canUseReadModeByHeight(realWidth, realHeight) && getContentView() instanceof SketchImageView; + isLongWidthImage = sizeCalculator.canUseReadModeByWidth(realWidth, realHeight) && getContentView() instanceof SketchImageView; + newWidth = screenWidth; + newHeight = (int) (newWidth * (realHeight / (float) realWidth)); + if (newHeight >= screenHeight || sizeCalculator.canUseReadModeByWidth(realWidth, realHeight)) { + newHeight = screenHeight; + } + } else { + newHeight = screenHeight; + newWidth = (int) (newHeight * (realWidth / (float) realHeight)); + } + + final int endLeft = (screenWidth - newWidth) / 2; + final int endHeight = newHeight; + final int endWidth = newWidth; +// if (targetImageHeight == endHeight && targetImageWidth == endWidth) { +// return; +// } + + if (showRightNow) { + targetImageHeight = endHeight; + targetImageWidth = endWidth; + targetImageTop = (screenHeight - targetImageHeight) / 2; + imageWrapper.setHeight(targetImageHeight); + imageWrapper.setWidth(endWidth); + imageWrapper.setMarginTop(targetImageTop); + imageWrapper.setMarginLeft(endLeft); + if (isPhoto) { + setImageDataOfAnimatorEnd(); + changeContentViewToFullscreen(); + } + return; + } + + //如果Y轴不进行变化 则只变化宽高 该情况暂时发现用在屏幕旋转的情况下 正方形图片 + if (targetImageTop == (screenHeight - endHeight) / 2) { + final int startLeft = imageWrapper.getMarginLeft(); + ValueAnimator animator = ValueAnimator.ofInt(targetImageWidth, endWidth); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + isAnimating = true; + int value = (int) valueAnimator.getAnimatedValue(); + if (endWidth - targetImageWidth == 0) { + imageWrapper.setWidth(targetImageWidth); + imageWrapper.setHeight(targetImageHeight); + imageWrapper.setMarginLeft((int) (startLeft)); + } else { + float yPercent = (value - targetImageWidth) / (float) (endWidth - targetImageWidth); + float xOffset = yPercent * (endLeft - startLeft); + float widthOffset = yPercent * (endWidth - targetImageWidth); + float heightOffset = yPercent * (endHeight - targetImageHeight); + imageWrapper.setWidth(targetImageWidth + widthOffset); + imageWrapper.setHeight(targetImageHeight + heightOffset); + imageWrapper.setMarginLeft((int) (startLeft + xOffset)); + } + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimating = false; + setImageDataOfAnimatorEnd(); + if (isPhoto) { + changeContentViewToFullscreen(); + } else { + targetImageHeight = endHeight; + targetImageWidth = endWidth; + targetImageTop = (screenHeight - targetImageHeight) / 2; + } + } + }); + animator.setDuration(animationDuration); + animator.start(); + } else { + ValueAnimator animator = ValueAnimator.ofInt(targetImageTop, (screenHeight - endHeight) / 2); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + isAnimating = true; + int value = (int) valueAnimator.getAnimatedValue(); + min2NormalAndDrag2Min(value, targetImageTop, (screenHeight - endHeight) / 2, + 0, endLeft, targetImageWidth, endWidth, + targetImageHeight, endHeight); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimating = false; + setImageDataOfAnimatorEnd(); + if (isPhoto) { + changeContentViewToFullscreen(); + } else { + targetImageHeight = endHeight; + targetImageWidth = endWidth; + targetImageTop = (screenHeight - targetImageHeight) / 2; + } + } + }); + animator.setDuration(animationDuration); + animator.start(); + } + } + + + public void putData(int left, int top, int originWidth, int originHeight) { + putData(left, top, originWidth, originHeight, 0, 0); + } + + public void putData(int left, int top, int originWidth, int originHeight, int realWidth, int realHeight) { + this.realWidth = realWidth; + this.realHeight = realHeight; + mOriginLeft = left; + mOriginTop = top; + mOriginWidth = originWidth; + mOriginHeight = originHeight; + } + + public void show(boolean showImmediately) { + setVisibility(View.VISIBLE); + mAlpha = showImmediately ? mAlpha = 1 : 0; + getLocation(mOriginWidth, mOriginHeight, showImmediately); + } + + + private void getLocation(float minViewWidth, float minViewHeight, final boolean showImmediately) { + int[] locationImage = new int[2]; + contentLayout.getLocationOnScreen(locationImage); + float targetSize; + targetImageWidth = screenWidth; + if (realHeight != 0 && realWidth != 0) { + notifySize(realWidth, realHeight, true); + return; + } else { + targetSize = minViewHeight / minViewWidth; + targetImageHeight = (int) (screenWidth * targetSize); + targetImageTop = (screenHeight - targetImageHeight) / 2; + } + + + imageWrapper.setWidth(mOriginWidth); + imageWrapper.setHeight(mOriginHeight); + imageWrapper.setMarginLeft(mOriginLeft); + imageWrapper.setMarginTop(mOriginTop); + + minWidth = (int) (targetImageWidth * DEFAULT_MIN_SCALE); + minHeight = (int) (targetImageHeight * DEFAULT_MIN_SCALE); + + if (showImmediately) { + mAlpha = 1f; + backgroundView.setAlpha(mAlpha); + min2NormalAndDrag2Min(targetImageTop, 0, targetImageWidth, targetImageHeight); + if (onShowFinishListener != null) { + onShowFinishListener.showFinish(this, true); + } + } else { + ValueAnimator valueAnimator = ValueAnimator.ofFloat(mOriginTop, targetImageTop); + valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float value = (float) animation.getAnimatedValue(); + min2NormalAndDrag2Min(value, mOriginTop, targetImageTop, mOriginLeft, 0, + mOriginWidth, targetImageWidth, mOriginHeight, targetImageHeight); + } + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimating = false; + if (onShowFinishListener != null) { + onShowFinishListener.showFinish(DragDiootoView.this, false); + } + } + }); + valueAnimator.setDuration(animationDuration).start(); + changeBackgroundViewAlpha(false); + } + } + + /** + * @param isToZero 是否透明 + */ + private void changeBackgroundViewAlpha(final boolean isToZero) { + final float end = isToZero ? 0 : 1f; + ValueAnimator valueAnimator = ValueAnimator.ofFloat(mAlpha, end); + valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + isAnimating = true; + mAlpha = (Float) valueAnimator.getAnimatedValue(); + backgroundView.setAlpha(mAlpha); + } + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimating = false; + if (isToZero) { + setVisibility(View.GONE); + if (onFinishListener != null) { + onFinishListener.callFinish(); + } + } + } + }); + valueAnimator.setDuration(animationDuration); + valueAnimator.start(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + int y = (int) event.getY(); + View view = getContentView(); + if (view instanceof SketchImageView) { + SketchImageView sketchImageView = (SketchImageView) view; + //如果是长图 没有缩放到最小,则不给事件 + if (sketchImageView.getZoomer() != null) { + if (isLongHeightImage || isLongWidthImage) { + if (sketchImageView.getZoomer().getZoomScale() > sketchImageView.getZoomer().getMinZoomScale()) { + return super.dispatchTouchEvent(event); + } + } else if ((Math.round(sketchImageView.getZoomer().getSupportZoomScale() * 1000) / 1000f) > 1) { + //如果对图片进行缩放或者缩小操作 则不给事件 + return super.dispatchTouchEvent(event); + } + } + } + switch (event.getActionMasked()) { + case MotionEvent.ACTION_POINTER_DOWN: + isMulitFinger = true; + break; + case MotionEvent.ACTION_DOWN: + mDownX = event.getX(); + mDownY = event.getY(); + mTranslateX = 0; + mTranslateY = 0; + //触摸背景需要捕捉事件 + if (!isTouchPointInContentLayout(contentLayout, event)) { + mLastY = y; + return true; + } + break; + case MotionEvent.ACTION_MOVE: + float moveX = event.getX(); + float moveY = event.getY(); + mTranslateX = moveX - mDownX; + mTranslateY = moveY - mDownY; + mYDistanceTraveled += Math.abs(mTranslateY); + mXDistanceTraveled += Math.abs(mTranslateX); + + if (isAnimating) { + break; + } + + if (view instanceof SketchImageView && (isLongHeightImage || isLongWidthImage)) { + //长图缩放到最小比例 拖动时显示方式需要更新 并且不能启用阅读模式 + SketchImageView sketchImageView = (SketchImageView) view; + if (sketchImageView.getZoomer() != null) { + sketchImageView.getZoomer().setReadMode(false); + } + changeImageViewToFitCenter(); + } + if (event.getPointerCount() != 1 || isMulitFinger) { + isMulitFinger = true; + break; + } + + //如果滑动距离不足,则不需要事件 + if (Math.abs(mYDistanceTraveled) < touchSlop || (Math.abs(mTranslateX) > Math.abs(mYDistanceTraveled) && !isDrag)) { + mYDistanceTraveled = 0; + if (isTouchPointInContentLayout(contentLayout, event)) { + break; + } + break; + } + if (mDragListener != null) { + mDragListener.onDrag(this, mTranslateX, mTranslateY); + } + isDrag = true; + int dy = y - mLastY; + int newMarY = imageWrapper.getMarginTop() + dy; + + //根据触摸点的Y坐标和屏幕的比例来更改透明度 + float alphaChangePercent = mTranslateY / screenHeight; + mAlpha = 1 - alphaChangePercent; + dragAnd2Normal(newMarY, true); + break; + case MotionEvent.ACTION_UP: + if (isAnimating) { + break; + } + //如果滑动距离不足,则不需要事件 + if (Math.abs(mYDistanceTraveled) < touchSlop || (Math.abs(mYDistanceTraveled) > Math.abs(mYDistanceTraveled) && !isDrag)) { + if (!isMulitFinger && onClickListener != null) { + onClickListener.onClick(DragDiootoView.this); + } + isMulitFinger = false; + if (isTouchPointInContentLayout(contentLayout, event)) { + break; + } + break; + } + //防止滑动时出现多点触控 + if (isMulitFinger && !isDrag) { + isMulitFinger = false; + break; + } + isMulitFinger = false; + if (mTranslateY > MAX_TRANSLATE_Y) { + backToMin(); + } else { + backToNormal(); + } + isDrag = false; + mYDistanceTraveled = 0; + break; + } + + mLastY = y; + return super.dispatchTouchEvent(event); + } + + private boolean isTouchPointInContentLayout(View view, MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + if (view == null) { + return false; + } + int[] location = new int[2]; + view.getLocationOnScreen(location); + int left = location[0]; + int top = location[1]; + int right = left + view.getMeasuredWidth(); + int bottom = top + view.getMeasuredHeight(); + return y >= top && y <= bottom && x >= left + && x <= right; + } + + + @Override + protected void onDetachedFromWindow() { + + super.onDetachedFromWindow(); + } + + + public class MarginViewWrapper { + private MarginLayoutParams params; + private View viewWrapper; + + MarginViewWrapper(View view) { + this.viewWrapper = view; + params = (MarginLayoutParams) viewWrapper.getLayoutParams(); + if (params instanceof LinearLayout.LayoutParams) { + ((LinearLayout.LayoutParams) params).gravity = Gravity.START; + } + } + + public int getWidth() { + return params.width; + } + + public int getHeight() { + return params.height; + } + + void setWidth(float width) { + params.width = Math.round(width); + viewWrapper.setLayoutParams(params); + } + + void setHeight(float height) { + params.height = Math.round(height); + viewWrapper.setLayoutParams(params); + } + + void setMarginTop(int m) { + params.topMargin = m; + viewWrapper.setLayoutParams(params); + } + + void setMarginBottom(int m) { + params.bottomMargin = m; + viewWrapper.setLayoutParams(params); + } + + public int getMarginTop() { + return params.topMargin; + } + + void setMarginRight(int mr) { + params.rightMargin = mr; + viewWrapper.setLayoutParams(params); + } + + void setMarginLeft(int mr) { + params.leftMargin = mr; + viewWrapper.setLayoutParams(params); + } + + int getMarginRight() { + return params.rightMargin; + } + + public int getMarginLeft() { + return params.leftMargin; + } + + int getMarginBottom() { + return params.bottomMargin; + } + } + + public void addContentChildView(View view) { + ViewGroup parentViewGroup = (ViewGroup) view.getParent(); + if (parentViewGroup != null) { + parentViewGroup.removeView(view); + } + if (view instanceof SketchImageView) { + SketchImageView sketchImageView = (SketchImageView) view; + if (sketchImageView.getZoomer() != null) { + sketchImageView.getZoomer().setReadMode(true); + sketchImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + backToMin(); + } + }); + } + sketchImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + } + contentLayout.addView(view); + } + + private void changeContentViewToFullscreen() { + targetImageHeight = screenHeight; + targetImageWidth = screenWidth; + targetImageTop = 0; + changeImageViewToFitCenter(); + imageWrapper.setHeight(screenHeight); + imageWrapper.setWidth(screenWidth); + imageWrapper.setMarginTop(0); + imageWrapper.setMarginLeft(0); + } + + private void setImageDataOfAnimatorEnd() { + imageLeftOfAnimatorEnd = imageWrapper.getMarginLeft(); + imageTopOfAnimatorEnd = imageWrapper.getMarginTop(); + imageWidthOfAnimatorEnd = imageWrapper.getWidth(); + imageHeightOfAnimatorEnd = imageWrapper.getHeight(); + } + + private void changeImageViewToFitCenter() { + if (getContentView() instanceof SketchImageView) { + ((SketchImageView) getContentView()).setScaleType(ImageView.ScaleType.FIT_CENTER); + } + } + + private void changeImageViewToCenterCrop() { + if (getContentView() instanceof SketchImageView) { + ((SketchImageView) getContentView()).setScaleType(ImageView.ScaleType.CENTER_CROP); + } + } + + private OnFinishListener onFinishListener; + private OnDragListener mDragListener; + private OnShowFinishListener onShowFinishListener; + private OnClickListener onClickListener; + private OnReleaseListener onReleaseListener; + + public void setOnReleaseListener(OnReleaseListener onReleaseListener) { + this.onReleaseListener = onReleaseListener; + } + + public void setOnClickListener(OnClickListener onClickListener) { + this.onClickListener = onClickListener; + } + + public void setOnShowFinishListener(OnShowFinishListener onShowFinishListener) { + this.onShowFinishListener = onShowFinishListener; + } + + public void setOnDragListener(OnDragListener listener) { + mDragListener = listener; + } + + public interface OnDragListener { + void onDrag(DragDiootoView view, float moveX, float moveY); + } + + public interface OnShowFinishListener { + void showFinish(DragDiootoView dragDiootoView, boolean showImmediately); + } + + public void setOnFinishListener(OnFinishListener onFinishListener) { + this.onFinishListener = onFinishListener; + } + + public interface OnFinishListener { + void callFinish(); + } + + public interface OnReleaseListener { + void onRelease(boolean isToMax, boolean isToMin); + } + + public interface OnClickListener { + void onClick(DragDiootoView dragDiootoView); + } + + + //获得可滑动view的布局中添加的子view + public View getContentView() { + return contentLayout.getChildAt(0); + } + + public ViewGroup getContentParentView() { + return contentLayout; + } + + public boolean isPhoto() { + return isPhoto; + } + + public void setPhoto(boolean photo) { + isPhoto = photo; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/ImageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/ImageActivity.java new file mode 100644 index 0000000..c432ec5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/ImageActivity.java @@ -0,0 +1,114 @@ +package com.fengliyan.tianlesue.view.diooto; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.KeyEvent; +import android.widget.FrameLayout; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentPagerAdapter; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.diooto.config.ContentViewOriginModel; +import com.fengliyan.tianlesue.view.diooto.config.DiootoConfig; +import com.fengliyan.tianlesue.view.diooto.interfaces.IIndicator; +import com.fengliyan.tianlesue.view.diooto.interfaces.IProgress; +import com.fengliyan.tianlesue.view.diooto.tools.NoScrollViewPager; + +import java.util.ArrayList; +import java.util.List; + +public class ImageActivity extends BaseActivity { + private NoScrollViewPager mViewPager; + List contentViewOriginModels; + List fragmentList; + DiootoConfig diootoConfig; + FrameLayout indicatorLayout; + static IIndicator iIndicator; + static IProgress iProgress; + boolean isNeedAnimationForClickPosition = true; + + public static void startImageActivity(Activity activity, DiootoConfig diootoConfig) { + Intent intent = new Intent(activity, ImageActivity.class); + intent.putExtra("config", diootoConfig); + activity.startActivity(intent); + activity.overridePendingTransition(0, 0); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN; +// uiFlags |= 0x00001000; +// getWindow().getDecorView().setSystemUiVisibility(uiFlags); +// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + hideTitleBar(); + setContentView(R.layout.activity_image_for_display); + mViewPager = findViewById(R.id.viewPager); + mViewPager.setOffscreenPageLimit(6); + indicatorLayout = findViewById(R.id.indicatorLayout); + diootoConfig = getIntent().getParcelableExtra("config"); + int currentPosition = diootoConfig.getPosition(); + String[] imageUrls = diootoConfig.getImageUrls(); + contentViewOriginModels = diootoConfig.getContentViewOriginModels(); + fragmentList = new ArrayList<>(); + for (int i = 0; i < contentViewOriginModels.size(); i++) { + ImageFragment imageFragment = ImageFragment.newInstance( + imageUrls[i], i, diootoConfig.getType(), + contentViewOriginModels.size() == 1 || diootoConfig.getPosition() == i, contentViewOriginModels.get(i) + ); + fragmentList.add(imageFragment); + } + mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { + @Override + public Fragment getItem(int position) { + return fragmentList.get(position); + } + + @Override + public int getCount() { + return fragmentList.size(); + } + }); + mViewPager.setCurrentItem(currentPosition); + if (iIndicator != null && contentViewOriginModels.size() != 1) { + iIndicator.attach(indicatorLayout); + iIndicator.onShow(mViewPager); + } + } + + //用来判断第一次点击的时候是否需要动画 第一次需要动画 后续viewpager滑动回到该页面的时候 不做动画 + public boolean isNeedAnimationForClickPosition(int position) { + return isNeedAnimationForClickPosition && diootoConfig.getPosition() == position; + } + + public void refreshNeedAnimationForClickPosition() { + isNeedAnimationForClickPosition = false; + } + + public void finishView() { + if (Diooto.onFinishListener != null) { + Diooto.onFinishListener.finish(fragmentList.get(mViewPager.getCurrentItem()).getDragDiootoView()); + } + Diooto.onLoadPhotoBeforeShowBigImageListener = null; + Diooto.onShowToMaxFinishListener = null; + Diooto.onProvideViewListener = null; + Diooto.onFinishListener = null; + iIndicator = null; + iProgress = null; + finish(); + overridePendingTransition(0, 0); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + fragmentList.get(mViewPager.getCurrentItem()).backToMin(); + return true; + } + return super.onKeyDown(keyCode, event); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/ImageFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/ImageFragment.java new file mode 100644 index 0000000..fa0c40b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/ImageFragment.java @@ -0,0 +1,352 @@ +package com.fengliyan.tianlesue.view.diooto; + +import android.content.res.Configuration; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.ViewCompat; +import androidx.fragment.app.Fragment; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.diooto.config.ContentViewOriginModel; +import com.fengliyan.tianlesue.view.diooto.config.DiootoConfig; +import com.fengliyan.uikit.sketch.Sketch; +import com.fengliyan.uikit.sketch.SketchImageView; +import com.fengliyan.uikit.sketch.cache.DiskCache; +import com.fengliyan.uikit.sketch.decode.ImageAttrs; +import com.fengliyan.uikit.sketch.drawable.SketchGifDrawable; +import com.fengliyan.uikit.sketch.request.CancelCause; +import com.fengliyan.uikit.sketch.request.DisplayListener; +import com.fengliyan.uikit.sketch.request.DownloadProgressListener; +import com.fengliyan.uikit.sketch.request.ErrorCause; +import com.fengliyan.uikit.sketch.request.ImageFrom; +import com.fengliyan.uikit.sketch.request.LoadListener; +import com.fengliyan.uikit.sketch.request.LoadRequest; +import com.fengliyan.uikit.sketch.request.LoadResult; +import com.fengliyan.uikit.sketch.util.SketchUtils; + + + +public class ImageFragment extends Fragment { + DragDiootoView dragDiootoView; + ContentViewOriginModel contentViewOriginModel; + String url; + SketchImageView sketchImageView; + int position; + int type = DiootoConfig.PHOTO; + FrameLayout loadingLayout; + boolean shouldShowAnimation = false; + boolean hasCache; + + public DragDiootoView getDragDiootoView() { + return dragDiootoView; + } + + public static ImageFragment newInstance(String url, int position, int type, boolean shouldShowAnimation, ContentViewOriginModel contentViewOriginModel) { + Bundle args = new Bundle(); + args.putString("url", url); + args.putInt("position", position); + args.putBoolean("shouldShowAnimation", shouldShowAnimation); + args.putInt("type", type); + args.putParcelable("model", contentViewOriginModel); + ImageFragment fragment = new ImageFragment(); + fragment.setArguments(args); + return fragment; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_image_for_display, container, false); + if (getArguments() != null) { + url = getArguments().getString("url"); + position = getArguments().getInt("position"); + shouldShowAnimation = getArguments().getBoolean("shouldShowAnimation"); + type = getArguments().getInt("type"); + contentViewOriginModel = getArguments().getParcelable("model"); + } + loadingLayout = view.findViewById(R.id.loadingLayout); + dragDiootoView = view.findViewById(R.id.dragDiootoView); + dragDiootoView.setPhoto(type == DiootoConfig.PHOTO); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.attach(position, loadingLayout); + } + loadingLayout.setVisibility(View.GONE); + if (type == DiootoConfig.VIDEO) { + if (Diooto.onProvideViewListener == null) { + throw new RuntimeException("you should set onProvideViewListener first if you use VIDEO"); + } + if (dragDiootoView.getContentParentView().getChildCount() <= 0) { + dragDiootoView.addContentChildView(Diooto.onProvideViewListener.provideView()); + SketchImageView photoView = new SketchImageView(getContext()); + dragDiootoView.addContentChildView(photoView); + Diooto.onProvideViewListener = null; + } + } else { + sketchImageView = new SketchImageView(getContext()); + ViewCompat.setTransitionName(sketchImageView,"image"); + sketchImageView.getOptions().setDecodeGifImage(true); + sketchImageView.setZoomEnabled(true); + dragDiootoView.addContentChildView(sketchImageView); + sketchImageView.getZoomer().getBlockDisplayer().setPause(!isVisibleToUser()); + } + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + if (getContext() == null || getActivity() == null) { + return; + } + if (Diooto.onLoadPhotoBeforeShowBigImageListener != null) { + if (dragDiootoView.getContentView() instanceof SketchImageView) { + Diooto.onLoadPhotoBeforeShowBigImageListener.loadView((SketchImageView) dragDiootoView.getContentView(), position); + } else if (dragDiootoView.getContentParentView().getChildAt(1) instanceof SketchImageView) { + Diooto.onLoadPhotoBeforeShowBigImageListener.loadView((SketchImageView) dragDiootoView.getContentParentView().getChildAt(1), 0); + dragDiootoView.getContentParentView().getChildAt(1).setVisibility(View.VISIBLE); + } + } + dragDiootoView.setOnShowFinishListener(new DragDiootoView.OnShowFinishListener() { + @Override + public void showFinish(DragDiootoView view, boolean showImmediately) { + if (type == DiootoConfig.VIDEO) { + loadingLayout.setVisibility(View.VISIBLE); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onStart(position); + } + if (Diooto.onShowToMaxFinishListener != null) { + Diooto.onShowToMaxFinishListener.onShowToMax(dragDiootoView, + (SketchImageView) dragDiootoView.getContentParentView().getChildAt(1), + ImageActivity.iProgress.getProgressView(position)); + } + } else if (type == DiootoConfig.PHOTO && view.getContentView() instanceof SketchImageView && !hasCache) { + loadImage(); + } + } + }); + dragDiootoView.setOnDragListener(new DragDiootoView.OnDragListener() { + @Override + public void onDrag(DragDiootoView view, float moveX, float moveY) { + if (ImageActivity.iIndicator != null) { + ImageActivity.iIndicator.move(moveX, moveY); + } + } + }); + DiskCache diskCache = Sketch.with(getContext()).getConfiguration().getDiskCache(); + hasCache = type == DiootoConfig.PHOTO && !((ImageActivity) getActivity()).isNeedAnimationForClickPosition(position) && diskCache.exist(url); + if (hasCache) { + ((ImageActivity) getActivity()).refreshNeedAnimationForClickPosition(); + loadImage(); + } else { + dragDiootoView.putData(contentViewOriginModel.getLeft(), contentViewOriginModel.getTop(), contentViewOriginModel.getWidth(), contentViewOriginModel.getHeight()); + //如果显示的点击的position 则进行动画处理 + dragDiootoView.show(!shouldShowAnimation); + } + dragDiootoView.setOnFinishListener(new DragDiootoView.OnFinishListener() { + @Override + public void callFinish() { + if (getContext() instanceof ImageActivity) { + ((ImageActivity) getContext()).finishView(); + } + if (Diooto.onFinishListener != null) { + Diooto.onFinishListener.finish(dragDiootoView); + } + } + }); + dragDiootoView.setOnReleaseListener(new DragDiootoView.OnReleaseListener() { + @Override + public void onRelease(boolean isToMax, boolean isToMin) { + if (ImageActivity.iIndicator != null) { + ImageActivity.iIndicator.fingerRelease(isToMax, isToMin); + } + } + }); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + dragDiootoView.notifySizeConfig(); + } + + + /** + * 由于图片框架原因 这里需要使用两种不同的加载方式 + * 如果有缓存 直接可显示 + * 如果没缓存 则需要等待加载完毕 才能够将图片显示在view上 + */ + private void loadImage() { + if (getContext() == null || sketchImageView == null) { + return; + } + if (hasCache) { + loadWithCache(); + } else { + loadWithoutCache(); + } + } + + private void loadWithCache() { + sketchImageView.setDisplayListener(new DisplayListener() { + @Override + public void onStarted() { + loadingLayout.setVisibility(View.VISIBLE); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onStart(position); + } + } + + @Override + public void onCompleted(@NonNull Drawable drawable, @NonNull ImageFrom imageFrom, @NonNull ImageAttrs imageAttrs) { + loadingLayout.setVisibility(View.GONE); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onFinish(position); + } + int w = drawable.getIntrinsicWidth(); + int h = drawable.getIntrinsicHeight(); + //如果有缓存 直接将大小变为最终大小而不是去调用notifySize来更新 并且是直接显示不进行动画 + dragDiootoView.putData( + contentViewOriginModel.getLeft(), contentViewOriginModel.getTop(), + contentViewOriginModel.getWidth(), contentViewOriginModel.getHeight(), + w, h); + dragDiootoView.show(true); + } + + @Override + public void onError(@NonNull ErrorCause cause) { + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onFailed(position); + } + } + + @Override + public void onCanceled(@NonNull CancelCause cause) { + + } + }); + sketchImageView.setDownloadProgressListener(new DownloadProgressListener() { + @Override + public void onUpdateDownloadProgress(int totalLength, int completedLength) { + loadingLayout.setVisibility(View.VISIBLE); + int ratio = (int) (completedLength / (float) totalLength * 100); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onProgress(position, ratio); + } + } + }); + sketchImageView.displayImage(url); + } + + LoadRequest loadRequest; + + private void loadWithoutCache() { + loadRequest = Sketch.with(getContext()).load(url, new LoadListener() { + @Override + public void onStarted() { + loadingLayout.setVisibility(View.VISIBLE); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onStart(position); + } + } + + @Override + public void onCompleted(@NonNull LoadResult result) { + loadingLayout.setVisibility(View.GONE); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onFinish(position); + } + if (result.getGifDrawable() != null) { + result.getGifDrawable().followPageVisible(true, true); + } + int w = result.getBitmap().getWidth(); + int h = result.getBitmap().getHeight(); + dragDiootoView.notifySize(w, h); + sketchImageView.displayImage(url); + hasCache = true; + } + + @Override + public void onError(@NonNull ErrorCause cause) { + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onFailed(position); + } + } + + @Override + public void onCanceled(@NonNull CancelCause cause) { + } + }).downloadProgressListener(new DownloadProgressListener() { + @Override + public void onUpdateDownloadProgress(int totalLength, int completedLength) { + loadingLayout.setVisibility(View.VISIBLE); + int ratio = (int) (completedLength / (float) totalLength * 100); + if (ImageActivity.iProgress != null) { + ImageActivity.iProgress.onProgress(position, ratio); + } + } + }).commit(); + } + + @Override + public void onDestroyView() { + if (loadRequest != null) { + loadRequest.cancel(CancelCause.ON_DETACHED_FROM_WINDOW); + loadRequest = null; + } + super.onDestroyView(); + } + + public void backToMin() { + dragDiootoView.backToMin(); + } + + /** + * SketchImageView 生命周期处理 + */ + + @Override + public void onPause() { + super.onPause(); + if (getUserVisibleHint()) { + onUserVisibleChanged(false); + } + } + + @Override + public void onResume() { + super.onResume(); + if (getUserVisibleHint()) { + onUserVisibleChanged(true); + } + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (isResumed()) { + onUserVisibleChanged(isVisibleToUser); + } + } + + public boolean isVisibleToUser() { + return isResumed() && getUserVisibleHint(); + } + + protected void onUserVisibleChanged(boolean isVisibleToUser) { + // 不可见的时候暂停分块显示器,节省内存,可见的时候恢复 + if (sketchImageView != null && sketchImageView.isZoomEnabled()) { + sketchImageView.getZoomer().getBlockDisplayer().setPause(!isVisibleToUser); + Drawable lastDrawable = SketchUtils.getLastDrawable(sketchImageView.getDrawable()); + if (lastDrawable != null && (lastDrawable instanceof SketchGifDrawable)) { + ((SketchGifDrawable) lastDrawable).followPageVisible(isVisibleToUser, false); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/config/ContentViewOriginModel.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/config/ContentViewOriginModel.java new file mode 100644 index 0000000..d8229a1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/config/ContentViewOriginModel.java @@ -0,0 +1,78 @@ +package com.fengliyan.tianlesue.view.diooto.config; + +import android.os.Parcel; +import android.os.Parcelable; + +public class ContentViewOriginModel implements Parcelable { + public int left; + public int top; + public int width; + public int height; + + public int getLeft() { + return left; + } + + public void setLeft(int left) { + this.left = left; + } + + public int getTop() { + return top; + } + + public void setTop(int top) { + this.top = top; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(this.left); + dest.writeInt(this.top); + dest.writeInt(this.width); + dest.writeInt(this.height); + } + + public ContentViewOriginModel() { + } + + protected ContentViewOriginModel(Parcel in) { + this.left = in.readInt(); + this.top = in.readInt(); + this.width = in.readInt(); + this.height = in.readInt(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public ContentViewOriginModel createFromParcel(Parcel source) { + return new ContentViewOriginModel(source); + } + + @Override + public ContentViewOriginModel[] newArray(int size) { + return new ContentViewOriginModel[size]; + } + }; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/config/DiootoConfig.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/config/DiootoConfig.java new file mode 100644 index 0000000..c723598 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/config/DiootoConfig.java @@ -0,0 +1,105 @@ +package com.fengliyan.tianlesue.view.diooto.config; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +public class DiootoConfig implements Parcelable { + + public static int PHOTO = 1; + public static int VIDEO = 2; + private int type = PHOTO; + private String[] imageUrls; + private boolean isFullScreen = false; + private List contentViewOriginModels; + private int position; + private boolean immersive; + + public boolean isImmersive() { + return immersive; + } + + public void setImmersive(boolean immersive) { + this.immersive = immersive; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String[] getImageUrls() { + return imageUrls; + } + + public void setImageUrls(String[] imageUrls) { + this.imageUrls = imageUrls; + } + + public boolean isFullScreen() { + return isFullScreen; + } + + public void setFullScreen(boolean fullScreen) { + isFullScreen = fullScreen; + } + + public List getContentViewOriginModels() { + return contentViewOriginModels; + } + + public void setContentViewOriginModels(List contentViewOriginModels) { + this.contentViewOriginModels = contentViewOriginModels; + } + + public DiootoConfig() { + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(this.type); + dest.writeStringArray(this.imageUrls); + dest.writeByte(this.isFullScreen ? (byte) 1 : (byte) 0); + dest.writeTypedList(this.contentViewOriginModels); + dest.writeInt(this.position); + dest.writeByte(this.immersive ? (byte) 1 : (byte) 0); + } + + protected DiootoConfig(Parcel in) { + this.type = in.readInt(); + this.imageUrls = in.createStringArray(); + this.isFullScreen = in.readByte() != 0; + this.contentViewOriginModels = in.createTypedArrayList(ContentViewOriginModel.CREATOR); + this.position = in.readInt(); + this.immersive = in.readByte() != 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public DiootoConfig createFromParcel(Parcel source) { + return new DiootoConfig(source); + } + + @Override + public DiootoConfig[] newArray(int size) { + return new DiootoConfig[size]; + } + }; +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/CircleIndexIndicator.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/CircleIndexIndicator.java new file mode 100644 index 0000000..82173cf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/CircleIndexIndicator.java @@ -0,0 +1,90 @@ +package com.fengliyan.tianlesue.view.diooto.interfaces; + +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.view.diooto.tools.Utils; + + +public class CircleIndexIndicator implements IIndicator { + + private CircleIndicator circleIndicator; + private int originBottomMargin = 10; + private int currentBottomMargin = originBottomMargin; + + @Override + public void attach(FrameLayout parent) { + originBottomMargin = Utils.dip2px(parent.getContext(), 16); + FrameLayout.LayoutParams indexLp = new FrameLayout.LayoutParams(WRAP_CONTENT, Utils.dip2px(parent.getContext(), 36)); + indexLp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; + indexLp.bottomMargin = originBottomMargin; + + circleIndicator = new CircleIndicator(parent.getContext()); + circleIndicator.setGravity(Gravity.CENTER_VERTICAL); + circleIndicator.setLayoutParams(indexLp); + + parent.addView(circleIndicator); + } + + @Override + public void onShow(ViewPager viewPager) { + circleIndicator.setVisibility(View.VISIBLE); + circleIndicator.setViewPager(viewPager); + } + + + @Override + public void move(float moveX, float moveY) { + if (circleIndicator == null) { + return; + } + FrameLayout.LayoutParams indexLp = (FrameLayout.LayoutParams) circleIndicator.getLayoutParams(); + currentBottomMargin = Math.round(originBottomMargin - moveY / 6f); + if (currentBottomMargin > originBottomMargin) { + currentBottomMargin = originBottomMargin; + } + indexLp.bottomMargin = currentBottomMargin; + circleIndicator.setLayoutParams(indexLp); + } + + @Override + public void fingerRelease(boolean isToMax, boolean isToMin) { + if (circleIndicator == null) { + return; + } + int begin = 0; + int end = 0; + if (isToMax) { + begin = currentBottomMargin; + end = originBottomMargin; + } + if (isToMin) { + circleIndicator.setVisibility(View.GONE); + return; + } + final FrameLayout.LayoutParams indexLp = (FrameLayout.LayoutParams) circleIndicator.getLayoutParams(); + ValueAnimator valueAnimator = ValueAnimator.ofInt(begin, end); + valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + indexLp.bottomMargin = (int) animation.getAnimatedValue(); + circleIndicator.setLayoutParams(indexLp); + } + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + + } + }); + valueAnimator.setDuration(300).start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/CircleIndicator.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/CircleIndicator.java new file mode 100644 index 0000000..bdd7713 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/CircleIndicator.java @@ -0,0 +1,275 @@ +package com.fengliyan.tianlesue.view.diooto.interfaces; + + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.animation.Interpolator; +import android.widget.LinearLayout; + +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; + + +public class CircleIndicator extends LinearLayout { + + private final static int DEFAULT_INDICATOR_WIDTH = 5; + + private ViewPager mViewpager; + private GradientDrawable mIndicatorBackground; + + private Animator mAnimatorOut; + private Animator mAnimatorIn; + private Animator mImmediateAnimatorOut; + private Animator mImmediateAnimatorIn; + + private int mIndicatorMargin = -1; + private int mIndicatorWidth = -1; + private int mIndicatorHeight = -1; + + private int mLastPosition = -1; + private final ViewPager.OnPageChangeListener mInternalPageChangeListener = new ViewPager.OnPageChangeListener() { + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + + if (mViewpager.getAdapter() == null || mViewpager.getAdapter().getCount() <= 0) { + return; + } + + if (mAnimatorIn.isRunning()) { + mAnimatorIn.end(); + mAnimatorIn.cancel(); + } + + if (mAnimatorOut.isRunning()) { + mAnimatorOut.end(); + mAnimatorOut.cancel(); + } + + View currentIndicator; + if (mLastPosition >= 0 && (currentIndicator = getChildAt(mLastPosition)) != null) { + currentIndicator.setBackgroundDrawable(mIndicatorBackground); + mAnimatorIn.setTarget(currentIndicator); + mAnimatorIn.start(); + } + + View selectedIndicator = getChildAt(position); + if (selectedIndicator != null) { + selectedIndicator.setBackgroundDrawable(mIndicatorBackground); + mAnimatorOut.setTarget(selectedIndicator); + mAnimatorOut.start(); + } + mLastPosition = position; + } + + @Override + public void onPageScrollStateChanged(int state) { + } + }; + + private DataSetObserver mInternalDataSetObserver = new DataSetObserver() { + @Override + public void onChanged() { + super.onChanged(); + if (mViewpager == null) { + return; + } + + int newCount = mViewpager.getAdapter().getCount(); + int currentCount = getChildCount(); + + if (newCount == currentCount) { // No change + return; + } else if (mLastPosition < newCount) { + mLastPosition = mViewpager.getCurrentItem(); + } else { + mLastPosition = -1; + } + + createIndicators(); + } + }; + + public CircleIndicator(Context context) { + this(context, null); + } + + public CircleIndicator(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleIndicator(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + mIndicatorBackground = new GradientDrawable(); + mIndicatorBackground.setShape(GradientDrawable.OVAL); + mIndicatorBackground.setColor(Color.WHITE); + + handleTypedArray(context, attrs); + checkIndicatorConfig(context); + } + + private void handleTypedArray(Context context, AttributeSet attrs) { + if (attrs == null) { + return; + } + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleIndicator); + mIndicatorWidth = + typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_width, -1); + mIndicatorHeight = + typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_height, -1); + mIndicatorMargin = + typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_margin, -1); + + int orientation = typedArray.getInt(R.styleable.CircleIndicator_ci_orientation, -1); + setOrientation(orientation == VERTICAL ? VERTICAL : HORIZONTAL); + + int gravity = typedArray.getInt(R.styleable.CircleIndicator_ci_gravity, -1); + setGravity(gravity >= 0 ? gravity : Gravity.CENTER); + + typedArray.recycle(); + } + + /** + * Create and configure Indicator in Java code. + */ + public void configureIndicator(int indicatorWidth, int indicatorHeight, int indicatorMargin) { + mIndicatorWidth = indicatorWidth; + mIndicatorHeight = indicatorHeight; + mIndicatorMargin = indicatorMargin; + + checkIndicatorConfig(getContext()); + } + + private void checkIndicatorConfig(Context context) { + mIndicatorWidth = (mIndicatorWidth < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorWidth; + mIndicatorHeight = + (mIndicatorHeight < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorHeight; + mIndicatorMargin = + (mIndicatorMargin < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorMargin; + + mAnimatorOut = createAnimatorOut(); + mImmediateAnimatorOut = createAnimatorOut(); + mImmediateAnimatorOut.setDuration(0); + + mAnimatorIn = createAnimatorIn(context); + mImmediateAnimatorIn = createAnimatorIn(context); + mImmediateAnimatorIn.setDuration(0); + } + + private Animator createAnimatorOut() { + ObjectAnimator alphaAnima = ObjectAnimator.ofFloat(null, "alpha", .5f, 1.f); + ObjectAnimator scaleX = ObjectAnimator.ofFloat(null, "scaleX", 1.0f, 1.8f); + ObjectAnimator scaleY = ObjectAnimator.ofFloat(null, "scaleY", 1.0f, 1.8f); + + AnimatorSet animatorOut = new AnimatorSet(); + animatorOut.play(alphaAnima).with(scaleX).with(scaleY); + return animatorOut; + } + + private Animator createAnimatorIn(Context context) { + Animator animatorIn = createAnimatorOut(); + animatorIn.setInterpolator(new ReverseInterpolator()); + return animatorIn; + } + + public void setViewPager(ViewPager viewPager) { + mViewpager = viewPager; + if (mViewpager != null && mViewpager.getAdapter() != null) { + mLastPosition = -1; + createIndicators(); + mViewpager.removeOnPageChangeListener(mInternalPageChangeListener); + mViewpager.addOnPageChangeListener(mInternalPageChangeListener); + mInternalPageChangeListener.onPageSelected(mViewpager.getCurrentItem()); + } + } + + public DataSetObserver getDataSetObserver() { + return mInternalDataSetObserver; + } + + /** + * @deprecated User ViewPager addOnPageChangeListener + */ + @Deprecated + public void setOnPageChangeListener(ViewPager.OnPageChangeListener onPageChangeListener) { + if (mViewpager == null) { + throw new NullPointerException("can not find Viewpager , setViewPager first"); + } + mViewpager.removeOnPageChangeListener(onPageChangeListener); + mViewpager.addOnPageChangeListener(onPageChangeListener); + } + + private void createIndicators() { + removeAllViews(); + int count = mViewpager.getAdapter().getCount(); + if (count <= 0) { + return; + } + int currentItem = mViewpager.getCurrentItem(); + int orientation = getOrientation(); + + for (int i = 0; i < count; i++) { + if (currentItem == i) { + addIndicator(orientation, mImmediateAnimatorOut); + } else { + addIndicator(orientation, mImmediateAnimatorIn); + } + } + } + + private void addIndicator(int orientation, Animator animator) { + if (animator.isRunning()) { + animator.end(); + animator.cancel(); + } + + View indicator = new View(getContext()); + indicator.setBackgroundDrawable(mIndicatorBackground); + addView(indicator, mIndicatorWidth, mIndicatorHeight); + LayoutParams lp = (LayoutParams) indicator.getLayoutParams(); + + if (orientation == HORIZONTAL) { + lp.leftMargin = mIndicatorMargin; + lp.rightMargin = mIndicatorMargin; + } else { + lp.topMargin = mIndicatorMargin; + lp.bottomMargin = mIndicatorMargin; + } + + indicator.setLayoutParams(lp); + + animator.setTarget(indicator); + animator.start(); + } + + public int dip2px(float dpValue) { + final float scale = getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + private class ReverseInterpolator implements Interpolator { + @Override + public float getInterpolation(float value) { + return Math.abs(1.0f - value); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/DefaultCircleProgress.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/DefaultCircleProgress.java new file mode 100644 index 0000000..e5bd73b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/DefaultCircleProgress.java @@ -0,0 +1,53 @@ +package com.fengliyan.tianlesue.view.diooto.interfaces; + +import android.content.Context; +import android.util.SparseArray; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ProgressBar; + +import com.fengliyan.tianlesue.view.diooto.tools.LoadingView; + + +public class DefaultCircleProgress implements IProgress { + private SparseArray progressBarArray = new SparseArray<>(); + + @Override + public void attach(int position, FrameLayout parent) { + Context context = parent.getContext(); + int progressSize = LoadingView.dip2Px(context, 50); + FrameLayout.LayoutParams progressLp = new FrameLayout.LayoutParams(progressSize, progressSize); + progressLp.gravity = Gravity.CENTER; + ProgressBar loadingView = new ProgressBar(context); + loadingView.setLayoutParams(progressLp); + parent.addView(loadingView); + progressBarArray.put(position, loadingView); + } + + @Override + public void onStart(int position) { + + } + + @Override + public void onProgress(int position, int progress) { + } + + @Override + public void onFinish(int position) { + ProgressBar loadingView = progressBarArray.get(position); + loadingView.setVisibility(View.GONE); + } + + @Override + public void onFailed(int position) { + ProgressBar loadingView = progressBarArray.get(position); + loadingView.setVisibility(View.GONE); + } + + @Override + public View getProgressView(int position) { + return progressBarArray.get(position); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/DefaultPercentProgress.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/DefaultPercentProgress.java new file mode 100644 index 0000000..8448382 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/DefaultPercentProgress.java @@ -0,0 +1,60 @@ +package com.fengliyan.tianlesue.view.diooto.interfaces; + +import android.content.Context; +import android.util.SparseArray; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +import com.fengliyan.tianlesue.view.diooto.tools.LoadingView; + +/** + * Created by moyokoo. + * Date: 2018/10/17 + * 进度加载 + */ +public class DefaultPercentProgress implements IProgress { + private SparseArray progressBarArray = new SparseArray<>(); + + @Override + public void attach(int position, FrameLayout parent) { + Context context = parent.getContext(); + int progressSize = LoadingView.dip2Px(context, 50); + FrameLayout.LayoutParams progressLp = new FrameLayout.LayoutParams(progressSize, progressSize); + progressLp.gravity = Gravity.CENTER; + LoadingView loadingView = new LoadingView(context); + loadingView.setLayoutParams(progressLp); + parent.addView(loadingView); + progressBarArray.put(position, loadingView); + } + + @Override + public void onStart(int position) { + + } + + @Override + public void onProgress(int position, int progress) { + LoadingView loadingView = progressBarArray.get(position); + if (loadingView != null) { + loadingView.setProgress(progress); + } + } + + @Override + public void onFinish(int position) { + LoadingView loadingView = progressBarArray.get(position); + loadingView.loadCompleted(); + } + + @Override + public void onFailed(int position) { + LoadingView loadingView = progressBarArray.get(position); + loadingView.loadFaild(); + } + + @Override + public View getProgressView(int position) { + return progressBarArray.get(position); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/IIndicator.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/IIndicator.java new file mode 100644 index 0000000..c44e5eb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/IIndicator.java @@ -0,0 +1,22 @@ +package com.fengliyan.tianlesue.view.diooto.interfaces; + +import android.widget.FrameLayout; + +import androidx.viewpager.widget.ViewPager; + +public interface IIndicator { + + void attach(FrameLayout parent); + + void onShow(ViewPager viewPager); + + /** + * 拖动的时候 移动的 X 和 Y 距离 + */ + void move(float moveX, float moveY); + + /** + * 手指松开后的状态 + */ + void fingerRelease(boolean isToMax, boolean isToMin); +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/IProgress.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/IProgress.java new file mode 100644 index 0000000..b1da5cd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/interfaces/IProgress.java @@ -0,0 +1,20 @@ +package com.fengliyan.tianlesue.view.diooto.interfaces; + +import android.view.View; +import android.widget.FrameLayout; + +public interface IProgress { + + void attach(int position, FrameLayout parent); + + void onStart(int position); + + void onProgress(int position, int progress); + + void onFinish(int position); + + void onFailed(int position); + + View getProgressView(int position); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/Fucking.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/Fucking.java new file mode 100644 index 0000000..186a933 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/Fucking.java @@ -0,0 +1,83 @@ +package com.fengliyan.tianlesue.view.diooto.tools; + +import android.content.Context; +import android.os.Build; +import android.util.Log; +import android.view.Window; + +import java.lang.reflect.Method; + +public class Fucking { + public static int getFuckHeight(Window window) { + + Context context = window.getContext(); + if (hasNotchAtHuawei(context) || hasNotchAtVoio(window.getContext()) || hasNotchInScreenAtOPPO(context)) { + return getStatusBarHeight(window.getContext()); + } + if (Build.VERSION.SDK_INT >= 28) { + //API不是28,暂时不需要 + /*final View decorView = window.getDecorView(); + DisplayCutout displayCutout = decorView.getRootWindowInsets().getDisplayCutout(); + if (displayCutout != null) { + return displayCutout.getSafeInsetTop(); + } else { + return 0; + }*/ + return 0; + } else { + return 0; + } + } + + public static int getStatusBarHeight(Context context) { + // 获得状态栏高度 + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + return context.getResources().getDimensionPixelSize(resourceId); + } + + public static boolean hasNotchAtHuawei(Context context) { + boolean ret = false; + try { + ClassLoader classLoader = context.getClassLoader(); + Class HwNotchSizeUtil = classLoader.loadClass("com.huawei.android.util.HwNotchSizeUtil"); + Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen"); + ret = (boolean) get.invoke(HwNotchSizeUtil); + } catch (ClassNotFoundException e) { + Log.e("Notch", "hasNotchAtHuawei ClassNotFoundException"); + } catch (NoSuchMethodException e) { + Log.e("Notch", "hasNotchAtHuawei NoSuchMethodException"); + } catch (Exception e) { + Log.e("Notch", "hasNotchAtHuawei Exception"); + } finally { + return ret; + } + } + + + public static final int VIVO_NOTCH = 0x00000020;//是否有刘海 + + //vivo不提供接口获取刘海尺寸,目前vivo的刘海宽为100dp,高为27dp + public static boolean hasNotchAtVoio(Context context) { + boolean ret = false; + try { + ClassLoader classLoader = context.getClassLoader(); + Class FtFeature = classLoader.loadClass("android.util.FtFeature"); + Method method = FtFeature.getMethod("isFeatureSupport", int.class); + ret = (boolean) method.invoke(FtFeature, VIVO_NOTCH); + } catch (ClassNotFoundException e) { + Log.e("Notch", "hasNotchAtVoio ClassNotFoundException"); + } catch (NoSuchMethodException e) { + Log.e("Notch", "hasNotchAtVoio NoSuchMethodException"); + } catch (Exception e) { + Log.e("Notch", "hasNotchAtVoio Exception"); + } finally { + return ret; + } + } + + //OPPO不提供接口获取刘海尺寸,目前其有刘海屏的机型尺寸规格都是统一的。 + // 不排除以后机型会有变化。 其显示屏宽度为1080px,高度为2280px。刘海区域则都是宽度为324px, 高度为80px + public static boolean hasNotchInScreenAtOPPO(Context context) { + return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism"); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/LoadingView.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/LoadingView.java new file mode 100644 index 0000000..36e8304 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/LoadingView.java @@ -0,0 +1,144 @@ +package com.fengliyan.tianlesue.view.diooto.tools; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +public class LoadingView extends View { + private Paint mPaint1; + private Paint mPaint2; + private Paint circleBgPaint; + private double percent = 0.083; + private float interval; + private float radius; + + public LoadingView(Context context) { + this(context, null); + } + + public LoadingView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context, attrs); + } + + + private void initView(Context context, AttributeSet attrs) { + if (null == attrs) { + if (!(getLayoutParams() instanceof FrameLayout.LayoutParams)) { + FrameLayout.LayoutParams layoutParams = + new FrameLayout.LayoutParams( + dip2Px(getContext(),50), + dip2Px(getContext(),50), + Gravity.CENTER); + setLayoutParams(layoutParams); + } + } + mPaint1 = new Paint(); + mPaint1.setAntiAlias(true); + mPaint1.setColor(Color.WHITE); + mPaint2 = new Paint(); + mPaint2.setAntiAlias(true); + mPaint2.setStyle(Paint.Style.STROKE); + mPaint2.setColor(Color.WHITE); + circleBgPaint = new Paint(); + circleBgPaint.setAntiAlias(true); + circleBgPaint.setStyle(Paint.Style.FILL); + circleBgPaint.setColor(Color.parseColor("#80000000")); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + radius = (getWidth() >= getHeight() ? getHeight() : getWidth()) * 0.8f; + interval = (float) (radius * 0.2); + mPaint2.setStrokeWidth(interval / 6); + canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius / 2 - interval / 3, circleBgPaint); + canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius / 2 - interval / 3, mPaint2); + RectF localRect = new RectF( + getWidth() / 2 - radius / 2 + interval, + getHeight() / 2 - radius / 2 + interval, + getWidth() / 2 + radius / 2 - interval, + getHeight() / 2 + radius / 2 - interval); + float f1 = (float) (percent * 360); + canvas.drawArc(localRect, -90, f1, true, mPaint1); + } + + public void setProgress(double progress) { + progress = progress / 100f; + if (progress == 0) { + progress = 0.083; + } + setVisibility(VISIBLE); + this.percent = progress; + invalidate();//重新执行onDraw方法,重新绘制图形 + } + + public void loadCompleted() { + setVisibility(GONE); + } + + public void loadFaild() { + setProgress(1.0); + setVisibility(GONE); + } + + public void setOutsideCircleColor(int color) { + mPaint2.setColor(color); + } + + public void setInsideCircleColor(int color) { + mPaint1.setColor(color); + } + + public void setTargetView(View target) { + if (getParent() != null) { + ((ViewGroup) getParent()).removeView(this); + } + + if (target == null) { + return; + } + + if (target.getParent() instanceof FrameLayout) { + ((FrameLayout) target.getParent()).addView(this); + + } else if (target.getParent() instanceof ViewGroup) { + ViewGroup parentContainer = (ViewGroup) target.getParent(); + int groupIndex = parentContainer.indexOfChild(target); + parentContainer.removeView(target); + + FrameLayout badgeContainer = new FrameLayout(getContext()); + ViewGroup.LayoutParams parentLayoutParams = target.getLayoutParams(); + + badgeContainer.setLayoutParams(parentLayoutParams); + target.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + + parentContainer.addView(badgeContainer, groupIndex, parentLayoutParams); + badgeContainer.addView(target); + + badgeContainer.addView(this); + } else if (target.getParent() == null) { + + } + + } + + /* + * converts dip to px + */ + public static int dip2Px(Context context, float dip) { + return (int) (dip * context.getResources().getDisplayMetrics().density + 0.5f); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/NoScrollViewPager.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/NoScrollViewPager.java new file mode 100644 index 0000000..fc5ee5e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/NoScrollViewPager.java @@ -0,0 +1,50 @@ +package com.fengliyan.tianlesue.view.diooto.tools; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; + +import androidx.viewpager.widget.ViewPager; + +public class NoScrollViewPager extends ViewPager { + private final String TAG = NoScrollViewPager.class.getSimpleName(); + + public NoScrollViewPager(Context context) { + super(context); + } + + public NoScrollViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void setCurrentItem(int item, boolean smoothScroll) { + super.setCurrentItem(item, smoothScroll); + } + + @Override + public void setCurrentItem(int item) { + super.setCurrentItem(item, false); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + try { + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + break; + case MotionEvent.ACTION_MOVE: + break; + case MotionEvent.ACTION_UP: + break; + } + return super.onInterceptTouchEvent(ev); + } catch (IllegalArgumentException ex) { + Log.w(TAG, "onInterceptTouchEvent() ", ex); + ex.printStackTrace(); + } + return false; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/Utils.java b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/Utils.java new file mode 100644 index 0000000..93368cb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/diooto/tools/Utils.java @@ -0,0 +1,164 @@ +package com.fengliyan.tianlesue.view.diooto.tools; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class Utils { + + /** + * Set the status bar color. + */ + public static void setStatusBarColor(Activity activity, int statusBarColor) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(statusBarColor); + } + } + + /** + * Set the navigation bar color. + */ + public static void setNavigationBarColor(Activity activity, int navigationBarColor) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setNavigationBarColor(navigationBarColor); + } + } + + /** + * Set the content layout full the StatusBar, but do not hide StatusBar. + */ + public static void invasionStatusBar(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + View decorView = window.getDecorView(); + decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.setStatusBarColor(Color.TRANSPARENT); + } + } + + /** + * Set the content layout full the NavigationBar, but do not hide NavigationBar. + */ + public static void invasionNavigationBar(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + View decorView = window.getDecorView(); + decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.setNavigationBarColor(Color.TRANSPARENT); + } + } + + /** + * Set the status bar to dark. + */ + public static int StatusBarLightMode(Activity activity, boolean dark) { + int result = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (MIUISetStatusBarLightMode(activity.getWindow(), dark)) { + result = 1; + } else if (FlymeSetStatusBarLightMode(activity.getWindow(), dark)) { + result = 2; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (dark) { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } else { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + result = 3; + } + } + return result; + } + + private static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) { + boolean result = false; + if (window != null) { + try { + WindowManager.LayoutParams lp = window.getAttributes(); + Field darkFlag = WindowManager.LayoutParams.class + .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); + Field meizuFlags = WindowManager.LayoutParams.class + .getDeclaredField("meizuFlags"); + darkFlag.setAccessible(true); + meizuFlags.setAccessible(true); + int bit = darkFlag.getInt(null); + int value = meizuFlags.getInt(lp); + if (dark) { + value |= bit; + } else { + value &= ~bit; + } + meizuFlags.setInt(lp, value); + window.setAttributes(lp); + result = true; + } catch (Exception ignored) { + } + } + return result; + } + + private static boolean MIUISetStatusBarLightMode(Window window, boolean dark) { + boolean result = false; + if (window != null) { + Class clazz = window.getClass(); + try { + int darkModeFlag = 0; + Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams"); + Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE"); + darkModeFlag = field.getInt(layoutParams); + Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class); + if (dark) { + extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体 + } else { + extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体 + } + result = true; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上 + if (dark) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } else { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + } + } catch (Exception ignored) { + } + } + return result; + } + + + private static boolean setDefaultStatusBarFont(Activity activity, boolean dark) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Window window = activity.getWindow(); + View decorView = window.getDecorView(); + if (dark) { + decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } else { + decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + return true; + } + return false; + } + + public static int dip2px(Context c, float dpValue) { + final float scale = c.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/DynamicDetailActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/DynamicDetailActivity.kt new file mode 100644 index 0000000..cb3d44a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/DynamicDetailActivity.kt @@ -0,0 +1,499 @@ +package com.fengliyan.tianlesue.view.dynamics.activity + +import android.content.Context +import android.content.Intent +import android.graphics.Color +import android.os.Bundle +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.TextUtils +import android.text.style.ForegroundColorSpan +import android.view.inputmethod.InputMethodManager +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.LinearLayoutManager +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.facebook.drawee.view.SimpleDraweeView +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.ConsUser +import com.fengliyan.tianlesue.controller.constant.ConstUrl +import com.fengliyan.tianlesue.controller.dynamics.adapter.DynamicsAdapter +import com.fengliyan.tianlesue.controller.dynamics.adapter.DynamicsAdapter.* +import com.fengliyan.tianlesue.controller.dynamics.adapter.MenuPopupItemAdapter +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager +import com.fengliyan.tianlesue.controller.eventBus.DynamicLikeEvent +import com.fengliyan.tianlesue.databinding.ActivityDynamicdetailBinding +import com.fengliyan.tianlesue.databinding.HeaderDynamicDetailBinding +import com.fengliyan.tianlesue.model.dynamics.CommentBean +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean +import com.fengliyan.tianlesue.model.main.FollowResultBean +import com.fengliyan.tianlesue.utils.SPUtils +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.base.utils.view.HangUpDialog +import com.fengliyan.tianlesue.view.base.utils.view.HangUpDialog.OnHangUpListener +import com.fengliyan.tianlesue.view.main.ComplaintActivity +import com.fengliyan.tianlesue.view.main.MainPageActivity +import com.fengliyan.uikit.dialog.BottomSelectiveDialog +import com.fengliyan.uikit.toast.MaleToast +import com.ryan.github.menupopupview.MenuPopupAdapter +import com.ryan.github.menupopupview.PopupLayout +import com.ryan.github.menupopupview.PopupView +import de.greenrobot.event.EventBus +import kotlinx.android.synthetic.main.header_dynamic_detail.* +import kotlinx.android.synthetic.main.header_dynamic_detail.view.* + +class DynamicDetailActivity : BaseActivity() { + lateinit var binding: ActivityDynamicdetailBinding + lateinit var headerBinding: HeaderDynamicDetailBinding + var replcyCommentId: String? = null + var datas = mutableListOf() + var likes = mutableListOf() + val dynamidData: ArrayList = ArrayList() + lateinit var dynamicAdapter: DynamicsAdapter + var dynamic_id: String? = null + var dynamic_from: Int = 0 + lateinit var adapter: BaseQuickAdapter + lateinit var adapter1: BaseQuickAdapter + private var mSelectiveDialog: BottomSelectiveDialog? = null + private var mDeleteBottomDialog: BottomSelectiveDialog? = null + private var page: Int = 1 + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + dynamicAdapter = DynamicsAdapter(this) + bindDynamicEvent(dynamicAdapter) + dynamicAdapter.setList(dynamidData) + dynamic_id = intent.getStringExtra("dynamic_id") + dynamic_from = intent.getIntExtra("dynamic_from", 0) + binding = ActivityDynamicdetailBinding.inflate(layoutInflater) + setContentView(binding.root) + setDefaultTitle() + setTitleName("动态详情") + binding.submitBtn.setOnClickListener { + submit() + } + binding.recyclreView.layoutManager = LinearLayoutManager(this) + adapter = + object : BaseQuickAdapter(R.layout.item_comment, datas) { + init { + addChildClickViewIds(R.id.likeImageView) + } + + override fun convert(helper: BaseViewHolder, item: CommentBean) { + val imageView = helper.getView(R.id.avatarImageView) + imageView.setImageURI("${ConstUrl.IMAGE_URL}${item.avatar}") + imageView.setOnClickListener { + val intent = Intent( + context, + MainPageActivity::class.java + ) + intent.putExtra("userId", item.uid) + context.startActivity(intent) + + } + helper.setText(R.id.nameLabel, item.nickname) + helper.setText(R.id.dateLabel, "${item.city} | ${item.create_time}") + when (item.is_like) { + 1 -> helper.setImageResource(R.id.likeImageView, R.mipmap.feed_heart_) + else -> helper.setImageResource(R.id.likeImageView, R.mipmap.feed_heart) + } + if (!TextUtils.isEmpty(item.pnickname)) { + val builder = + SpannableStringBuilder("回复@${item.pnickname}: ${item.content}") + builder.setSpan( + ForegroundColorSpan(Color.RED), + 2, + item.pnickname.length + 2 + 2, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE + ) + helper.setText(R.id.contentLabel, builder) + } else { + helper.setText(R.id.contentLabel, item.content) + } + + val itemView = helper.getView(R.id.cl_comment_item) + itemView.setOnLongClickListener { + if (SPUtils.getInt(context, ConsUser.USER_ID) == item.uid) { + val menus: MutableList = ArrayList() + menus.add("删除") + val adapter: MenuPopupAdapter = MenuPopupItemAdapter(menus) + val popupView = PopupView(context) + popupView.adapter = adapter + popupView.setOnPopupItemClickListener { view, position -> + val hangUpDialog = HangUpDialog( + context, + OnHangUpListener { + dynamicDelComment( + item.dynamic_id.toString(), + item.id.toString() + ) + }, "您确定要删除吗?", "确定", "取消" + ) + hangUpDialog.show() + popupView.dismiss() + } + popupView.setPopupLocation(PopupLayout.PopupLocation.TOP) + popupView.show(it) + } + true + } + } + } + adapter.setOnItemChildClickListener { adapter, view, position -> + if (view.id == R.id.likeImageView) { + likeComment(position) + } else if (view.id == R.id.avatarImageView) { + } + } + adapter.setOnItemClickListener { adapter, view, position -> + replcyCommentId = "${datas[position].uid}" + binding.contentField.hint = "@${datas[position].nickname}" + binding.contentField.requestFocus() + showKeyboard(true) + } + adapter1 = + object : BaseQuickAdapter(R.layout.item_like, likes) { + init { + addChildClickViewIds(R.id.likeImageView) + } + + override fun convert(helper: BaseViewHolder, item: CommentBean) { + val imageView = helper.getView(R.id.avatarImageView) + imageView.setImageURI("${ConstUrl.IMAGE_URL}${item.avatar}") + imageView.setOnClickListener { + val intent = Intent( + context, + MainPageActivity::class.java + ) + intent.putExtra("userId", item.user_id) + context.startActivity(intent) + + } + helper.setText(R.id.nameLabel, item.nickname) + helper.setText(R.id.dateLabel, "${item.city} | ${item.create_time}") + + } + } + binding.recyclreView.adapter = adapter + headerBinding = HeaderDynamicDetailBinding.inflate(layoutInflater) + headerBinding.listView.adapter = dynamicAdapter + headerBinding.tvComment.isEnabled = false + headerBinding.tvComment.setOnClickListener { + adapter1.removeHeaderView(headerBinding.root) + adapter.addHeaderView(headerBinding.root) + headerBinding.tvComment.setTextColor(ContextCompat.getColor(this, R.color.one_text)) + headerBinding.tvLike.setTextColor(ContextCompat.getColor(this, R.color.three_text)) + binding.recyclreView.adapter = adapter + headerBinding.tvComment.isEnabled = false + headerBinding.tvLike.isEnabled = true + } + headerBinding.tvLike.setOnClickListener { + adapter.removeHeaderView(headerBinding.root) + adapter1.addHeaderView(headerBinding.root) + headerBinding.tvLike.setTextColor(ContextCompat.getColor(this, R.color.one_text)) + headerBinding.tvComment.setTextColor(ContextCompat.getColor(this, R.color.three_text)) + binding.recyclreView.adapter = adapter1 + headerBinding.tvComment.isEnabled = true + headerBinding.tvLike.isEnabled = false + } + adapter.addHeaderView(headerBinding.root) + binding.refreshLayout.setOnRefreshListener { + page = 1 + refresh() + getCommentList() + } + binding.refreshLayout.setOnLoadMoreListener { + page++ + getCommentList() + } + binding.refreshLayout.setEnableRefresh(true) + refresh() + getCommentList() + } + + private fun focus(userId: String) { + DynamicsManager.follow(this as BaseActivity?, + userId, + object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: FollowResultBean?, + message: String? + ) { + MaleToast.showMessage(this@DynamicDetailActivity, "关注成功") + } + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(this@DynamicDetailActivity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(this@DynamicDetailActivity, "关注失败") + } + }) + } + + + fun bindDynamicEvent(mAdapter: DynamicsAdapter) { + mAdapter.likeDynamicCallback = DynamicLikeCallback { bean -> likeFeed(bean) } + mAdapter.dynamicCommentCallback = DynamicCommentCallback { + replcyCommentId = null + binding.contentField.hint = "想和TA说..." + showKeyboard(true) + } + mAdapter.setOnMenuClickListener(OnMenuClickListener { dynamicIndex -> + mSelectiveDialog = + BottomSelectiveDialog(DynamicDetailActivity@ this, R.style.SelectiveDialog) + if (0 == dynamidData.get(dynamicIndex).is_follow) { + mSelectiveDialog?.addSelectButton( + "关注", + BottomSelectiveDialog.OnButtonSelectListener { view, index -> + mSelectiveDialog?.dismiss() + focus(dynamidData.get(dynamicIndex).getUser_id()) + }) + } + mSelectiveDialog?.addSelectButton( + "举报", + BottomSelectiveDialog.OnButtonSelectListener { view, index -> + mSelectiveDialog?.dismiss() + var intent = Intent(DynamicDetailActivity@ this, ComplaintActivity::class.java) + intent.putExtra("uid", dynamidData.get(dynamicIndex).getUser_id()) + intent.putExtra("type", 3) + startActivity(intent) + }) + mSelectiveDialog?.show() + }) + + //删除动态 + mAdapter.setOnMenuDeleteClickListener(OnMenuDeleteClickListener { position, mDynamicsItemList -> + val hangUpDialog = HangUpDialog( + this@DynamicDetailActivity, + OnHangUpListener { + deleteDynamics(mDynamicsItemList[position].id, position) + }, "您确定要删除吗?", "确定", "取消" + ) + hangUpDialog.show() +// mDeleteBottomDialog = +// BottomSelectiveDialog(this@DynamicDetailActivity, R.style.SelectiveDialog) +// mDeleteBottomDialog?.addSelectButton( +// "删除", +// BottomSelectiveDialog.OnButtonSelectListener { view, index -> +// mDeleteBottomDialog?.dismiss() +// deleteDynamics(mDynamicsItemList[position].id, position) +// }) +// mDeleteBottomDialog?.show() + }) + } + + fun likeFeed(bean: DynamicsItemBean) { + val activity = this as BaseActivity + var isLikeParam = false + if (bean.is_like == 0) { + isLikeParam = true + } + DynamicsManager.likeDynamic(activity, bean.id, isLikeParam, object : HttpUiCallBack { + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(this@DynamicDetailActivity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(this@DynamicDetailActivity, "操作失败") + } + + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + bean.is_like = 1 - bean.is_like + if (bean.is_like == 1) { + bean.like_count = bean.like_count + 1 + EventBus.getDefault() + .post(DynamicLikeEvent(bean.is_like, bean.like_count, dynamic_from)) + } else { + bean.like_count = bean.like_count - 1 + EventBus.getDefault() + .post(DynamicLikeEvent(bean.is_like, bean.like_count, dynamic_from)) + } + refresh() +// dynamicAdapter.notifyDataSetChanged() + } + }) + } + + /** + * 请求网络删除动态 + * @param id + */ + private fun deleteDynamics(id: String, index: Int) { + DynamicsManager.deleteDynamics(this as BaseActivity?, id, object : HttpUiCallBack { + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(this@DynamicDetailActivity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(this@DynamicDetailActivity, "删除失败") + } + + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + MaleToast.showMessage(this@DynamicDetailActivity, "删除成功") + finish() + } + }) + } + + private fun dynamicDelComment(dynamicId: String, contentId: String) { + DynamicsManager.dynamicDelComment( + this as BaseActivity?, + dynamicId, + contentId, + object : HttpUiCallBack { + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(this@DynamicDetailActivity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(this@DynamicDetailActivity, "删除失败") + } + + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + MaleToast.showMessage(this@DynamicDetailActivity, "删除成功") + refresh() + } + }) + } + + fun likeComment(posiiont: Int) { + val item = datas[posiiont] + DynamicsManager.commentLike(this, dynamic_id, "${item.id}", object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + item.is_like = 1 - item.is_like +// adapter.notifyDataSetChanged() + adapter.notifyItemChanged(posiiont + 1) + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity, "操作失败") + } + + }) + } + + fun refresh() { + val callback = object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: DynamicsItemBean, + tips: String? + ) { + binding.refreshLayout.finishRefresh() + dynamidData.clear() + dynamidData.add(result) + dynamicAdapter.notifyDataSetChanged() +// datas.clear() +// datas.addAll(result.comments) + likes.clear() + likes.addAll(result.likes) +// adapter.notifyDataSetChanged() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + binding.refreshLayout.finishRefresh() + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + binding.refreshLayout.finishRefresh() + MaleToast.showMessage(activity, "获取详情失败") + } + } + DynamicsManager.dynamicDeteail(this, dynamic_id, callback) + } + + fun getCommentList() { + val callback = object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: DynamicsItemBean, + tips: String? + ) { + binding.refreshLayout.finishLoadMore() + if (page == 1) { + datas.clear() + } + result.list?.let { + if (it.isNotEmpty()) { + binding.refreshLayout.setEnableLoadMore(true) + datas.addAll(it) + } else { + binding.refreshLayout.setEnableLoadMore(false) + } + } + adapter.notifyDataSetChanged() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + binding.refreshLayout.finishLoadMore() + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + binding.refreshLayout.finishLoadMore() + MaleToast.showMessage(activity, "获取详情失败") + } + } + DynamicsManager.dynamicCommentList(this, dynamic_id, page, callback) + } + + + fun submit() { + val str = binding.contentField.text.toString().trim() + if (str.isEmpty()) { + MaleToast.showMessage(this, "请输入评论内容") + return + } + showKeyboard(false) + DynamicsManager.dynamicComment( + this, + dynamic_id, + str, + replcyCommentId, + object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + binding.contentField.setText("") + refresh() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity, "评论失败") + } + + }); + + } + + fun showKeyboard(isShow: Boolean) { + val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + if (isShow) { + if (currentFocus == null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) + } else { + imm.showSoftInput(currentFocus, 0) + } + } else { + if (currentFocus != null) { + imm.hideSoftInputFromWindow( + this.currentFocus!!.windowToken, + InputMethodManager.HIDE_NOT_ALWAYS + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/DynamicPostActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/DynamicPostActivity.java new file mode 100644 index 0000000..39bc898 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/DynamicPostActivity.java @@ -0,0 +1,531 @@ +package com.fengliyan.tianlesue.view.dynamics.activity; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Bitmap; +import android.media.ThumbnailUtils; +import android.os.Bundle; +import android.provider.MediaStore; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.utils.camera2.BitmapUtils; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.VideoMessageHelper; +import com.fengliyan.tianlesue.model.dynamics.DynamicPostBean; +import com.fengliyan.tianlesue.model.dynamics.ImageUploadBean; +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.ImageUtils; +import com.fengliyan.tianlesue.view.dynamics.utils.ImageLayout; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; + +public class DynamicPostActivity extends BaseActivity implements View.OnClickListener { + public static final int MULTI_SELECTOR_REQUEST = 200; + public static final int SINGLE_SELECTOR_REQUEST = 201; + public static final int MAX_IMAGE_COUNT = 9; + private LinearLayout mPhotoLine1; + private LinearLayout mPhotoLine2; + private LinearLayout mPhotoLine3; + private EditText mEditText; + private TextView mComplaintInputText; + private int mSingleIndex; + private ArrayList mSelectPath = new ArrayList<>(); + private MultiImageSelector mSelector; + private StringBuilder mImages; + private TextView mRight; + private ProgressDialog progressDialog; + private boolean isVideo; + private VideoMessageHelper helper; + private File videoFile; + private TextWatcher mWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + String length = mEditText.getText().length() + "/300字"; + mComplaintInputText.setText(length); + } + + @Override + public void afterTextChanged(Editable editable) { + + } + }; + + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + isVideo = getIntent().getBooleanExtra("isVideo", false); + setContentView(R.layout.activity_dynamic_post); + helper = new VideoMessageHelper(this, new VideoMessageHelper.VideoMessageHelperListener() { + @Override + public void onVideoPicked(File file, String md5) { + videoFile = file; + Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.FULL_SCREEN_KIND); + BitmapUtils.savePicNoRotate(BitmapUtils.toByteArray(bitmap), "video_cover", + new Function2() { + @Override + public Unit invoke(String s, String s2) { + bitmap.recycle(); + runOnUiThread(new Runnable() { + @Override + public void run() { + List paths = new ArrayList<>(); + paths.add(s); + notifyDataSetChanged(paths); + mSelectPath.add(s); + } + }); + return null; + } + }, new Function1() { + @Override + public Unit invoke(String s) { + runOnUiThread(new Runnable() { + @Override + public void run() { + MaleToast.showMessage(DynamicPostActivity.this, "获取视频缩略图失败"); + + } + }); + return null; + } + }); + } + }); + initView(); + initTitle(); + } + + private void initTitle() { + setTitleName("发布动态"); + Title title = getCustomTitle(); + mRight = (TextView) title.findViewById(R.id.right_text); + mRight.setText("发布"); + mRight.setTextColor(getResources().getColor(R.color.mainColor)); + mRight.setVisibility(View.VISIBLE); + mRight.setTextSize(17); + mRight.setEnabled(true); + mRight.setOnClickListener(this); + + } + + private void initView() { + mPhotoLine1 = findViewById(R.id.dynamics_post_line_1); + mPhotoLine2 = findViewById(R.id.dynamics_post_line_2); + mPhotoLine3 = findViewById(R.id.dynamics_post_line_3); + mEditText = findViewById(R.id.edit_post); + mComplaintInputText = findViewById(R.id.edit_char_count); + mSelector = MultiImageSelector.create().multi().count(MAX_IMAGE_COUNT); + mImages = new StringBuilder(); + addPhotos(mSelectPath); + mEditText.addTextChangedListener(mWatcher); + } + + + public void notifyDataSetChanged(List imagePath) { + removePhotos(); + addPhotos(imagePath); + } + + private void removePhotos() { + mPhotoLine1.removeAllViews(); + mPhotoLine2.removeAllViews(); + mPhotoLine3.removeAllViews(); + } + + private void addPhotos(List imagePath) { + Iterator i = imagePath.iterator(); + int count = 0; + + while (i.hasNext()) { + String path = i.next(); + final ImageLayout image = new ImageLayout(this); + setImage(path, image); + image.setPadding(6, 0, 0, 0); + image.setOnImageHandlingListener(new ImageLayout.OnImageHandlingListener() { + @Override + public void onImageClicked() { + singleReplace(image.getImageUrl()); + } + + @Override + public void onReadyLogoClicked() { + startImageSelector(); + } + + @Override + public void onRemoveLogoClicked() { + removeImage(image.getImageUrl()); + } + }); + + if (count < 3) { + mPhotoLine1.addView(image); + } else if (count < 6) { + mPhotoLine2.addView(image); + } else if (count < 9) { + mPhotoLine3.addView(image); + } + + count++; + } + + if (isVideo) { + if (imagePath.size() == 0) { + addTail(count); + } + } else { + addTail(count); + } + + } + + void addTail(int count) { + if (count != 9) { + ImageLayout image = new ImageLayout(this); + image.setPadding(6, 0, 0, 0); + image.setOnImageHandlingListener(new ImageLayout.OnImageHandlingListener() { + @Override + public void onImageClicked() { + + } + + @Override + public void onReadyLogoClicked() { + startImageSelector(); + } + + @Override + public void onRemoveLogoClicked() { + + } + }); + +// if (count == 0) { +// image.empty(); +// } + + if (count < 3) { + mPhotoLine1.addView(image); + } else if (count < 6) { + mPhotoLine2.addView(image); + } else if (count < 9) { + mPhotoLine3.addView(image); + } + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (isVideo) { + helper.onGetLocalVideoResult(data); + } + if (requestCode == MULTI_SELECTOR_REQUEST && resultCode == RESULT_OK) { + mSelectPath.addAll(data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT)); + notifyDataSetChanged(mSelectPath); + } else if (requestCode == SINGLE_SELECTOR_REQUEST && resultCode == RESULT_OK) { + mSelectPath.remove(mSingleIndex); + mSelectPath.add(mSingleIndex, data. + getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT).get(0)); + + notifyDataSetChanged(mSelectPath); + } + } + + public void removeImage(String path) { + path = path.replace("file:", ""); + mSelectPath.remove(path); + notifyDataSetChanged(mSelectPath); + } + + public void startImageSelector() { + if (isVideo) { + helper.chooseVideoFromLocal(); + return; + } + mSelector.multi(); + mSelector.count(9 - mSelectPath.size()); + mSelector.start(this, MULTI_SELECTOR_REQUEST); + } + + public void singleReplace(String path) { + if (isVideo) { + helper.chooseVideoFromLocal(); + return; + } + path = path.replace("file:", ""); + mSingleIndex = mSelectPath.indexOf(path); + mSelector.single(); + mSelector.start(this, SINGLE_SELECTOR_REQUEST); + } + + private void setImage(String path, ImageLayout image) { + if (path != null) { + File file = new File(path); + if (null != file) { + URI uri = file.toURI(); + image.imageLoad(uri.toString()); + } + } + } + + private void compressAndUpload() { + Iterator i = mSelectPath.iterator(); + final UploadFile[] uploadFiles = new UploadFile[mSelectPath.size()]; + int count = 0; + while (i.hasNext()) { + String path = i.next(); + path = ImageUtils.compressImage(this, path, Constant.IMAGE_MEMORY_SIZE, false); + File file = new File(path); + UploadFile uploadFile = new UploadFile("file[" + count + "]", file); + uploadFiles[count] = uploadFile; + count++; + } + + if (null != uploadFiles) { + if (uploadFiles.length != 0) { + if (uploadFiles[0].getFile().exists()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + uploadImage(uploadFiles, mEditText.getText().toString()); + } + }); + } + } + } else { + progressDialog.dismiss(); + mRight.setEnabled(true); + } + + } + + void uploadVideo(String content, String coverUrl) { + UploadFile uploadFile = new UploadFile(System.currentTimeMillis() + ".mp4", videoFile); + UploadFile[] files = new UploadFile[]{uploadFile}; + DynamicsManager.uploadImage(this, files, "dynamic", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + if (result.size() > 0) { + String videoUrl = result.get(0).getUrl(); + postDynamics(content, coverUrl, videoUrl); + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, tip); + mRight.setEnabled(true); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, "视频上传失败"); + mRight.setEnabled(true); + } + }); + } + + private void uploadImage(UploadFile[] uploadFiles, final String content) { + DynamicsManager.uploadImage(this, uploadFiles, "dynamic", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + mImages = new StringBuilder(); + Iterator iterator = result.iterator(); + int count = 0; + while (iterator.hasNext()) { + UploadImageBean bean = iterator.next(); + if (0 != count) { + mImages.append(","); + } + + mImages.append(bean.getUrl()); + count++; + } + if (isVideo) { + uploadVideo(content, mImages.toString()); + } else { + postDynamics(content, mImages.toString(), null); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, tip); + mRight.setEnabled(true); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, "图片上传失败"); + mRight.setEnabled(true); + } + }); + } + + private void setImageUrl(String dynamicId, String imageUrl, String videoUrl) { + DynamicsManager.setImageUrl(this, dynamicId, imageUrl, videoUrl, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ImageUploadBean result, String message) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, "动态上传成功"); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, tip); + mRight.setEnabled(true); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showMessage(activity, "图片上传失败"); + progressDialog.dismiss(); + setResult(RESULT_OK); + finish(); + } + }); + } + + private void postDynamics(String content, final String images, final String videoUrl) { + DynamicsManager.postDynamics(this, content, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, DynamicPostBean result, String message) { + if (null != images) { + setImageUrl(result.getDynamic_id(), images, videoUrl); + } else { + if (progressDialog != null) { + progressDialog.dismiss(); + } + MaleToast.showMessage(activity, "动态上传成功"); + setResult(RESULT_OK); + finish(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (progressDialog != null) { + progressDialog.dismiss(); + } + MaleToast.showMessage(activity, tip); + mRight.setEnabled(true); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + if (progressDialog != null) { + progressDialog.dismiss(); + } + MaleToast.showMessage(activity, "动态上传失败"); + mRight.setEnabled(true); + } + }); + } + + private final int MIN_DELAY_TIME = 8000; // 两次点击间隔不能少于10000ms + private long lastClickTime; + + public boolean isFastClick() { + boolean flag = true; + long currentClickTime = System.currentTimeMillis(); + if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) { + flag = false; + } + lastClickTime = currentClickTime; + return flag; + } + + @Override + public void onClick(View view) { + if (view == mRight) { + String content = mEditText.getText().toString(); + if (TextUtils.isEmpty(content)) { + MaleToast.showFailureMsg(DynamicPostActivity.this, "请输入文字内容"); + return; + } + if (isVideo) { +// if (videoFile == null) { +// MaleToast.showFailureMsg(DynamicPostActivity.this, "请选择视频"); +// return; +// } + if (videoFile != null) { + mRight.setEnabled(false); + progressDialog = ProgressDialog.show(this, "正在发布", "请稍后..."); + new Thread(new Runnable() { + @Override + public void run() { + compressAndUpload(); + } + }).start(); + return; + } + } +// if (mSelectPath.isEmpty()) { +// MaleToast.showFailureMsg(DynamicPostActivity.this, "请选择图片"); +// return; +// } + String word = null; + if (!TextUtils.isEmpty(content)) { + word = mEditText.getText().toString(); + } + + if (!mSelectPath.isEmpty()) { + if (!isFastClick()) { + progressDialog = ProgressDialog.show(this, "正在发布", "请稍后..."); + mRight.setEnabled(false); + new Thread(new Runnable() { + @Override + public void run() { + compressAndUpload(); + + } + }).start(); + } + } else { + if (null != word || TextUtils.isEmpty(word)) { + postDynamics(content, null, null); +// MaleToast.showMessage(DynamicPostActivity.this, "请选择图片"); + } else { + MaleToast.showMessage(DynamicPostActivity.this, "请输入内容"); + } + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/FixLayoutLinearlayout.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/FixLayoutLinearlayout.java new file mode 100644 index 0000000..62e1eb4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/FixLayoutLinearlayout.java @@ -0,0 +1,66 @@ +package com.fengliyan.tianlesue.view.dynamics.activity; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Rect; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.view.WindowInsets; +import android.widget.LinearLayout; + +public class FixLayoutLinearlayout extends LinearLayout { + + private int[] mInsets = new int[4]; + + public FixLayoutLinearlayout(Context context) { + super(context); + } + + public FixLayoutLinearlayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FixLayoutLinearlayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public FixLayoutLinearlayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected final boolean fitSystemWindows(Rect insets) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // Intentionally do not modify the bottom inset. For some reason, + // if the bottom inset is modified, window resizing stops working. + + mInsets[0] = insets.left; + mInsets[1] = insets.top; + mInsets[2] = insets.right; + + insets.left = 0; + insets.top = 0; + insets.right = 0; + } + + return super.fitSystemWindows(insets); + } + + @Override + public final WindowInsets onApplyWindowInsets(WindowInsets insets) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { + mInsets[0] = insets.getSystemWindowInsetLeft(); + Log.e("mInsets[0]",""+mInsets[0]); + mInsets[1] = insets.getSystemWindowInsetTop(); + Log.e("mInsets[1]",""+mInsets[1]); + mInsets[2] = insets.getSystemWindowInsetRight(); + Log.e("mInsets[2]",""+mInsets[2]); + return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0, + insets.getSystemWindowInsetBottom())); + } else { + return insets; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/ImageDisplayActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/ImageDisplayActivity.java new file mode 100644 index 0000000..39a8f1e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/ImageDisplayActivity.java @@ -0,0 +1,73 @@ +package com.fengliyan.tianlesue.view.dynamics.activity; + +import android.os.Bundle; +import android.view.View; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.dynamics.adapter.ImageSlidePagerAdapter; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import java.util.List; + +/** + * Created by abby on 2017/7/1. + */ + +public class ImageDisplayActivity extends BaseActivity { + private ViewPager mViewPager; + private TextView mIndicator; + private int mPageCount; + private List mImagePathList; + private ImageSlidePagerAdapter mAdapter; + + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setContentView(R.layout.activity_image_display); + hideTitleBar(); + mImagePathList = getIntent().getStringArrayListExtra("urlList"); + mPageCount = getIntent().getIntExtra("pageCount", 0); + + initView(); + } + + private void initView(){ + mViewPager = (ViewPager)findViewById(R.id.image_display_viewpager); + mIndicator = (TextView)findViewById(R.id.image_display_tv_indicator); + findViewById(R.id.rl_back).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + mAdapter = new ImageSlidePagerAdapter(getSupportFragmentManager(), mImagePathList); + mViewPager.setAdapter(mAdapter); + mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + mIndicator.setText(String.valueOf(position+1)+"/"+mImagePathList.size()); + } + + @Override + public void onPageSelected(int position) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPager.setCurrentItem(mPageCount); + mAdapter.notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/MyDynamicActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/MyDynamicActivity.java new file mode 100644 index 0000000..825efa1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/MyDynamicActivity.java @@ -0,0 +1,139 @@ +package com.fengliyan.tianlesue.view.dynamics.activity; + + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.dynamics.fragment.MyDynamicAuditedFragment; +import com.fengliyan.uikit.title.Title; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ying on 2020/4/8. + * DEscribe: + */ +public class MyDynamicActivity extends BaseActivity implements View.OnClickListener { + + private ViewPager mViewPager; + private View mTitleView; + private TextView mTextAudited; + private TextView mTextpending; + private View mAuditedLine; + private View mpendingLine; + private int mItme; + private MyDynamicAuditedFragment mAuditedFragment; + private MyDynamicAuditedFragment mPendingFragment; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_my_dynamic_view_pager); + mViewPager = findViewById(R.id.dynamic_view_pager); + initTitle(); + + List fragments = new ArrayList<>(); + mAuditedFragment = MyDynamicAuditedFragment.newInstance(1); + mPendingFragment = MyDynamicAuditedFragment.newInstance(0); + fragments.add(mAuditedFragment); + fragments.add(mPendingFragment); + + mViewPager.setAdapter(new MainViewPagerAdapter(getSupportFragmentManager(),fragments)); + mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + mViewPager.setCurrentItem(0, false); + } + + + private void initTitle() { + Title title = getCustomTitle(); + title.setVisibility(View.VISIBLE); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.item_my_dynamic_title, null); + mTitleView.findViewById(R.id.my_dynamic_title_return).setOnClickListener(this); + mTitleView.findViewById(R.id.my_dynamic_title_audited_layout).setOnClickListener(this); + mTitleView.findViewById(R.id.my_dynamic_title_pending_layout).setOnClickListener(this); + mTextAudited = mTitleView.findViewById(R.id.my_dynamic_title_audited); + mTextAudited.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + mTextpending = mTitleView.findViewById(R.id.my_dynamic_title_pending); + mTextpending.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mAuditedLine = mTitleView.findViewById(R.id.my_dynamic_title_audited_line); + mpendingLine = mTitleView.findViewById(R.id.my_dynamic_title_pending_line); + title.addViewTo(mTitleView, POSTION_CENTER); + + + viewPagerChange(0); + } + + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.my_dynamic_title_return: + finishActivity(); + break; + case R.id.my_dynamic_title_audited_layout: + mViewPager.setCurrentItem(0, false); + // viewPagerChange(0); + break; + case R.id.my_dynamic_title_pending_layout: + // viewPagerChange(1); + mViewPager.setCurrentItem(1, false); + break; + } + } + + private void viewPagerChange(int index) { + mItme=index; + switch (index) { + case 0: + mTextAudited.setTextColor(getResources().getColor(R.color.charcoalColor)); + mTextAudited.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mAuditedLine.setVisibility(View.VISIBLE); + mTextpending.setTextColor(getResources().getColor(R.color.nofocus)); + mTextpending.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mpendingLine.setVisibility(View.GONE); + break; + case 1: + mTextpending.setTextColor(getResources().getColor(R.color.charcoalColor)); + mTextpending.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mpendingLine.setVisibility(View.VISIBLE); + mTextAudited.setTextColor(getResources().getColor(R.color.nofocus)); + mTextAudited.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mAuditedLine.setVisibility(View.GONE); + break; + } + + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/PageVideoPlayActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/PageVideoPlayActivity.kt new file mode 100644 index 0000000..8dbfe28 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/PageVideoPlayActivity.kt @@ -0,0 +1,173 @@ +package com.fengliyan.tianlesue.view.dynamics.activity + +import android.animation.ValueAnimator +import android.content.Intent +import android.os.Bundle +import android.text.TextUtils +import android.widget.ImageView +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.Constant +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager +import com.fengliyan.tianlesue.controller.main.manager.MainManager +import com.fengliyan.tianlesue.databinding.ActivityPageVideoPlayBinding +import com.fengliyan.tianlesue.im.uikit.common.Constans +import com.fengliyan.tianlesue.model.main.CallBean +import com.fengliyan.tianlesue.model.main.FollowResultBean +import com.fengliyan.tianlesue.utils.StrU +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.main.AgoraWithFUVideoActivity +import com.fengliyan.uikit.toast.MaleToast +import com.shuyu.gsyvideoplayer.utils.GSYVideoType + +class PageVideoPlayActivity : BaseActivity() { + lateinit var binding: ActivityPageVideoPlayBinding + private var userId: Int = 0 + private var videoUrl: String? = "" + private var age: Int = 0 + private var nickname: String? = "" + private var avatarUrl: String? = "" + private var isFollow: Int = 0 + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityPageVideoPlayBinding.inflate(layoutInflater) + setContentView(binding.root) + setDefaultTitle() + hideTitleBar() + userId = intent.getIntExtra("userId", 0) + videoUrl = intent.getStringExtra("videoUrl") + age = intent.getIntExtra("age", 0) + nickname = intent.getStringExtra("nickname") + avatarUrl = intent.getStringExtra("avatar_url") + isFollow = intent.getIntExtra("is_follow", 0) + binding.ivBack.setOnClickListener { + finish() + } + GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_FULL) + binding.videoView.setUp( + Constans.IMAGE_URL + videoUrl, true, "" + ) + binding.videoView.isLooping = true + val duration = if (binding.videoView.duration > 0) { + binding.videoView.duration.toLong() + } else { + 15000 + } + binding.videoView.startPlayLogic() + binding.progress.setRadius(36f) + binding.progress.post { //设置进度条长度 默认px + binding.progress.progress = binding.progress.measuredWidth.toFloat() + //设置动画时间 + binding.progress.setDuration(duration) + binding.progress.setRepeatCount(ValueAnimator.INFINITE) + binding.progress.startAnim() + } + binding.ivCall.setOnClickListener { getCallInfo(userId, 0) } + + binding.ivUserAvatar.setImageURI(StrU.getResourcePath(avatarUrl, this)) + binding.ivUserAvatar.setOnClickListener { finish() } + if (!TextUtils.isEmpty(nickname)) { + binding.tvNickName.text = nickname + } + binding.tvAge.text = age.toString() + if (isFollow == 0) { + binding.ivFollow.setImageResource(R.drawable.ic_play_unfollow) + } else { + binding.ivFollow.setImageResource(R.drawable.ic_play_follow) + } + binding.ivFollow.setOnClickListener { + focus(userId.toString() + "", binding.ivFollow) + } + } + + private fun getCallInfo(mUid: Int, callType: Int) { + MainManager.getCallInfo(this, mUid, 1, callType, object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: CallBean?, message: String?) { + val intent = Intent( + activity, + AgoraWithFUVideoActivity::class.java + ) + intent.putExtra(Constant.SOCKET_URL, result?.socket_url) + intent.putExtra("isCaller", true) + intent.putExtra("callType", callType) + intent.putExtra("roomId", result?.room_id?.toInt()) + intent.putExtra("avatar", result?.to_avatar) + intent.putExtra("nickName", result?.to_nickname) + intent.putExtra("price", result?.skill?.price) + intent.putExtra("toUid", result?.to_uid) + intent.putExtra("porn_check_bean_v2", result?.porn_checkV2) + intent.putExtra("diff_num", result?.guard?.diff_num) + intent.putExtra("guard_price", result?.guard?.guard_price) + intent.putExtra("free_num", result?.free_num) + intent.putExtra( + "isRisk", + result!!.from_risk_status == 1 || result.to_risk_status == 1 + ) + val callBean = CallBean() + callBean.user_id = userId.toString() + callBean.age = age + callBean.video_url = videoUrl + callBean.nickname = nickname + callBean.avatar_url = avatarUrl + intent.putExtra("bean", callBean) + startActivity(intent) + } + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(activity, "请重试") + } + + }) + } + + private fun focus(userId: String, iv_follow: ImageView) { + DynamicsManager.follow(this, + userId, + object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: FollowResultBean?, + tips: String? + ) { + if (result != null) { + if (StrU.equals("add", result.action)) { + iv_follow.setImageResource(R.drawable.ic_play_follow) + MaleToast.showMessage(activity, "关注成功") + } else { + iv_follow.setImageResource(R.drawable.ic_play_unfollow) + MaleToast.showMessage(activity, tips) + } + } + } + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(activity, "关注失败") + } + }) + } + + override fun onPause() { + super.onPause() + binding.videoView.onVideoPause() + } + + override fun onRestart() { + super.onRestart() + binding.videoView.onVideoResume() + } + + override fun onDestroy() { + super.onDestroy() + binding.videoView.setVideoAllCallBack(null) + binding.videoView.release() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/QYPreviewVideoActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/QYPreviewVideoActivity.kt new file mode 100644 index 0000000..7e55688 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/activity/QYPreviewVideoActivity.kt @@ -0,0 +1,36 @@ +package com.fengliyan.tianlesue.view.dynamics.activity + +import android.os.Bundle +import android.view.View +import com.fengliyan.tianlesue.databinding.ActivityPreviewDynamicvideoBinding +import com.fengliyan.tianlesue.view.base.BaseActivity + +class QYPreviewVideoActivity : BaseActivity() { + lateinit var binding: ActivityPreviewDynamicvideoBinding + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityPreviewDynamicvideoBinding.inflate(layoutInflater) + setContentView(binding.root) + val videoUrl = intent.getStringExtra("videoUrl") + binding.videoView.fullscreenButton.visibility = View.INVISIBLE + binding.videoView.backButton.setOnClickListener { + finish() + } + binding.videoView.setUp( + videoUrl, true, "" + ) + binding.videoView.startPlayLogic() + setDefaultTitle() + hideTitleBar() + } + + override fun onPause() { + super.onPause() + binding.videoView.onVideoPause() + } + + override fun onDestroy() { + super.onDestroy() + binding.videoView.setVideoAllCallBack(null) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/ChooseFeedTypeDialog.kt b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/ChooseFeedTypeDialog.kt new file mode 100644 index 0000000..099d1c4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/ChooseFeedTypeDialog.kt @@ -0,0 +1,37 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.fengliyan.base.base.AnyCallback +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.databinding.DialogChooseFeedtypeBinding + +class ChooseFeedTypeDialog(context: Context) : Dialog(context, R.style.FeedDialog) { + lateinit var binding:DialogChooseFeedtypeBinding + lateinit var callback: AnyCallback + enum class FeedType{ + Video, + Pic + } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DialogChooseFeedtypeBinding.inflate(layoutInflater) + setContentView(binding.root) + window!!.attributes.width = context.resources.displayMetrics.widthPixels + window!!.attributes.height = context.resources.displayMetrics.heightPixels + binding.closeBtn.setOnClickListener { + dismiss() + } + binding.videoBtn.setOnClickListener { + dismiss() + callback.callback(FeedType.Video) + } + binding.picBtn.setOnClickListener { + dismiss() + callback.callback(FeedType.Pic) + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/DynamicViewPagerFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/DynamicViewPagerFragment.java new file mode 100644 index 0000000..5fb4d65 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/DynamicViewPagerFragment.java @@ -0,0 +1,459 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment; + +import static android.app.Activity.RESULT_OK; +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.base.base.AnyCallback; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.dynamics.activity.DynamicPostActivity; +import com.fengliyan.tianlesue.view.dynamics.activity.MyDynamicActivity; +import com.fengliyan.tianlesue.view.main.CityPickerActivity; +import com.fengliyan.tianlesue.view.settings.RealNameActivity; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.title.Title; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2018/12/24. + */ + +public class DynamicViewPagerFragment extends Fragment implements View.OnClickListener { + + private View mTitleView; + private TextView mTitleText1; + private TextView mTitleText2; + private TextView mTitleText3; + private View mTitleBottom1; + private View mTitleBottom2; + private View mTitleBottom3; + private SimpleDraweeView mTitleTextMydynamic; + private View mTitleTag1; + private View mTitleTag2; + private View mTitleTag3; + private View mTitlePost; + private ViewPager mDynamicViewPager; + private MainViewPagerAdapter mViewPagerAdapter; + private List mDynamicFragments = new ArrayList<>(); + private SameCityDynamicFragment mCityFragment; + private RecentDynamicFragment mRecent; + private FollowUsersDynamicFragment mFocusFragment; + private int currentag = 0; + private ImageView mIvMoreCity; + private ImageView iv_address; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_dynamic_view_pager, container, false); + initTitle(); + initView(v); + return v; + } + + @Override + public void onHiddenChanged(boolean hidden) { + if (!hidden) { + initTitle(); + viewPagerChange(mIndex); + } + } + + private void initView(View v) { + mDynamicViewPager = v.findViewById(R.id.dynamic_view_pager); + v.findViewById(R.id.addFeedBtn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + addFeed(); + } + }); + mDynamicViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + + } + + @Override + public void onPageSelected(int position) { + currentag = position; + if (0 == position) { + viewPagerChange(1); + } else if (1 == position) { + viewPagerChange(2); + } else if (2 == position) { + viewPagerChange(3); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPagerAdapter = new MainViewPagerAdapter(getChildFragmentManager(), + mDynamicFragments); + + mCityFragment = new SameCityDynamicFragment(); + mRecent = new RecentDynamicFragment(); + mFocusFragment = new FollowUsersDynamicFragment(); + + mDynamicFragments.add(mRecent); + mDynamicFragments.add(mFocusFragment); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) != 0 && SPUtils.getInt(getContext(), ConsUser.TYPE) != 2) { + mDynamicFragments.add(mCityFragment); + } + + mDynamicViewPager.setAdapter(mViewPagerAdapter); + mDynamicViewPager.setCurrentItem(0, false); + mDynamicViewPager.setOffscreenPageLimit(2); + + mTitleText1.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom1.setVisibility(View.VISIBLE); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + + mTitleText2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + + mTitleText3.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + + if (!TextUtils.isEmpty(SPUtils.getString(getActivity(), ConsUser.DYNAMIC_CITY))) { + mTitleText3.setText(SPUtils.getString(getActivity(), ConsUser.DYNAMIC_CITY)); + } + } + + private int mIndex = 1; + + private void viewPagerChange(int index) { + if (null != mTitleText3) { + String city = SPUtils.getString(getActivity(), ConsUser.DYNAMIC_CITY); + if (!TextUtils.isEmpty(city)) { + mTitleText3.setText(city); + } + } + mIndex = index; + switch (index) { + case 1: + mTitleText1.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mTitleBottom1.setVisibility(View.VISIBLE); + + mTitleText2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom2.setVisibility(View.GONE); + + mTitleText3.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom3.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + isReClick = false; + break; + case 2: + mTitleText2.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mTitleBottom2.setVisibility(View.VISIBLE); + + mTitleText1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom1.setVisibility(View.GONE); + + mTitleText3.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom3.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + isReClick = false; + break; + case 3: + mTitleText3.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mTitleBottom3.setVisibility(View.VISIBLE); + + mTitleText2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom2.setVisibility(View.GONE); + + mTitleText1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom1.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo2); + isReClick = true; + break; + } + } + + private void initTitle() { + Title title = ((BaseActivity) getActivity()).getCustomTitle(); + title.setVisibility(View.VISIBLE); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(getActivity(), R.layout.item_dynamic_title, null); + mTitleTextMydynamic = mTitleView.findViewById(R.id.dynamic_title_my); + iv_address = mTitleView.findViewById(R.id.iv_address); + mTitleTag1 = mTitleView.findViewById(R.id.dynamic_title_view_1); + mTitleTag2 = mTitleView.findViewById(R.id.dynamic_title_view_2); + mTitleTag3 = mTitleView.findViewById(R.id.dynamic_title_view_3); + mTitleText1 = mTitleView.findViewById(R.id.dynamic_title_name_1); + mTitleText2 = mTitleView.findViewById(R.id.dynamic_title_name_2); + mTitleText3 = mTitleView.findViewById(R.id.dynamic_title_name_3); + mTitleBottom1 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_1); + mTitleBottom2 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_2); + mTitleBottom3 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_3); + mIvMoreCity = mTitleView.findViewById(R.id.iv_more_city); + mTitlePost = mTitleView.findViewById(R.id.dynamic_title_post); + mTitleTextMydynamic.setOnClickListener(this); + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + mTitleTag3.setOnClickListener(this); + mTitlePost.setOnClickListener(this); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + iv_address.setVisibility(View.INVISIBLE); + mTitleTag3.setVisibility(View.INVISIBLE); + } else { + iv_address.setVisibility(View.VISIBLE); + mTitleTag3.setVisibility(View.VISIBLE); + } + mTitleTextMydynamic.setImageURI(ConstUrl.IMAGE_URL + UserManager.getUserInfo().getAvatar()); + title.addViewTo(mTitleView, POSTION_CENTER); + +// if (UserManager.getInstance().getUserInfo().getGender() == 2) { +// mTitlePost.setVisibility(View.GONE); +// } else { +// mTitlePost.setVisibility(View.VISIBLE); +// } + + } + + public static int REQUEST_POST = 206; + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_POST && resultCode == RESULT_OK) { + clickRefresh(); + } else if (requestCode == 1005 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(getActivity(), ConsUser.DYNAMIC_CITY, city); + mTitleText3.setText(city); + + if (!TextUtils.isEmpty(city)) { + String cityId = GlobalManager.getCityMap().get(city); + SPUtils.saveString(getActivity(), ConsUser.DYNAMIC_CITY_ID, cityId); + if (null != mCityFragment) { + mCityFragment.setCityChoose(cityId); + } + } + } + } + } + + public void clickRefresh() { + if (currentag == 0) { + if (null != mRecent) { + mRecent.getDynamicList(1, 1); + } + } else { + mDynamicViewPager.setCurrentItem(0, false); + } + } + + private boolean isReClick = false; + + void chooseFeedType() { + ChooseFeedTypeDialog dialog = new ChooseFeedTypeDialog(getActivity()); + dialog.setCallback(new AnyCallback() { + @Override + public void callback(ChooseFeedTypeDialog.FeedType feedType) { + Intent intent = new Intent(getActivity(), DynamicPostActivity.class); + intent.putExtra("isVideo", feedType == ChooseFeedTypeDialog.FeedType.Video); + getActivity().startActivityForResult(intent, REQUEST_POST); + } + }); + dialog.show(); + } + + void addFeed() { +// if (isRealName()) { +// return; +// } + if (UserManager.getUserInfo().getGender() == 2) { + isvip(1); + } else +// if (UserManager.getUserInfo().getIs_anchor() == 1) + { + chooseFeedType(); +// } else { +// GirlAuthDialog dialog = new GirlAuthDialog(getActivity()); +// dialog.show(); +// MaleToast.showMessage(getActivity(), "通过真人认证才能使用该功能"); + } + } + + @Override + public void onClick(View view) { + if (view == mTitleTag1) { + currentag = 0; + mDynamicViewPager.setCurrentItem(0, false); + } else if (view == mTitleTag2) { + currentag = 1; + mDynamicViewPager.setCurrentItem(1, false); + } else if (view == mTitleTag3) { + if (isReClick) { + Intent intent = new Intent(getActivity(), CityPickerActivity.class); +// startActivity(intent); + startActivityForResult(intent, 1005); + } else { + currentag = 2; + mDynamicViewPager.setCurrentItem(2, false); + } + + } else if (view == mTitlePost) { + + NimUIKit.startChat("11", getActivity()); + } else if (view == mTitleTextMydynamic) { +// if (isRealName()) { +// return; +// } + if (UserManager.getUserInfo().getGender() == 2) { + isvip(0); +// } else if (UserManager.getUserInfo().getIs_anchor() != 1) { +// GirlAuthDialog dialog = new GirlAuthDialog(getActivity()); +// dialog.show(); +// MaleToast.showMessage(getActivity(), "通过真人认证才能使用该功能"); + } else { + Intent intent = new Intent(getActivity(), MyDynamicActivity.class); +// startActivity(intent); + startActivityForResult(intent, 1005); + } + } + } + + private BaseMessageDialog baseMessageDialog; + + private boolean isRealName() { + if (NoClearSPUtils.getInt(getActivity(), ConsUser.DYNAMIC_REAL_NAME_SWITCH, 0) > 0 && UserManager.getUserInfo().getReal_name_status() == 0) { + if (baseMessageDialog == null) { + baseMessageDialog = new BaseMessageDialog.Builder(getActivity()).setMessage("通过实名认证才能使用该功能").setPositive("去实名").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + baseMessageDialog.dismiss(); + } + }).setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(getActivity(), RealNameActivity.class); + startActivity(intent); + baseMessageDialog.dismiss(); + } + }).build(); + } + baseMessageDialog.show(); + return true; + } + return false; + } + + // 0 我的动态 1 发布动态 + private void isvip(final int type) { +// DynamicsManager.isVip((BaseActivity) getActivity(), new HttpUiCallBack() { +// @Override +// public void onSuccess(final BaseActivity activity, VipBean result, String message) { +// +// if (result.getIf_vip() == 1) { + switch (type) { + case 0: + startActivity(new Intent(getActivity(), MyDynamicActivity.class)); + break; + case 1: + chooseFeedType(); + break; + } +// } else { +// View inflate = LayoutInflater.from(activity).inflate(R.layout.dialog_vip, null); +// final AlertDialog alertDialog = new AlertDialog.Builder(activity).setView(inflate).create(); +// inflate.findViewById(R.id.dialog_vip_no).setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// alertDialog.dismiss(); +// } +// }); +// inflate.findViewById(R.id.dialog_vip_ok).setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// activity.startActivity(new Intent(activity, MemberActivity.class)); +// alertDialog.dismiss(); +// } +// }); +// alertDialog.show(); +// alertDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); +// Display display = alertDialog.getWindow().getWindowManager().getDefaultDisplay(); +// WindowManager.LayoutParams lp = alertDialog.getWindow().getAttributes(); +// lp.width = (int) (display.getWidth()); //设置宽度 +// lp.height = WindowManager.LayoutParams.WRAP_CONTENT; +// alertDialog.getWindow().setAttributes(lp); +// } +// } + +// @Override +// public void onFailure(BaseActivity activity, String tip) { + +// } +// +// @Override +// public void onException(BaseActivity activity, Throwable e) { +// +// } +// }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/FollowUsersDynamicFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/FollowUsersDynamicFragment.java new file mode 100644 index 0000000..5119484 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/FollowUsersDynamicFragment.java @@ -0,0 +1,393 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment; + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.dynamics.adapter.DynamicsAdapter1; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.eventBus.DynamicLikeEvent; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.model.dynamics.DynamicsListBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.dynamics.activity.DynamicDetailActivity; +import com.fengliyan.tianlesue.view.main.ComplaintActivity; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2018/12/25. + * 关注 + */ + +public class FollowUsersDynamicFragment extends Fragment { + + private int mType = 2; + private LoadMoreListView mListView; + private List mImageList = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + private DynamicsAdapter1 mAdapter; + private SwipeRefreshLayout mRefresh; + private BottomSelectiveDialog mSelectiveDialog; + private BottomSelectiveDialog mDeleteBottomDialog; + private int detailPosition; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_dynamic_channel, container, false); + EventBus.getDefault().register(this); + initView(v); + if (getUserVisibleHint()) { + getBanner(); + mPage = 1; + getDynamicList(mType, 1); + } + return v; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); //防止数据预加载, 只预加载View,不预加载数据 + if (isVisibleToUser && isVisible()) { + getBanner(); + mPage = 1; + getDynamicList(mType, 1); + } + } + + private void initView(View v) { + mListView = v.findViewById(R.id.dynamics_list); + mRefresh = v.findViewById(R.id.dynamics_refresh); + mAdapter = new DynamicsAdapter1(getActivity()); + mAdapter.setList(mImageList); + mListView.setAdapter(mAdapter); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (0 != mImageList.size() && (mImageList.size() + mAdapter.getDeleteCount()) % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mImageList.size() - 2) { + getDynamicList(mType, mPage); + mPageLoad = true; + } else if (mListView.getLastVisiblePosition() <= mImageList.size() - 2) { + mPageLoad = false; + } + } + }); + + mAdapter.setOnThumbupClickedListener(new DynamicsAdapter1.OnThumbupClickedListener() { + @Override + public void onClick(View v, String uid) { + thumbup(uid); + } + }); + mAdapter.setOnGiftSendListener(new DynamicsAdapter1.OnGiftSendListener() { + @Override + public void onSend(DynamicsItemBean bean, int quantity) { + sendGift(bean.getId(), quantity, bean); + } + }); + + mAdapter.setOnMenuClickListener(new DynamicsAdapter1.OnMenuClickListener() { + @Override + public void onMenuClicked(final int dynamicIndex) { + mSelectiveDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + if (0 == mImageList.get(dynamicIndex).getIs_follow()) { + mSelectiveDialog.addSelectButton("关注", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + focus(mImageList.get(dynamicIndex).getUser_id()); + } + }); + } + + mSelectiveDialog.addSelectButton("举报", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + Intent intent = new Intent(getActivity(), ComplaintActivity.class); + intent.putExtra("uid", mImageList.get(dynamicIndex).getUser_id()); + intent.putExtra("type", 3); + startActivity(intent); + } + }); + + mSelectiveDialog.show(); + } + }); + mAdapter.likeDynamicCallback = new DynamicsAdapter1.DynamicLikeCallback() { + @Override + public void likeDynamic(DynamicsItemBean bean) { + likeFeed(bean); + } + }; + //删除动态 + mAdapter.setOnMenuDeleteClickListener(new DynamicsAdapter1.OnMenuDeleteClickListener() { + @Override + public void onMenuDelete(final int position, final List mDynamicsItemList) { + mDeleteBottomDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + mDeleteBottomDialog.addSelectButton("删除", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mDeleteBottomDialog.dismiss(); + deleteDynamics(mDynamicsItemList.get(position).getId(), position); + } + }); + + mDeleteBottomDialog.show(); + } + }); + mAdapter.setOnDetailClicked(new DynamicsAdapter1.OnDetailClickListener() { + @Override + public void onDetailClicked(int position, String id) { + detailPosition = position; + Intent intent = new Intent(getContext(), DynamicDetailActivity.class); + intent.putExtra("dynamic_id", id); + intent.putExtra("dynamic_from", 1); + startActivity(intent); + } + }); + mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + getBanner(); + mPage = 1; + getDynamicList(mType, 1); + } + }); + } + + public void onEventMainThread(DynamicLikeEvent event) { + int isLike = event.isLike(); + int likeNum = event.getLikeNum(); + int from = event.getFrom(); + if (from == 1) { + mAdapter.getmDynamicsItemList().get(detailPosition).setIs_like(isLike); + mAdapter.getmDynamicsItemList().get(detailPosition).setLike_count(likeNum); + mAdapter.notifyDataSetChanged(); + } + } + + void likeFeed(DynamicsItemBean bean) { + BaseActivity activity = (BaseActivity) getActivity(); + boolean isLikeParam = false; + if (bean.getIs_like() == 0) { + isLikeParam = true; + } + DynamicsManager.likeDynamic(activity, bean.getId(), isLikeParam, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + bean.setIs_like(1 - bean.getIs_like()); + if (bean.getIs_like() == 1) { + bean.setLike_count(bean.getLike_count() + 1); + } else { + bean.setLike_count(bean.getLike_count() - 1); + } + mAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "操作失败"); + + } + }); + } + + /** + * 请求网络删除动态 + * + * @param id + */ + private void deleteDynamics(String id, final int index) { + DynamicsManager.deleteDynamics((BaseActivity) getActivity(), id, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + mAdapter.delete(index); + MaleToast.showMessage(getActivity(), "删除成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "删除失败"); + + } + }); + } + + public void getDynamicList(int type, final int page) { + DynamicsManager.getDynamicList((BaseActivity) getActivity(), type, page, 10, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, DynamicsListBean result, String message) { + + if (page == 1) { + mImageList.clear(); + mAdapter.setDeleteCount(0); + } + + mImageList.addAll(result.getList()); + + if (mImageList.size() != 0 && mImageList.size() % 10 != 0) { //显示尾布局 + mListView.onNoDataLoaded(); + } + mAdapter.notifyDataSetChanged(); + if (page == 1) { + mListView.setSelection(0); + } + mPage++; + mRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(getActivity(), tip); + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + }); + } + + public void thumbup(String dynamicId) { + DynamicsManager.thumbup((BaseActivity) getActivity(), mType, dynamicId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { +// MaleToast.showMessage(getActivity(), "点赞成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showMessage(getActivity(), "点赞失败,请重试"); + } + }); + } + + public void sendGift(String dynamicId, final int number, final DynamicsItemBean bean) { + DynamicsManager.sendGifts((BaseActivity) getActivity(), dynamicId, number, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(getActivity(), "礼物赠送成功"); + if (null != mAdapter) { + mAdapter.setGiftCount(number + bean.getReward_count(), bean.getId()); + mAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "赠送失败,请重试"); + } + }); + } + + private void focus(String userId) { + DynamicsManager.follow((BaseActivity) getActivity(), + userId, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + MaleToast.showMessage(getActivity(), "关注成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "关注失败"); + } + }); + } + + private void getBanner() { + if (getActivity() != null) { + DynamicsManager.getBannerList((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String tips) { + List images = new ArrayList<>(); + if (null != result.getBanner()) { + if (result.getBanner().size() > 0) { + for (int i = 0; i < result.getBanner().size(); i++) { + BannerBean bean = new BannerBean(); + bean.setImage(StrU.getResourcePath(result.getBanner().get(i).getImage(), activity)); + bean.setLink_url(result.getBanner().get(i).getLink_url()); + bean.setLink_type(result.getBanner().get(i).getLink_type()); + images.add(bean); + } + mAdapter.setBannerImages(images, true); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/ImageSlideFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/ImageSlideFragment.java new file mode 100644 index 0000000..d08a86d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/ImageSlideFragment.java @@ -0,0 +1,123 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment; + +import android.graphics.Bitmap; +import android.graphics.drawable.Animatable; +import android.net.Uri; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.facebook.common.references.CloseableReference; +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder; +import com.facebook.drawee.controller.BaseControllerListener; +import com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory; +import com.facebook.imagepipeline.image.ImageInfo; +import com.facebook.imagepipeline.request.BasePostprocessor; +import com.facebook.imagepipeline.request.ImageRequest; +import com.facebook.imagepipeline.request.ImageRequestBuilder; +import com.fengliyan.tianlesue.R; + +import me.relex.photodraweeview.PhotoDraweeView; + +/** + * Created by abby on 2017/7/1. + */ + +public class ImageSlideFragment extends Fragment { + private String mUrl; + private PhotoDraweeView imageView; + + public static ImageSlideFragment newInstance(String url) { + ImageSlideFragment f = new ImageSlideFragment(); + + Bundle args = new Bundle(); + args.putString("url", url); + f.setArguments(args); + + return f; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mUrl = getArguments().getString("url"); + + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v=inflater.inflate(R.layout.fragment_image_display,container,false); + + ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(mUrl)).setPostprocessor(new BasePostprocessor() { + @Override + public String getName() { + return super.getName(); + } + + @Override + public CloseableReference process( + Bitmap sourceBitmap, + PlatformBitmapFactory bitmapFactory) { + CloseableReference bitmapRef; + if(1.5 < (sourceBitmap.getHeight() / sourceBitmap.getWidth())){ + DisplayMetrics dm = getActivity().getResources().getDisplayMetrics(); + int width = dm.widthPixels; + int height = width * sourceBitmap.getHeight() / sourceBitmap.getWidth(); + Bitmap destBitmap = Bitmap.createScaledBitmap(sourceBitmap, width, 2*height, true); + bitmapRef = bitmapFactory.createBitmap(destBitmap); + destBitmap.recycle(); + //layoutParams.width = width; + //layoutParams.height = width * imageInfo.getHeight() / imageInfo.getWidth(); + //imageView.setLayoutParams(layoutParams); + //imageView.update(width, (width * imageInfo.getHeight() / imageInfo.getWidth())); + }else{ + bitmapRef = bitmapFactory.createBitmap(sourceBitmap, 0,0, + sourceBitmap.getWidth(), + sourceBitmap.getHeight() ); + } + + return CloseableReference.cloneOrNull(bitmapRef); + + } + }).build(); + + imageView= (PhotoDraweeView) v.findViewById(R.id.image_display_image_photo); + PipelineDraweeControllerBuilder controller = Fresco.newDraweeControllerBuilder(); + //controller.setImageRequest(request); + controller.setUri(mUrl); + controller.setOldController(imageView.getController()); + controller.setControllerListener(new BaseControllerListener() { + @Override + public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) { + super.onFinalImageSet(id, imageInfo, animatable); + if (imageInfo == null || imageView == null) { + return; + } + + if(1.5 < (imageInfo.getHeight() / imageInfo.getWidth())){ + DisplayMetrics dm = getActivity().getResources().getDisplayMetrics(); + //int width = dm.widthPixels; + //LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) imageView.getLayoutParams(); + //layoutParams.width = width; + //layoutParams.height = width * imageInfo.getHeight() / imageInfo.getWidth(); + //imageView.setLayoutParams(layoutParams); + //imageView.update(width, (width * imageInfo.getHeight() / imageInfo.getWidth())); + }else { + //imageView.update(imageInfo.getWidth(), imageInfo.getHeight()); + } + + imageView.update(imageInfo.getWidth(), imageInfo.getHeight()); + } + }); + imageView.setController(controller.build()); + + return v; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/MyDynamicAuditedFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/MyDynamicAuditedFragment.java new file mode 100644 index 0000000..e7224e1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/MyDynamicAuditedFragment.java @@ -0,0 +1,304 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment; + + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.dynamics.adapter.DynamicsAdapter; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.eventBus.DynamicEvent; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.model.dynamics.DynamicsListBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.HangUpDialog; +import com.fengliyan.tianlesue.view.main.ComplaintActivity; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + + +/** + * Created by ying on 2020/4/8. + * DEscribe: + */ +public class MyDynamicAuditedFragment extends Fragment { + + private int mType = 1; + private LoadMoreListView mListView; + private List mImageList = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + private DynamicsAdapter mAdapter; + private SwipeRefreshLayout mRefresh; + private BottomSelectiveDialog mSelectiveDialog; + private BottomSelectiveDialog mDeleteBottomDialog; + + public static MyDynamicAuditedFragment newInstance(int type) { + MyDynamicAuditedFragment frag = new MyDynamicAuditedFragment(); + Bundle args = new Bundle(); + args.putInt("type", type); + frag.setArguments(args); + return frag; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + mType = getArguments().getInt("type"); + View v = inflater.inflate(R.layout.fragment_dynamic_channel, container, false); + initView(v); + if (getUserVisibleHint()) { + mPage = 1; + getDynamicList(mType, 1); + } + return v; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); //防止数据预加载, 只预加载View,不预加载数据 + if (isVisibleToUser && isVisible()) { + mPage = 1; + getDynamicList(mType, 1); + } + } + + private void initView(View v) { + mListView = v.findViewById(R.id.dynamics_list); + mRefresh = v.findViewById(R.id.dynamics_refresh); + mAdapter = new DynamicsAdapter(getActivity()); + mAdapter.setList(mImageList); + mListView.setAdapter(mAdapter); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (0 != mImageList.size() && (mImageList.size() + mAdapter.getDeleteCount()) % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mImageList.size() - 2) { + getDynamicList(mType, mPage); + mPageLoad = true; + } else if (mListView.getLastVisiblePosition() <= mImageList.size() - 2) { + mPageLoad = false; + } + } + }); + + mAdapter.setOnThumbupClickedListener(new DynamicsAdapter.OnThumbupClickedListener() { + @Override + public void onClick(View v, String uid) { + thumbup(uid); + } + }); + mAdapter.setOnGiftSendListener(new DynamicsAdapter.OnGiftSendListener() { + @Override + public void onSend(DynamicsItemBean bean, int quantity) { + sendGift(bean.getId(), quantity, bean); + } + }); + + mAdapter.setOnMenuClickListener(new DynamicsAdapter.OnMenuClickListener() { + @Override + public void onMenuClicked(final int dynamicIndex) { + mSelectiveDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + if (0 == mImageList.get(dynamicIndex).getIs_follow()) { + mSelectiveDialog.addSelectButton("关注", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + focus(mImageList.get(dynamicIndex).getUser_id()); + } + }); + } + + mSelectiveDialog.addSelectButton("举报", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + Intent intent = new Intent(getActivity(), ComplaintActivity.class); + intent.putExtra("uid", mImageList.get(dynamicIndex).getUser_id()); + intent.putExtra("type", 3); + startActivity(intent); + } + }); + + mSelectiveDialog.show(); + } + }); + + //删除动态 + mAdapter.setOnMenuDeleteClickListener(new DynamicsAdapter.OnMenuDeleteClickListener() { + @Override + public void onMenuDelete(final int position, final List mDynamicsItemList) { + HangUpDialog hangUpDialog = new HangUpDialog(getActivity(), new HangUpDialog.OnHangUpListener() { + @Override + public void onHangUp() { + deleteDynamics(mDynamicsItemList.get(position).getId(), position); + } + }, "您确定要删除吗?", "确定", "取消"); + hangUpDialog.show(); + } + }); + + mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getDynamicList(mType, 1); + } + }); + } + + /** + * 请求网络删除动态 + * + * @param id + */ + private void deleteDynamics(String id, final int index) { + DynamicsManager.deleteDynamics((BaseActivity) getActivity(), id, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + mAdapter.delete(index); + MaleToast.showMessage(getActivity(), "删除成功"); + EventBus.getDefault().post(new DynamicEvent()); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "删除失败"); + + } + }); + } + + public void thumbup(String dynamicId) { + DynamicsManager.thumbup((BaseActivity) getActivity(), mType, dynamicId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { +// MaleToast.showMessage(getActivity(), "点赞成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showMessage(getActivity(), "点赞失败,请重试"); + } + }); + } + + public void sendGift(String dynamicId, final int number, final DynamicsItemBean bean) { + DynamicsManager.sendGifts((BaseActivity) getActivity(), dynamicId, number, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(getActivity(), "礼物赠送成功"); + if (null != mAdapter) { + mAdapter.setGiftCount(number + bean.getReward_count(), bean.getId()); + mAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "赠送失败,请重试"); + } + }); + } + + private void focus(String userId) { + DynamicsManager.follow((BaseActivity) getActivity(), + userId, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + MaleToast.showMessage(getActivity(), "关注成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "关注失败"); + } + }); + } + + public void setCityChoose(String cityId) { + mPage = 1; + getDynamicList(mType, mPage); + } + + public void getDynamicList(int type, final int page) { + DynamicsManager.getMyDynamicCityList((BaseActivity) getActivity(), type, page, 10, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, DynamicsListBean result, String message) { + if (page == 1) { + mImageList.clear(); + mAdapter.setDeleteCount(0); + } + + mImageList.addAll(result.getList()); + + if (mImageList.size() == 0) mListView.onNoDataLoaded(); + +// if (mImageList.size() != 0 && mImageList.size() % 10 != 0) { //显示尾布局 +// mListView.onNoDataLoaded(); +// } + mAdapter.notifyDataSetChanged(); + if (page == 1) { + mListView.setSelection(0); + } + mPage++; + mRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(getActivity(), tip); + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/MyDynamicPendingFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/MyDynamicPendingFragment.java new file mode 100644 index 0000000..6373ca7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/MyDynamicPendingFragment.java @@ -0,0 +1,66 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment; + + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; + + +/** + * Created by ying on 2020/4/8. + * DEscribe: 废弃 未审核 和已审核 共用一个 + */ +public class MyDynamicPendingFragment extends Fragment { + private RecyclerView mRecyclerView; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + mRecyclerView = new RecyclerView(container.getContext()); + LinearLayoutManager layoutManager = new LinearLayoutManager(container.getContext()); + mRecyclerView.setLayoutManager(layoutManager); + mRecyclerView.setAdapter(new RecyclerView.Adapter() { + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new MyViewHolder(View.inflate(parent.getContext(), R.layout.item_dynamic_list, null)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { +// MyViewHolder myViewHolder = (MyViewHolder) holder; +// myViewHolder.mViewById.setText(position); + } + + @Override + public int getItemCount() { + return 10; + } + }); + return mRecyclerView; + } + + public void onRefresh(SwipeRefreshLayout layout){ + + } + + class MyViewHolder extends RecyclerView.ViewHolder { + + TextView mViewById; + + public MyViewHolder(View itemView) { + super(itemView); + mViewById = itemView.findViewById(R.id.dynamic_list_name); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/RecentDynamicFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/RecentDynamicFragment.java new file mode 100644 index 0000000..e091950 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/RecentDynamicFragment.java @@ -0,0 +1,406 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment; + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.dynamics.adapter.DynamicsAdapter1; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.eventBus.DynamicLikeEvent; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.model.dynamics.DynamicsListBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.dynamics.activity.DynamicDetailActivity; +import com.fengliyan.tianlesue.view.main.ComplaintActivity; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2018/12/25. + * 最新 + */ + +public class RecentDynamicFragment extends Fragment { + + private int mType = 1; + private LoadMoreListView mListView; + private List mImageList = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + private DynamicsAdapter1 mAdapter; + private SwipeRefreshLayout mRefresh; + private BottomSelectiveDialog mSelectiveDialog; + private BottomSelectiveDialog mDeleteBottomDialog; + private int detailPosition; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_dynamic_channel, container, false); + EventBus.getDefault().register(this); + initView(v); + if (getUserVisibleHint()) { + getBanner(); + mPage = 1; + getDynamicList(mType, 1); + } + return v; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); //防止数据预加载, 只预加载View,不预加载数据 + if (isVisibleToUser && isVisible()) { + getBanner(); + mPage = 1; + getDynamicList(mType, 1); + } + } + + private void initView(View v) { + mListView = v.findViewById(R.id.dynamics_list); + mRefresh = v.findViewById(R.id.dynamics_refresh); + mAdapter = new DynamicsAdapter1(getActivity()); + mAdapter.setList(mImageList); + mListView.setAdapter(mAdapter); +// mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { +// @Override +// public void onItemClick(AdapterView parent, View view, int position, long id) { +// Intent intent = new Intent(getActivity(), DynamicDetailActivity.class); +// intent.putExtra("dynamic_id",mImageList.get(position).getId()); +// startActivity(intent); +// } +// }); + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (0 != mImageList.size() && (mImageList.size() + mAdapter.getDeleteCount()) % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mImageList.size() - 2) { + getDynamicList(mType, mPage); + mPageLoad = true; + } else if (mListView.getLastVisiblePosition() <= mImageList.size() - 2) { + mPageLoad = false; + } + } + }); + + mAdapter.likeDynamicCallback = new DynamicsAdapter1.DynamicLikeCallback() { + @Override + public void likeDynamic(DynamicsItemBean bean) { + likeFeed(bean); + } + }; + mAdapter.setOnThumbupClickedListener(new DynamicsAdapter1.OnThumbupClickedListener() { + @Override + public void onClick(View v, String uid) { + thumbup(uid); + } + }); + mAdapter.setOnGiftSendListener(new DynamicsAdapter1.OnGiftSendListener() { + @Override + public void onSend(DynamicsItemBean bean, int quantity) { + sendGift(bean.getId(), quantity, bean); + } + }); + + mAdapter.setOnMenuClickListener(new DynamicsAdapter1.OnMenuClickListener() { + @Override + public void onMenuClicked(final int dynamicIndex) { + mSelectiveDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + if (0 == mImageList.get(dynamicIndex).getIs_follow()) { + mSelectiveDialog.addSelectButton("关注", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + focus(mImageList.get(dynamicIndex).getUser_id()); + } + }); + } + + mSelectiveDialog.addSelectButton("举报", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + Intent intent = new Intent(getActivity(), ComplaintActivity.class); + intent.putExtra("uid", mImageList.get(dynamicIndex).getUser_id()); + intent.putExtra("type", 3); + startActivity(intent); + } + }); + + mSelectiveDialog.show(); + } + }); + + //删除动态 + mAdapter.setOnMenuDeleteClickListener(new DynamicsAdapter1.OnMenuDeleteClickListener() { + @Override + public void onMenuDelete(final int position, final List mDynamicsItemList) { + mDeleteBottomDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + mDeleteBottomDialog.addSelectButton("删除", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mDeleteBottomDialog.dismiss(); + deleteDynamics(mDynamicsItemList.get(position).getId(), position); + } + }); + + mDeleteBottomDialog.show(); + } + }); + + mAdapter.setOnDetailClicked(new DynamicsAdapter1.OnDetailClickListener() { + @Override + public void onDetailClicked(int position, String id) { + detailPosition = position; + Intent intent = new Intent(getContext(), DynamicDetailActivity.class); + intent.putExtra("dynamic_id", id); + intent.putExtra("dynamic_from", 0); + startActivity(intent); + } + }); + + mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + getBanner(); + mPage = 1; + getDynamicList(mType, 1); + } + }); + } + + public void onEventMainThread(DynamicLikeEvent event) { + int isLike = event.isLike(); + int likeNum = event.getLikeNum(); + int from = event.getFrom(); + if (from == 0) { + mAdapter.getmDynamicsItemList().get(detailPosition).setIs_like(isLike); + mAdapter.getmDynamicsItemList().get(detailPosition).setLike_count(likeNum); + mAdapter.notifyDataSetChanged(); + } + } + + void likeFeed(DynamicsItemBean bean) { + BaseActivity activity = (BaseActivity) getActivity(); + boolean isLikeParam = false; + if (bean.getIs_like() == 0) { + isLikeParam = true; + } + DynamicsManager.likeDynamic(activity, bean.getId(), isLikeParam, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + bean.setIs_like(1 - bean.getIs_like()); + if (bean.getIs_like() == 1) { + bean.setLike_count(bean.getLike_count() + 1); + } else { + bean.setLike_count(bean.getLike_count() - 1); + } + mAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "操作失败"); + + } + }); + } + + /** + * 请求网络删除动态 + * + * @param id + */ + private void deleteDynamics(String id, final int index) { + DynamicsManager.deleteDynamics((BaseActivity) getActivity(), id, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + mAdapter.delete(index); + MaleToast.showMessage(getActivity(), "删除成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "删除失败"); + + } + }); + } + + public void getDynamicList(int type, final int page) { + if (getActivity() != null) { + DynamicsManager.getDynamicList((BaseActivity) getActivity(), type, page, 10, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, DynamicsListBean result, String message) { + + if (page == 1) { + mImageList.clear(); + mAdapter.setDeleteCount(0); + } + + mImageList.addAll(result.getList()); + + if (mImageList.size() != 0 && mImageList.size() % 10 != 0) { //显示尾布局 + mListView.onNoDataLoaded(); + } + mAdapter.notifyDataSetChanged(); + if (page == 1) { + mListView.setSelection(0); + } + mPage++; + mRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(getActivity(), tip); + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + }); + } + } + + public void thumbup(String dynamicId) { + DynamicsManager.thumbup((BaseActivity) getActivity(), mType, dynamicId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { +// MaleToast.showMessage(getActivity(), "点赞成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showMessage(getActivity(), "点赞失败,请重试"); + } + }); + } + + public void sendGift(String dynamicId, final int number, final DynamicsItemBean bean) { + DynamicsManager.sendGifts((BaseActivity) getActivity(), dynamicId, number, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(getActivity(), "礼物赠送成功"); + if (null != mAdapter) { + mAdapter.setGiftCount(number + bean.getReward_count(), bean.getId()); + mAdapter.notifyDataSetChanged(); + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "赠送失败,请重试"); + } + }); + } + + private void focus(String userId) { + DynamicsManager.follow((BaseActivity) getActivity(), + userId, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + MaleToast.showMessage(getActivity(), "关注成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "关注失败"); + } + }); + } + + private void getBanner() { + if (getActivity() != null) { + DynamicsManager.getBannerList((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String tips) { + List images = new ArrayList<>(); + if (null != result.getBanner()) { + if (result.getBanner().size() > 0) { + for (int i = 0; i < result.getBanner().size(); i++) { + BannerBean bean = new BannerBean(); + bean.setImage(StrU.getResourcePath(result.getBanner().get(i).getImage(), activity)); + bean.setLink_url(result.getBanner().get(i).getLink_url()); + bean.setLink_type(result.getBanner().get(i).getLink_type()); + images.add(bean); + } + mAdapter.setBannerImages(images, true); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/SameCityDynamicFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/SameCityDynamicFragment.java new file mode 100644 index 0000000..8addd13 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/fragment/SameCityDynamicFragment.java @@ -0,0 +1,404 @@ +package com.fengliyan.tianlesue.view.dynamics.fragment; + + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.dynamics.adapter.DynamicsAdapter1; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.eventBus.DynamicEvent; +import com.fengliyan.tianlesue.controller.eventBus.DynamicLikeEvent; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.model.dynamics.DynamicsListBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.dynamics.activity.DynamicDetailActivity; +import com.fengliyan.tianlesue.view.main.ComplaintActivity; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2018/12/25. + * 同城 + */ + +public class SameCityDynamicFragment extends Fragment { + + private int mType = 0; + private LoadMoreListView mListView; + private List mImageList = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + private DynamicsAdapter1 mAdapter; + private SwipeRefreshLayout mRefresh; + private BottomSelectiveDialog mSelectiveDialog; + private BottomSelectiveDialog mDeleteBottomDialog; + private int detailPosition; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_dynamic_channel, container, false); + EventBus.getDefault().register(this); + initView(v); + if (getUserVisibleHint()) { + getBanner(); + mPage = 1; + getDynamicList(mType, 1, SPUtils.getString(getActivity(), ConsUser.DYNAMIC_CITY_ID)); + } + return v; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); //防止数据预加载, 只预加载View,不预加载数据 + if (isVisibleToUser && isVisible()) { + getBanner(); + mPage = 1; + getDynamicList(mType, 1, SPUtils.getString(getActivity(), ConsUser.DYNAMIC_CITY_ID)); + } + } + + private void initView(View v) { + mListView = v.findViewById(R.id.dynamics_list); + mRefresh = v.findViewById(R.id.dynamics_refresh); + mAdapter = new DynamicsAdapter1(getActivity()); + mAdapter.setList(mImageList); + mListView.setAdapter(mAdapter); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (0 != mImageList.size() && (mImageList.size() + mAdapter.getDeleteCount()) % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mImageList.size() - 2) { + getDynamicList(mType, mPage, SPUtils.getString(getActivity(), ConsUser.DYNAMIC_CITY_ID)); + mPageLoad = true; + } else if (mListView.getLastVisiblePosition() <= mImageList.size() - 2) { + mPageLoad = false; + } + } + }); + + mAdapter.setOnThumbupClickedListener(new DynamicsAdapter1.OnThumbupClickedListener() { + @Override + public void onClick(View v, String uid) { + thumbup(uid); + } + }); + mAdapter.setOnGiftSendListener(new DynamicsAdapter1.OnGiftSendListener() { + @Override + public void onSend(DynamicsItemBean bean, int quantity) { + sendGift(bean.getId(), quantity, bean); + } + }); + + mAdapter.setOnMenuClickListener(new DynamicsAdapter1.OnMenuClickListener() { + @Override + public void onMenuClicked(final int dynamicIndex) { + mSelectiveDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + if (0 == mImageList.get(dynamicIndex).getIs_follow()) { + mSelectiveDialog.addSelectButton("关注", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + focus(mImageList.get(dynamicIndex).getUser_id()); + } + }); + } + + mSelectiveDialog.addSelectButton("举报", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + Intent intent = new Intent(getActivity(), ComplaintActivity.class); + intent.putExtra("uid", mImageList.get(dynamicIndex).getUser_id()); + intent.putExtra("type", 3); + startActivity(intent); + } + }); + + mSelectiveDialog.show(); + } + }); + + mAdapter.likeDynamicCallback = new DynamicsAdapter1.DynamicLikeCallback() { + @Override + public void likeDynamic(DynamicsItemBean bean) { + likeFeed(bean); + } + }; + //删除动态 + mAdapter.setOnMenuDeleteClickListener(new DynamicsAdapter1.OnMenuDeleteClickListener() { + @Override + public void onMenuDelete(final int position, final List mDynamicsItemList) { + mDeleteBottomDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + mDeleteBottomDialog.addSelectButton("删除", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mDeleteBottomDialog.dismiss(); + deleteDynamics(mDynamicsItemList.get(position).getId(), position); + } + }); + + mDeleteBottomDialog.show(); + } + }); + mAdapter.setOnDetailClicked(new DynamicsAdapter1.OnDetailClickListener() { + @Override + public void onDetailClicked(int position, String id) { + detailPosition = position; + Intent intent = new Intent(getContext(), DynamicDetailActivity.class); + intent.putExtra("dynamic_id", id); + intent.putExtra("dynamic_from", 2); + startActivity(intent); + } + }); + + mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + getBanner(); + mPage = 1; + getDynamicList(mType, 1, SPUtils.getString(getActivity(), ConsUser.DYNAMIC_CITY_ID)); + } + }); + } + + public void onEventMainThread(DynamicLikeEvent event) { + int isLike = event.isLike(); + int likeNum = event.getLikeNum(); + int from = event.getFrom(); + if (from == 2) { + mAdapter.getmDynamicsItemList().get(detailPosition).setIs_like(isLike); + mAdapter.getmDynamicsItemList().get(detailPosition).setLike_count(likeNum); + mAdapter.notifyDataSetChanged(); + } + } + + void likeFeed(DynamicsItemBean bean) { + BaseActivity activity = (BaseActivity) getActivity(); + boolean isLikeParam = false; + if (bean.getIs_like() == 0) { + isLikeParam = true; + } + DynamicsManager.likeDynamic(activity, bean.getId(), isLikeParam, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + bean.setIs_like(1 - bean.getIs_like()); + if (bean.getIs_like() == 1) { + bean.setLike_count(bean.getLike_count() + 1); + } else { + bean.setLike_count(bean.getLike_count() - 1); + } + mAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "操作失败"); + + } + }); + } + + /** + * 请求网络删除动态 + * + * @param id + */ + private void deleteDynamics(String id, final int index) { + DynamicsManager.deleteDynamics((BaseActivity) getActivity(), id, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + mAdapter.delete(index); + MaleToast.showMessage(getActivity(), "删除成功"); + EventBus.getDefault().post(new DynamicEvent()); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "删除失败"); + + } + }); + } + + public void getDynamicList(int type, final int page, String cityId) { + DynamicsManager.getDynamicCityList((BaseActivity) getActivity(), type, page, 10, cityId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, DynamicsListBean result, String message) { + if (page == 1) { + mImageList.clear(); + mAdapter.setDeleteCount(0); + } + + mImageList.addAll(result.getList()); + +// if (mImageList.size() != 0 && mImageList.size() % 10 != 0) { //显示尾布局 +// mListView.onNoDataLoaded(); +// } + mAdapter.notifyDataSetChanged(); + if (page == 1) { + mListView.setSelection(0); + } + mPage++; + mRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(getActivity(), tip); + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mListView.onNoDataLoaded(); + mRefresh.setRefreshing(false); + } + }); + } + + public void thumbup(String dynamicId) { + DynamicsManager.thumbup((BaseActivity) getActivity(), mType, dynamicId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { +// MaleToast.showMessage(getActivity(), "点赞成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showMessage(getActivity(), "点赞失败,请重试"); + } + }); + } + + public void sendGift(String dynamicId, final int number, final DynamicsItemBean bean) { + DynamicsManager.sendGifts((BaseActivity) getActivity(), dynamicId, number, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(getActivity(), "礼物赠送成功"); + if (null != mAdapter) { + mAdapter.setGiftCount(number + bean.getReward_count(), bean.getId()); + mAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "赠送失败,请重试"); + } + }); + } + + private void focus(String userId) { + DynamicsManager.follow((BaseActivity) getActivity(), + userId, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + MaleToast.showMessage(getActivity(), "关注成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "关注失败"); + } + }); + } + + public void setCityChoose(String cityId) { + mPage = 1; + getDynamicList(mType, mPage, cityId); + } + + private void getBanner() { + if (getActivity() != null) { + DynamicsManager.getBannerList((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String tips) { + List images = new ArrayList<>(); + if (null != result.getBanner()) { + if (result.getBanner().size() > 0) { + for (int i = 0; i < result.getBanner().size(); i++) { + BannerBean bean = new BannerBean(); + bean.setImage(StrU.getResourcePath(result.getBanner().get(i).getImage(), activity)); + bean.setLink_url(result.getBanner().get(i).getLink_url()); + bean.setLink_type(result.getBanner().get(i).getLink_type()); + images.add(bean); + } + mAdapter.setBannerImages(images, true); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/utils/BitmapUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/utils/BitmapUtils.java new file mode 100644 index 0000000..6631a7f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/utils/BitmapUtils.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.view.dynamics.utils; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import java.io.ByteArrayOutputStream; + +public class BitmapUtils { + public static byte[] compressBitmapToBytes(String filePath, int reqWidth, int reqHeight, int quality, Bitmap.CompressFormat format) { + Bitmap bitmap = getSmallBitmap(filePath, reqWidth, reqHeight); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + bitmap.compress(format, quality, baos); + byte[] bytes = baos.toByteArray(); + bitmap.recycle(); + return bytes; + } + + public static Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(filePath, options); + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + options.inJustDecodeBounds = false; + return BitmapFactory.decodeFile(filePath, options); + } + + public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { + int h = options.outHeight; + int w = options.outWidth; + int inSampleSize = 0; + if (h > reqHeight || w > reqWidth) { + float ratioW = (float) w / reqWidth; + float ratioH = (float) h / reqHeight; + inSampleSize = (int) Math.min(ratioH, ratioW); + } + inSampleSize = Math.max(1, inSampleSize); + return inSampleSize; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/utils/ImageLayout.java b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/utils/ImageLayout.java new file mode 100644 index 0000000..6423c8c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/dynamics/utils/ImageLayout.java @@ -0,0 +1,100 @@ +package com.fengliyan.tianlesue.view.dynamics.utils; + +import android.content.Context; +import androidx.annotation.Nullable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.fengliyan.tianlesue.R; +import com.facebook.drawee.view.SimpleDraweeView; + +/** + * Created by chenqihong on 2017/6/26. + */ + +public class ImageLayout extends LinearLayout implements View.OnClickListener{ + private ImageView mCloseButton; + private View mReadyLogo; + private ImageView mReadyLogoInner; + private SimpleDraweeView mPhoto; + private OnImageHandlingListener mListener; + private String mImageUrl; + + @Override + public void onClick(View v) { + if(v == mCloseButton){ + mListener.onRemoveLogoClicked(); + ready(); + }else if(v == mReadyLogo){ + mListener.onReadyLogoClicked(); + }else if(v == mPhoto){ + mListener.onImageClicked(); + } + } + + public void setOnImageHandlingListener(OnImageHandlingListener listener){ + mListener = listener; + } + + public interface OnImageHandlingListener{ + void onImageClicked(); + void onReadyLogoClicked(); + void onRemoveLogoClicked(); + } + + public ImageLayout(Context context) { + super(context); + LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.item_question_post_image, this); + initView(); + ready(); + } + + public ImageLayout(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.item_question_post_image, this); + initView(); + ready(); + } + + private void initView(){ + mCloseButton = (ImageView)findViewById(R.id.post_image_remove); + mReadyLogo = findViewById(R.id.post_image_ready_logo); + mReadyLogoInner = findViewById(R.id.post_image_ready_logo_inner); + mPhoto = (SimpleDraweeView) findViewById(R.id.post_image_selected); + mCloseButton.setOnClickListener(this); + mReadyLogo.setOnClickListener(this); + mPhoto.setOnClickListener(this); + } + + public void imageLoad(String url){ + mPhoto.setImageURI(url); + mImageUrl = url; + mReadyLogo.setVisibility(View.GONE); + mCloseButton.setVisibility(View.VISIBLE); + mPhoto.setVisibility(View.VISIBLE); + } + + public String getImageUrl(){ + return mImageUrl; + } + + public void ready(){ + mPhoto.setVisibility(View.GONE); + mCloseButton.setVisibility(View.GONE); + mReadyLogo.setVisibility(View.VISIBLE); + mImageUrl = null; + } + + public void empty(){ + mPhoto.setVisibility(View.GONE); + mCloseButton.setVisibility(View.GONE); + mReadyLogo.setVisibility(View.VISIBLE); + mReadyLogoInner.setImageResource(R.drawable.ic_dynamic_photo); + mImageUrl = null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/login/ForgetActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/login/ForgetActivity.java new file mode 100644 index 0000000..6606c29 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/login/ForgetActivity.java @@ -0,0 +1,242 @@ +package com.fengliyan.tianlesue.view.login; + +import android.content.Intent; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.login.manager.ForgetManager; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.CodeUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.editor.CaiEditText; +import com.fengliyan.uikit.toast.MaleToast; + +/** + * Created by abby on 2018/3/21. + */ + +public class ForgetActivity extends BaseActivity implements View.OnClickListener{ + private Button mConfirmButton; + private Button mSendCodeButton; + private CaiEditText mPhoneEditText; + private CaiEditText mPasswordEditText; + private CaiEditText mAuthCodeEditText; + private boolean isPasswordShowed; + + private ImageView captchaImageView; + private String code; + private CaiEditText imageVerifyEditText; + private CountDownTimer mTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + mSendCodeButton.setText((l / 1000) + ""); + } + + @Override + public void onFinish() { + mSendCodeButton.setEnabled(true); + mSendCodeButton.setText("获取验证码"); + + } + }; + + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if(!TextUtils.isEmpty(mPhoneEditText.getText()) + && !TextUtils.isEmpty(mPasswordEditText.getText()) + && !TextUtils.isEmpty(mAuthCodeEditText.getText())){ + mConfirmButton.setEnabled(true); + }else{ + mConfirmButton.setEnabled(false); + } + + if(!TextUtils.isEmpty(mPhoneEditText.getText())){ + mSendCodeButton.setEnabled(true); + }else{ + mSendCodeButton.setEnabled(false); + } + } + }; + + @Override + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_forget); + setTitleName("找回密码"); + setDefaultTitle(); + initPicCode(); + dissmissTitleBottomLine(); + initView(); + } + + private void initView(){ + mConfirmButton = findViewById(R.id.forget_button); + mPhoneEditText = findViewById(R.id.forget_phone_num_layout); + mPasswordEditText = findViewById(R.id.forget_password_layout); + mAuthCodeEditText = findViewById(R.id.forget_verify_edit); + mSendCodeButton = findViewById(R.id.forget_send_code_button); + captchaImageView= findViewById(R.id.image); + imageVerifyEditText= findViewById(R.id.register_image_verify_edit); + + captchaImageView.setOnClickListener(this); + mConfirmButton.setOnClickListener(this); + mSendCodeButton.setOnClickListener(this); + mPhoneEditText.getEditText().addTextChangedListener(mTextWatcher); + mPasswordEditText.getEditText().addTextChangedListener(mTextWatcher); + mAuthCodeEditText.getEditText().addTextChangedListener(mTextWatcher); + mPhoneEditText.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + mPhoneEditText.setText(""); + } + }); + + mPasswordEditText.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + if(isPasswordShowed){ + isPasswordShowed = false; + mPasswordEditText.setRightButtonImageById(R.drawable.ic_sign_input2); + mPasswordEditText + .getEditText() + .setTransformationMethod(PasswordTransformationMethod.getInstance()); + mPasswordEditText + .getEditText() + .setSelection(mPasswordEditText.getEditText().getText().length()); + }else{ + isPasswordShowed = true; + mPasswordEditText.setRightButtonImageById(R.drawable.ic_sign_input3); + mPasswordEditText + .getEditText() + .setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + mPasswordEditText + .getEditText() + .setSelection(mPasswordEditText.getEditText().getText().length()); + } + } + }); + } + + @Override + public void onClick(View view) { + if(view == mConfirmButton){ + forget(mPhoneEditText.getText(), + mPasswordEditText.getText(), + mAuthCodeEditText.getText()); + }else if(view == mSendCodeButton){ + sendCode(mPhoneEditText.getText()); + }else if(view==captchaImageView){ + initPicCode(); + } + } + + @Override + public void onDestroy(){ + super.onDestroy(); + if(null != mTimer){ + mTimer.cancel(); + } + } + + //获取图形验证码 + public void initPicCode(){ + RegisterManager.getPicCode(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + if(ConstUrl.LOGDEBUG) Log.d("ssz",tips); + code=result.toString(); + captchaImageView.setImageBitmap(CodeUtils.getInstance().createBitmap(code)); + } + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + public void forget(final String userName, final String password, String authCode){ + ForgetManager.forget(this, userName, password, authCode, + false, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { + Intent intent = new Intent(); + intent.putExtra("UserName", userName); + intent.putExtra("Password", password); + setResult(RESULT_OK, intent); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + public void sendCode(String number){ + if(StringUtil.isEmpty(mPhoneEditText.getText().toString())){ + MaleToast.showFailureMsg(ForgetActivity.this, "请输入您的手机号码"); + return; + } + if(StringUtil.isEmpty(imageVerifyEditText.getText().toString())){ + MaleToast.showFailureMsg(ForgetActivity.this, "请输入图片验证码"); + return; + } + if(!imageVerifyEditText.getText().toString().toLowerCase().equals(code.toLowerCase())){ + MaleToast.showFailureMsg(ForgetActivity.this, "图片验证码错误"); + return; + } + RegisterManager.sendAuthCode(this, number, code,"forget", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + mTimer.start(); + mSendCodeButton.setEnabled(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginActivity.java new file mode 100644 index 0000000..229bc94 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginActivity.java @@ -0,0 +1,1023 @@ +package com.fengliyan.tianlesue.view.login; + +import android.Manifest; +import android.content.Intent; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.blankj.utilcode.util.ActivityUtils; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.utils.ToastUtil; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.eventBus.RegisterInfoEvent; +import com.fengliyan.tianlesue.controller.login.manager.LoginManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.model.login.bean.CustomerTipBean; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.main.SystemVersionBean; +import com.fengliyan.tianlesue.utils.DemoHelper; +import com.fengliyan.tianlesue.utils.InviteCodeUpdateUtils; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.AppStatusCallbacks; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.config.BaseUIConfig; +import com.fengliyan.tianlesue.view.config.CustomXmlConfig; +import com.fengliyan.tianlesue.view.config.OnOneKeyCustomClickListener; +import com.fengliyan.tianlesue.view.login.utils.LoginUtils; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.main.dialog.UpdateDialog; +import com.fengliyan.tianlesue.view.register.RegisterActivity; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.dialog.PrivateDialogs; +import com.fengliyan.uikit.editor.CaiEditText; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; +import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper; +import com.mobile.auth.gatewayauth.ResultCode; +import com.mobile.auth.gatewayauth.TokenResultListener; +import com.mobile.auth.gatewayauth.model.TokenRet; +import com.netease.htprotect.HTProtect; +import com.netease.htprotect.callback.GetTokenCallback; +import com.netease.htprotect.result.AntiCheatResult; +import com.snail.antifake.deviceid.emulator.EmuCheckUtil; +import com.snail.antifake.jni.EmulatorDetectUtil; +import com.xinlingwu.share.ShareManager; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.greenrobot.event.EventBus; + +/** + * Created by abby on 2018/3/20. + */ + +public class LoginActivity extends BaseActivity implements View.OnClickListener, DemoHelper.AppIdsUpdater { + public static int REQUEST_FORGET = 200; + public static int REQUEST_REGISTER = 201; + public static int REQUEST_INFO = 202; + private TextView tv_login_sms; + private TextView tv_login_pw; + private LinearLayout lin_sms_login; + private CaiEditText login_sms_phone_number_layout; + private CaiEditText login_vcode; + private TextView tv_send_code; + private LinearLayout lin_password_login; + private CaiEditText mPhoneNumberEdit; + private CaiEditText mPasswordEdit; + private TextView mRegisterView; + private TextView mForgetView; + private TextView mContractTitle; + private ImageView mQqImageView; + private ImageView mWeixinImageView; + private ImageView mWeiboImageView; + private Button mLoginButton; + private LinearLayout lin_login_help; + private boolean isPasswordShowed; + private long mExitTime; + private MaleToast mToast; + private String mUid; + private String mAccessToken; + private String mPlatform; + private CheckBox isSelectBox; + private Boolean isSelect = false; + private BaseMessageDialog mMessageDialog; + private int loginType = 1;//0.验证码登录 1.密码登录 + + private PhoneNumberAuthHelper mPhoneNumberAuthHelper; + private TokenResultListener mTokenResultListener; + private BaseUIConfig mUIConfig; + private OnOneKeyCustomClickListener onOneKeyCustomClickListener; + + + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + initLoginBtnEnabled(); + } + }; + + private void initLoginBtnEnabled() { + if (loginType == 0) { + mLoginButton.setEnabled(!TextUtils.isEmpty(login_sms_phone_number_layout.getText()) && !TextUtils.isEmpty(login_vcode.getText())); + } else { + mLoginButton.setEnabled(!TextUtils.isEmpty(mPasswordEdit.getText()) && !TextUtils.isEmpty(mPhoneNumberEdit.getText())); + } + } + + private TextView mMAbout_contract_2; + private DemoHelper demoHelper; + + @Override + public void onCreate(Bundle savedInstanceState) { + AppStatusCallbacks.get().setmAppStatus(AppStatusCallbacks.STATUS_NORMAL); + super.onCreate(savedInstanceState); +// BaseApplication.getInstance().userstatisticsSocketClose(); + setContentView(R.layout.activity_login); + dissmissTitleBottomLine(); + Title title = getCustomTitle(); +// title.hideLeft(); + title.hideRight(); + hideTitleBar(); +// OpenInstall.getInstall(new AppInstallAdapter() { +// @Override +// public void onInstall(AppData appData) { +// //获取渠道数据 +// String channelCode = appData.getChannel(); +// //获取自定义数据 +// String bindData = appData.getData(); +// Gson gson = new Gson(); +// InviteCodeBean inviteCodeBean = gson.fromJson(bindData, InviteCodeBean.class); +// if (inviteCodeBean != null) { +// // BaseApplication.getInstance().setInvite_code(inviteCodeBean.getInvite_code()); +// UserManager.setInviteCode(inviteCodeBean.getInvite_code()); +// } +// + initView(); +// } +// }); + try { + demoHelper = new DemoHelper(this); + demoHelper.getDeviceIds(LoginActivity.this.getApplicationContext()); + } catch (Exception e) { + + } + // initView(); + EventBus.getDefault().register(this); + +// AndroidDeviceIMEIUtil.isRunOnEmulator(this); + EmulatorDetectUtil.isEmulatorFromAll(this); + EmuCheckUtil.checkEmulatorFromCache(getApplicationContext(), + new EmuCheckUtil.CheckEmulatorCallBack() { + @Override + public void onCheckSuccess(boolean isEmulator) { + if (isEmulator) { + ToastUtil.showToast(LoginActivity.this, "检测到模拟器登录,已退出"); + finish(); + } + } + + @Override + public void onCheckFaild() { + Log.i("TAG", "onCheckFaild: --------->"); + } + }); + checkUpdate(); + oneKeyLoginInit(); + } + + private void initView() { + tv_login_sms = findViewById(R.id.tv_login_sms); + tv_login_pw = findViewById(R.id.tv_login_pw); + lin_sms_login = findViewById(R.id.lin_sms_login); + login_sms_phone_number_layout = findViewById(R.id.login_sms_phone_number_layout); + login_vcode = findViewById(R.id.login_vcode); + tv_send_code = findViewById(R.id.tv_send_code); + lin_password_login = findViewById(R.id.lin_password_login); + mRegisterView = findViewById(R.id.login_register_view); + mForgetView = findViewById(R.id.login_forget_view); + mPhoneNumberEdit = findViewById(R.id.login_phone_number_layout); + mPasswordEdit = findViewById(R.id.login_password_layout); + mLoginButton = findViewById(R.id.login_button); + mWeixinImageView = findViewById(R.id.login_weixin); + mQqImageView = findViewById(R.id.login_qq); + mWeiboImageView = findViewById(R.id.login_weibo); + mContractTitle = findViewById(R.id.login_contract_titile); + mMAbout_contract_2 = findViewById(R.id.about_contract_2); + isSelectBox = findViewById(R.id.activity_login_select_box); + lin_login_help = findViewById(R.id.lin_login_help); + findViewById(R.id.backBtn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + tv_login_sms.setOnClickListener(this); + tv_login_pw.setOnClickListener(this); + isSelectBox.setOnClickListener(this); + mRegisterView.setOnClickListener(this); + mForgetView.setOnClickListener(this); + mLoginButton.setOnClickListener(this); + mWeixinImageView.setOnClickListener(this); + mQqImageView.setOnClickListener(this); + mWeiboImageView.setOnClickListener(this); + mContractTitle.setOnClickListener(this); + mMAbout_contract_2.setOnClickListener(this); + tv_send_code.setOnClickListener(this); + lin_login_help.setOnClickListener(this); + login_sms_phone_number_layout.getEditText().addTextChangedListener(mTextWatcher); + login_vcode.getEditText().addTextChangedListener(mTextWatcher); + mPhoneNumberEdit.getEditText().addTextChangedListener(mTextWatcher); + mPasswordEdit.getEditText().addTextChangedListener(mTextWatcher); + mPhoneNumberEdit.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + mPhoneNumberEdit.setText(""); + } + }); + login_sms_phone_number_layout.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + login_sms_phone_number_layout.setText(""); + } + }); + login_sms_phone_number_layout.setText(NoClearSPUtils.getString(this, Constans.USER_MOBILE)); + mPhoneNumberEdit.setText(NoClearSPUtils.getString(this, Constans.USER_MOBILE)); + mPasswordEdit.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + if (isPasswordShowed) { + isPasswordShowed = false; + mPasswordEdit.setRightButtonImageById(R.drawable.ic_sign_input2); + mPasswordEdit + .getEditText() + .setTransformationMethod(PasswordTransformationMethod.getInstance()); + mPasswordEdit + .getEditText() + .setSelection(mPasswordEdit.getEditText().getText().length()); + } else { + isPasswordShowed = true; + mPasswordEdit.setRightButtonImageById(R.drawable.ic_sign_input3); + mPasswordEdit + .getEditText() + .setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + mPasswordEdit + .getEditText() + .setSelection(mPasswordEdit.getEditText().getText().length()); + } + } + }); + } + + @Override + public void onClick(View view) { + if (view == tv_send_code) { + if (StrU.isFastClick()) { + if (StringUtil.isEmpty(login_sms_phone_number_layout.getText())) { + MaleToast.showFailureMsg(this, "请输入您的手机号码"); + return; + } + sendCode(login_sms_phone_number_layout.getText()); + } + } else if (view == tv_login_sms) { + loginType = 0; + tv_login_pw.setBackgroundResource(0); + tv_login_pw.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + tv_login_sms.setBackgroundResource(R.drawable.white_bg_40); + tv_login_sms.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + lin_sms_login.setVisibility(View.VISIBLE); + lin_password_login.setVisibility(View.GONE); + initLoginBtnEnabled(); + } else if (view == tv_login_pw) { + loginType = 1; + tv_login_sms.setBackgroundResource(0); + tv_login_sms.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + tv_login_pw.setBackgroundResource(R.drawable.white_bg_40); + tv_login_pw.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + lin_sms_login.setVisibility(View.GONE); + lin_password_login.setVisibility(View.VISIBLE); + initLoginBtnEnabled(); + } else if (view == mRegisterView) { + if (StrU.isFastClick()) { + Intent intent = new Intent(LoginActivity.this, RegisterActivity.class); + startActivity(intent); + } + } else if (view == mForgetView) { + if (StrU.isFastClick()) { + Intent intent = new Intent(LoginActivity.this, ForgetActivity.class); + startActivityForResult(intent, REQUEST_FORGET); + } + } else if (view == isSelectBox) { + if (isSelect) { + isSelectBox.setChecked(false); + isSelect = false; + } else { + isSelectBox.setChecked(true); + isSelect = true; + } + } else if (view == mLoginButton) { + if (StrU.isFastClick()) { + if (isSelect) { + if (loginType == 0) { + String userName = login_sms_phone_number_layout.getText(); + String password = login_vcode.getText(); + InviteCodeUpdateUtils.getOpeninstallData(this, new InviteCodeUpdateUtils.CodeCallback() { + @Override + public void callback(String code) { + onSMSLogin(userName, password, code); + } + }); + } else { + String userName = mPhoneNumberEdit.getText(); + String password = mPasswordEdit.getText(); + login(userName, password); + } + } else { + PrivateDialogs.getInstace().message("").sure("同意").cancle("取消") + .setOnTipItemClickListener(new PrivateDialogs.OnTipItemClickListener() { + @Override + public void cancleClick() { +// finishActivity(); + } + + @Override + public void sureClick() { + isSelectBox.setChecked(true); + isSelect = true; + if (loginType == 0) { + String userName = login_sms_phone_number_layout.getText(); + String password = login_vcode.getText(); + InviteCodeUpdateUtils.getOpeninstallData(LoginActivity.this, new InviteCodeUpdateUtils.CodeCallback() { + @Override + public void callback(String code) { + onSMSLogin(userName, password, code); + } + }); + } else { + String userName = mPhoneNumberEdit.getText(); + String password = mPasswordEdit.getText(); + login(userName, password); + } + } + + @Override + public void userClick() { + Intent intent = new Intent(LoginActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } + + @Override + public void termsClick() { + Intent intent = new Intent(LoginActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } + }).create(this); + + } + } + } else if (view == mQqImageView) { + if (StrU.isFastClick()) { + if (isSelect) { + onQqLogin(); + } else { + onSelect(2); + } + } + } else if (view == mWeixinImageView) { + if (StrU.isFastClick()) { + if (isSelect) { + onWeixinLogin(); + } else { + onSelect(1); + } + } + } else if (view == mWeiboImageView) { + if (StrU.isFastClick()) { + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map map) { + thirdLogin(map, "weibo"); + + } + + @Override + public void error() { + + } + + @Override + public void cancel() { + + } + }, this, ShareManager.TYPE_WEIBO); + } + } else if (view == mContractTitle) { + if (StrU.isFastClick()) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } + } else if (view == mMAbout_contract_2) { + if (StrU.isFastClick()) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } + } else if (view == lin_login_help) { + getCustomerTip(); + } + } + + public void login(final String userName, String password) { + mUid = null; + mAccessToken = null; + mPlatform = null; + HTProtect.getTokenAsync(3000, "11dfa1f43cd4f2f77dddad305690ada3", new GetTokenCallback() { + @Override + public void onResult(AntiCheatResult antiCheatResult) { + NoClearSPUtils.saveString(LoginActivity.this, "x-risk-engine-token", antiCheatResult.token); + LoginManager.login(LoginActivity.this, userName, password, false, antiCheatResult.token, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + LoginUtils.checkLoginStatus(LoginActivity.this, result, 0); + NoClearSPUtils.saveString(activity, Constans.USER_MOBILE, userName); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showFailureMsg(activity, "请重试"); + } + }); + } + }); + } + + private void onSMSLogin(String userName, String code, String invite_code) { + HTProtect.getTokenAsync(3000, "11dfa1f43cd4f2f77dddad305690ada3", new GetTokenCallback() { + @Override + public void onResult(AntiCheatResult antiCheatResult) { + NoClearSPUtils.saveString(LoginActivity.this, "x-risk-engine-token", antiCheatResult.token); + LoginManager.onSMSLogin(LoginActivity.this, userName, code, invite_code, antiCheatResult.token, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String tips) { + LoginUtils.checkLoginStatus(LoginActivity.this, result, 0); + NoClearSPUtils.saveString(activity, Constans.USER_MOBILE, userName); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showFailureMsg(activity, "登录失败"); + e.printStackTrace(); + } + }); + } + }); + } + + public void thirdLogin(Map params, String platform) { + String uid = (null == params.get("uid")) ? params.get("unionid") : params.get("uid"); + String accessToken = params.get("accessToken"); + mUid = uid; + mAccessToken = accessToken; + mPlatform = platform; + mPhoneNumberEdit.setText(""); + mPasswordEdit.setText(""); + HTProtect.getTokenAsync(3000, "11dfa1f43cd4f2f77dddad305690ada3", new GetTokenCallback() { + @Override + public void onResult(AntiCheatResult antiCheatResult) { + NoClearSPUtils.saveString(LoginActivity.this, "x-risk-engine-token", antiCheatResult.token); + InviteCodeUpdateUtils.getOpeninstallData(LoginActivity.this, new InviteCodeUpdateUtils.CodeCallback() { + @Override + public void callback(String code) { + LoginManager.thirdLogin(LoginActivity.this, platform, uid, accessToken, code, antiCheatResult.token, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + LoginUtils.checkLoginStatus(LoginActivity.this, result, 0); + if (null != result.getUserinfo().getInvite_code()) { + UserManager.setInviteResult(true); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(LoginActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showFailureMsg(LoginActivity.this, "登录失败login" + e.getMessage()); + } + }); + } + }); + } + }); + } + + public void goToMain() { + finish(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + if ((REQUEST_REGISTER == requestCode + || REQUEST_FORGET == requestCode + || REQUEST_INFO == requestCode) + && RESULT_OK == resultCode) { + if (null != intent) { + String userName = intent.getStringExtra("UserName"); + String password = intent.getStringExtra("Password"); + if (null != userName && null != password) { + mPhoneNumberEdit.setText(userName); + mPasswordEdit.setText(password); + } + } + + String name = mPhoneNumberEdit.getText(); + String password = mPasswordEdit.getText(); + String uid = mUid; + String accessToken = mAccessToken; + String platform = mPlatform; + + if (null != name && null != password + && !"".equals(name) && !"".equals(password)) { + login(name, password); + } else if (null != uid && null != accessToken && null != platform) { + Map params = new HashMap<>(); + params.put("uid", uid); + params.put("accessToken", accessToken); + thirdLogin(params, platform); + } + } else { + ShareManager.getInstance().onActivityResult(this, requestCode, resultCode, intent); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + ExitApp(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + private void ExitApp() { + if ((System.currentTimeMillis() - mExitTime) > 2000) { + MaleToast.showMessage(this, "再按一次退出"); + mExitTime = System.currentTimeMillis(); + } else { + setResult(RESULT_OK); + ActivityUtils.finishAllActivities(); + } + + } + + //完善资料后,关闭登录界面 + public void onEventMainThread(RegisterInfoEvent event) { +// LoginBean loginBean = event.getBean(); +// LoginUtils.checkLoginStatus(LoginActivity.this, loginBean, 1); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mPhoneNumberAuthHelper.setAuthListener(null); + mPhoneNumberAuthHelper.quitLoginPage(); + EventBus.getDefault().unregister(this); + } + + private void onQqLogin() { + if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_QQ)) { + MaleToast.showMessage(this, "请先安装QQ"); + return; + } + + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map map) { + thirdLogin(map, "qq"); + } + + @Override + public void error() { + } + + @Override + public void cancel() { + } + }, this, ShareManager.TYPE_QQ); + isSelectBox.setChecked(true); + isSelect = true; + } + + private void onWeixinLogin() { + if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_WEIXIN)) { + MaleToast.showMessage(this, "请先安装微信"); + return; + } + + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map map) { + thirdLogin(map, "wechat"); + } + + @Override + public void error() { + + } + + @Override + public void cancel() { + + } + }, this, ShareManager.TYPE_WEIXIN); + } + + private void onSelect(int index) { + PrivateDialogs.getInstace().message("").sure("同意").cancle("取消") + .setOnTipItemClickListener(new PrivateDialogs.OnTipItemClickListener() { + @Override + public void cancleClick() { + + } + + @Override + public void sureClick() { + isSelectBox.setChecked(true); + isSelect = true; + if (index == 1) { + onWeixinLogin(); + } else if (index == 2) { + onQqLogin(); + } + } + + @Override + public void userClick() { + Intent intent = new Intent(LoginActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } + + @Override + public void termsClick() { + Intent intent = new Intent(LoginActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } + }).create(this); + } + + @Override + public void onIdsValid(String ids) { + try { + runOnUiThread(() -> { + SPUtils.saveString(LoginActivity.this, "OAID", ids); + }); + } catch (Exception e) { + } + } + + private CountDownTimer mTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + tv_send_code.setText((l / 1000) + ""); + } + + //test + @Override + public void onFinish() { + tv_send_code.setEnabled(true); +// isCodeSend = false; + tv_send_code.setText("获取验证码"); + } + }; + + //手机验证码登录 + public void sendCode(String number) { + RegisterManager.sendAuthCode(this, number, "", "login", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + mTimer.start(); + tv_send_code.setEnabled(false); +// isCodeSend = true; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + public void getCustomerTip() { + LoginManager.getCustomerTip(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, CustomerTipBean result, String message) { + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private UpdateDialog mUpdateDialog; + private String mDownloadUrl; + public static final String DOWNLOAD_PATH = ConstUrl.DEFAULT_PATH + "/cache/"; + + private void checkUpdate() { + MainManager.checkUpdate(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final SystemVersionBean result, String message) { + mUpdateDialog = new UpdateDialog(LoginActivity.this, R.style.SelectiveDialog); + mUpdateDialog.setConfirmListener(new UpdateDialog.DownloadConfirmListener() { + @Override + public void onConfirm() { + PermissionDialog permissionDialog = new PermissionDialog(LoginActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}); + permissionDialog.show(); + XXPermissions.with(activity).permission(Manifest.permission.WRITE_EXTERNAL_STORAGE).request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + permissionDialog.dismiss(); + if (all) { + File file = new File(DOWNLOAD_PATH); + if (file.isFile()) { + file.delete(); + } + + if (!file.exists()) { + file.mkdirs(); + } + + MainManager.downloadNewApp(LoginActivity.this, mDownloadUrl, + DOWNLOAD_PATH + "temp.apk", + new HttpCallback() { + @Override + public void onFailure(int httpStatusCode, String message, Throwable throwable) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } + } + + @Override + public void onSuccess(int httpStatusCode, String responseObject) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + if (result.getEnforce() != 1) { + mUpdateDialog.dismiss(); + } + } + LoginUtils.install(DOWNLOAD_PATH + "temp.apk", LoginActivity.this); + } + + @Override + public void onProgress(long bytesCount, long contentLength, boolean done) { + mUpdateDialog.setProgress((int) (((double) bytesCount) / contentLength * 100)); + } + }); + + } else { + if (result.getEnforce() == 1) { + finish(); + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + OnPermissionCallback.super.onDenied(permissions, never); + permissionDialog.dismiss(); + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } + } + }); + } + + @Override + public void onCancel() { + + } + }); + mUpdateDialog.setCancelable(false); + mDownloadUrl = result.getDownloadurl(); + mUpdateDialog.setInfo(result.getUpgradetext()); + mUpdateDialog.setVersionName(result.getNewversion()); + if (result.getVersioncode() > LoginUtils.getVersionCode(LoginActivity.this)) { + if (result.getEnforce() == 1) { + StorageManager.getInstance(LoginActivity.this) + .putBean("UpdateHintDate", null); + mUpdateDialog.setFinishHide(); + mUpdateDialog.show(); + } else { + final Long currentTime = System.currentTimeMillis(); + final Long lastTime = (Long) StorageManager.getInstance(LoginActivity.this).getBean("UpdateHintDate", Long.class); + if (null == lastTime || currentTime - lastTime > 7 * 24 * 60 * 60 * 1000) { + mUpdateDialog.show(); + StorageManager.getInstance(LoginActivity.this) + .putBean("UpdateHintDate", currentTime); + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + public void oneKeyLoginInit() { + sdkInit(BuildConfig.AUTH_SECRET); + onOneKeyCustomClickListener = new OnOneKeyCustomClickListener() { + @Override + public void onChangeLoginType() { + mPhoneNumberAuthHelper.setAuthListener(null); + mPhoneNumberAuthHelper.quitLoginPage(); + } + + @Override + public void onThirdLogin(int type) { + if (type == 1) { + onWeixinLogin(); + } else { + onQqLogin(); + } + } + + @Override + public void onCustomerTip() { + getCustomerTip(); + } + }; + mUIConfig = new CustomXmlConfig(LoginActivity.this, mPhoneNumberAuthHelper, onOneKeyCustomClickListener); + mPhoneNumberAuthHelper = PhoneNumberAuthHelper.getInstance(getApplicationContext(), mTokenResultListener); + mPhoneNumberAuthHelper.setAuthPageUseDayLight(false); + mPhoneNumberAuthHelper.checkEnvAvailable(); + mUIConfig.configAuthPage(); + mPhoneNumberAuthHelper.closeAuthPageReturnBack(true); + mPhoneNumberAuthHelper.getLoginToken(LoginActivity.this, 5000); + } + + public void sdkInit(String secretInfo) { + mTokenResultListener = new TokenResultListener() { + @Override + public void onTokenSuccess(String s) { + try { + TokenRet tokenRet = null; + tokenRet = TokenRet.fromJson(s); + if (ConstUrl.LOGDEBUG) Log.i("TAG", "onTokenSuccess: tokenRet------>" + s); + if (ResultCode.CODE_START_AUTHPAGE_SUCCESS.equals(tokenRet.getCode())) { + if (ConstUrl.LOGDEBUG) Log.i("TAG", "唤起授权页成功:" + s); + } + final String token = tokenRet.getToken(); + if (ResultCode.CODE_SUCCESS.equals(tokenRet.getCode())) { + if (ConstUrl.LOGDEBUG) Log.i("TAG", "获取token成功:" + s); + InviteCodeUpdateUtils.getOpeninstallData(LoginActivity.this, new InviteCodeUpdateUtils.CodeCallback() { + @Override + public void callback(String code) { + oneKeyLogin(token, code); + } + }); + mPhoneNumberAuthHelper.setAuthListener(null); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onTokenFailed(String s) { + //dismissProgressBar(); + TokenRet tokenRet = null; + Log.i("TAG", "唤起授权页失败"); + try { + tokenRet = TokenRet.fromJson(s); + if (ResultCode.CODE_ERROR_USER_CANCEL.equals(tokenRet.getCode())) { + //模拟的是必须登录 否则直接退出app的场景 + Log.i("TAG", "用户取消快捷"); + finish(); + } else { + mPhoneNumberAuthHelper.setAuthListener(null); + mPhoneNumberAuthHelper.quitLoginPage(); + } + } catch (Exception e) { + e.printStackTrace(); + } + // rl_login_root.setVisibility(View.VISIBLE); + mPhoneNumberAuthHelper.setAuthListener(null); + mPhoneNumberAuthHelper.quitLoginPage(); + } + }; + mPhoneNumberAuthHelper = PhoneNumberAuthHelper.getInstance(BaseApplication.getInstance().getApplicationContext(), mTokenResultListener); + mPhoneNumberAuthHelper.getReporter().setLoggerEnable(true); +// mPhoneNumberAuthHelper.setUIClickListener(new AuthUIControlClickListener() { +// @Override +// public void onClick(String s, Context context, String s1) { +// if (s.equals("700003")) { +// //隐私政策勾选回调 +// JSONObject jsonObject = null; +// try { +// jsonObject = new JSONObject(s1); +// isOneKeyIsPricyChecked = jsonObject.getBoolean("isChecked"); +// Log.i("一键登录页", "isChecked:" + isOneKeyIsPricyChecked); +// } catch (JSONException e) { +// e.printStackTrace(); +// } +// +// } +// Log.i("一键登录页", "s:" + s + ";s1" + s1); +// } +// }); + mPhoneNumberAuthHelper.setAuthSDKInfo(secretInfo); + } + + private void oneKeyLogin(String token, String invite_code) { + HTProtect.getTokenAsync(3000, "11dfa1f43cd4f2f77dddad305690ada3", new GetTokenCallback() { + @Override + public void onResult(AntiCheatResult antiCheatResult) { + com.fengliyan.base.base.utils.NoClearSPUtils.saveString(LoginActivity.this, "x-risk-engine-token", antiCheatResult.token); + MainManager.oneKeyLogin(LoginActivity.this, token, invite_code, antiCheatResult.token, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String tips) { + mPhoneNumberAuthHelper.removeAuthRegisterViewConfig(); + mPhoneNumberAuthHelper.removeAuthRegisterXmlConfig(); + mPhoneNumberAuthHelper.setAuthListener(null); + mPhoneNumberAuthHelper.quitLoginPage(); + LoginUtils.checkLoginStatus(LoginActivity.this, result, 2); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showFailureMsg(activity, tip); + mPhoneNumberAuthHelper.setAuthListener(null); + mPhoneNumberAuthHelper.quitLoginPage(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showFailureMsg(activity, "登录失败"); +// e.printStackTrace(); + mPhoneNumberAuthHelper.setAuthListener(null); + mPhoneNumberAuthHelper.quitLoginPage(); + } + }); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginForOtherActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginForOtherActivity.java new file mode 100644 index 0000000..0ba14ca --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginForOtherActivity.java @@ -0,0 +1,394 @@ +package com.fengliyan.tianlesue.view.login; + +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.widget.CheckBox; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.utils.ToastUtil; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.eventBus.RegisterInfoEvent; +import com.fengliyan.tianlesue.controller.login.manager.LoginManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.login.bean.CustomerTipBean; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.DemoHelper; +import com.fengliyan.tianlesue.utils.InviteCodeUpdateUtils; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.login.utils.LoginUtils; +import com.fengliyan.uikit.dialog.PrivateDialogs; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.htprotect.HTProtect; +import com.netease.htprotect.callback.GetTokenCallback; +import com.netease.htprotect.result.AntiCheatResult; +import com.snail.antifake.deviceid.emulator.EmuCheckUtil; +import com.snail.antifake.jni.EmulatorDetectUtil; +import com.xinlingwu.share.ShareManager; + +import java.util.HashMap; +import java.util.Map; + +import de.greenrobot.event.EventBus; + +/** + * Created by abby on 2018/3/20. + */ + +public class LoginForOtherActivity extends BaseActivity implements View.OnClickListener, DemoHelper.AppIdsUpdater { + public static int REQUEST_FORGET = 200; + public static int REQUEST_REGISTER = 201; + public static int REQUEST_INFO = 202; + + private long mExitTime; + private String mUid; + private String mAccessToken; + private String mPlatform; + private Boolean isSelect = false; + + private LinearLayout lin_login_wechat; + private LinearLayout lin_login_qq; + private TextView tv_login_mobile; + private CheckBox isSelectBox; + private TextView mContractTitle; + private TextView mMAbout_contract_2; + private LinearLayout lin_login_help; + private DemoHelper demoHelper; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// BaseApplication.getInstance().userstatisticsSocketClose(); + setContentView(R.layout.activity_login_for_other); + dissmissTitleBottomLine(); + Title title = getCustomTitle(); +// title.hideLeft(); + title.hideRight(); + hideTitleBar(); +// OpenInstall.getInstall(new AppInstallAdapter() { +// @Override +// public void onInstall(AppData appData) { +// //获取渠道数据 +// String channelCode = appData.getChannel(); +// //获取自定义数据 +// String bindData = appData.getData(); +// Gson gson = new Gson(); +// InviteCodeBean inviteCodeBean = gson.fromJson(bindData, InviteCodeBean.class); +// if (inviteCodeBean != null) { +// // BaseApplication.getInstance().setInvite_code(inviteCodeBean.getInvite_code()); +// UserManager.setInviteCode(inviteCodeBean.getInvite_code()); +// } +// + initView(); +// } +// }); + try { + demoHelper = new DemoHelper(this); + demoHelper.getDeviceIds(LoginForOtherActivity.this.getApplicationContext()); + } catch (Exception e) { + + } + // initView(); + EventBus.getDefault().register(this); + +// AndroidDeviceIMEIUtil.isRunOnEmulator(this); + EmulatorDetectUtil.isEmulatorFromAll(this); + EmuCheckUtil.checkEmulatorFromCache(getApplicationContext(), + new EmuCheckUtil.CheckEmulatorCallBack() { + @Override + public void onCheckSuccess(boolean isEmulator) { + if (isEmulator) { + ToastUtil.showToast(LoginForOtherActivity.this, "检测到模拟器登录,已退出"); + finish(); + } + } + + @Override + public void onCheckFaild() { + Log.i("TAG", "onCheckFaild: --------->"); + } + }); + } + + private void initView() { + lin_login_wechat = findViewById(R.id.lin_login_wechat); + lin_login_qq = findViewById(R.id.lin_login_qq); + tv_login_mobile = findViewById(R.id.tv_login_mobile); + mContractTitle = findViewById(R.id.login_contract_titile); + mMAbout_contract_2 = findViewById(R.id.about_contract_2); + isSelectBox = findViewById(R.id.activity_login_select_box); + lin_login_help = findViewById(R.id.lin_login_help); + lin_login_wechat.setOnClickListener(this); + lin_login_qq.setOnClickListener(this); + tv_login_mobile.setOnClickListener(this); + isSelectBox.setOnClickListener(this); + mContractTitle.setOnClickListener(this); + mMAbout_contract_2.setOnClickListener(this); + lin_login_help.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (view == tv_login_mobile) { + if (StrU.isFastClick()) { + Intent intent = new Intent(LoginForOtherActivity.this, LoginActivity.class); + startActivity(intent); + } + } else if (view == isSelectBox) { + if (isSelect) { + isSelectBox.setChecked(false); + isSelect = false; + } else { + isSelectBox.setChecked(true); + isSelect = true; + } + } else if (view == lin_login_qq) { + if (StrU.isFastClick()) { + if (isSelect) { + onQqLogin(); + } else { + onSelect(2); + } + } + } else if (view == lin_login_wechat) { + if (StrU.isFastClick()) { + if (isSelect) { + onWeixinLogin(); + } else { + onSelect(1); + } + } + } else if (view == mContractTitle) { + if (StrU.isFastClick()) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } + } else if (view == mMAbout_contract_2) { + if (StrU.isFastClick()) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } + } else if (view == lin_login_help) { + getCustomerTip(); + } + } + + public void thirdLogin(Map params, String platform) { + String uid = (null == params.get("uid")) ? params.get("unionid") : params.get("uid"); + String accessToken = params.get("accessToken"); + mUid = uid; + mAccessToken = accessToken; + mPlatform = platform; + HTProtect.getTokenAsync(3000, "11dfa1f43cd4f2f77dddad305690ada3", new GetTokenCallback() { + @Override + public void onResult(AntiCheatResult antiCheatResult) { + NoClearSPUtils.saveString(LoginForOtherActivity.this, "x-risk-engine-token", antiCheatResult.token); + InviteCodeUpdateUtils.getOpeninstallData(LoginForOtherActivity.this, new InviteCodeUpdateUtils.CodeCallback() { + @Override + public void callback(String code) { + LoginManager.thirdLogin(LoginForOtherActivity.this, platform, uid, accessToken, + code, antiCheatResult.token, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + LoginUtils.checkLoginStatus(LoginForOtherActivity.this, result, 0); + if (null != result.getUserinfo().getInvite_code()) { + UserManager.setInviteResult(true); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(LoginForOtherActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showFailureMsg(LoginForOtherActivity.this, "登录失败login" + e.getMessage()); + } + }); + } + }); + } + }); + } + + public void goToMain() { + finish(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + if ((REQUEST_REGISTER == requestCode + || REQUEST_FORGET == requestCode + || REQUEST_INFO == requestCode) + && RESULT_OK == resultCode) { + + String uid = mUid; + String accessToken = mAccessToken; + String platform = mPlatform; + if (null != uid && null != accessToken && null != platform) { + Map params = new HashMap<>(); + params.put("uid", uid); + params.put("accessToken", accessToken); + thirdLogin(params, platform); + } + } else { + ShareManager.getInstance().onActivityResult(this, requestCode, resultCode, intent); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + ExitApp(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + private void ExitApp() { + if ((System.currentTimeMillis() - mExitTime) > 2000) { + MaleToast.showMessage(this, "再按一次退出"); + mExitTime = System.currentTimeMillis(); + } else { + setResult(RESULT_OK); + finish(); + } + } + + //完善资料后,关闭登录界面 + public void onEventMainThread(RegisterInfoEvent event) { +// LoginBean loginBean = event.getBean(); +// LoginUtils.checkLoginStatus(LoginActivity.this, loginBean, 1); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private void onQqLogin() { + if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_QQ)) { + MaleToast.showMessage(this, "请先安装QQ"); + return; + } + + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map map) { + thirdLogin(map, "qq"); + } + + @Override + public void error() { + } + + @Override + public void cancel() { + } + }, this, ShareManager.TYPE_QQ); + isSelectBox.setChecked(true); + isSelect = true; + } + + private void onWeixinLogin() { + if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_WEIXIN)) { + MaleToast.showMessage(this, "请先安装微信"); + return; + } + + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map map) { + thirdLogin(map, "wechat"); + } + + @Override + public void error() { + + } + + @Override + public void cancel() { + + } + }, this, ShareManager.TYPE_WEIXIN); + } + + public void getCustomerTip() { + LoginManager.getCustomerTip(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, CustomerTipBean result, String message) { + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private void onSelect(int index) { + PrivateDialogs.getInstace().message("").sure("同意").cancle("取消") + .setOnTipItemClickListener(new PrivateDialogs.OnTipItemClickListener() { + @Override + public void cancleClick() { + + } + + @Override + public void sureClick() { + isSelectBox.setChecked(true); + isSelect = true; + if (index == 1) { + onWeixinLogin(); + } else if (index == 2) { + onQqLogin(); + } + } + + @Override + public void userClick() { + Intent intent = new Intent(LoginForOtherActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } + + @Override + public void termsClick() { + Intent intent = new Intent(LoginForOtherActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } + }).create(this); + } + + @Override + public void onIdsValid(String ids) { + try { + runOnUiThread(() -> { + SPUtils.saveString(LoginForOtherActivity.this, "OAID", ids); + }); + } catch (Exception e) { + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginResultActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginResultActivity.java new file mode 100644 index 0000000..1233eb2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/login/LoginResultActivity.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.view.login; + +import android.os.Bundle; + +import com.fengliyan.tianlesue.view.base.BaseActivity; + +/** + * Created by zhangbin on 2019/3/5. + * 登录回调界面 + */ + +public class LoginResultActivity extends BaseActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/login/utils/LoginUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/login/utils/LoginUtils.java new file mode 100644 index 0000000..5fa1c67 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/login/utils/LoginUtils.java @@ -0,0 +1,117 @@ +package com.fengliyan.tianlesue.view.login.utils; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; + +import androidx.core.content.FileProvider; + +import com.fengliyan.base.base.utils.NoClearSPUtils; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.main.MainActivity; +import com.fengliyan.tianlesue.view.register.InfoEditActivity; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.auth.LoginInfo; + +import java.io.File; + +public class LoginUtils { + //isRegister为从完善资料界面过来的 + public static void checkLoginStatus(final Activity activity, final LoginBean result, final int isRegister) { + DeviceManager.getInstance().setToken(result.getUserinfo().getToken()); + NoClearSPUtils.saveString(activity, "token", result.getUserinfo().getToken()); + if (0 == result.getUserinfo().getFinish_status()) { + Intent intent = new Intent(activity, InfoEditActivity.class); +// activity.startActivityForResult(intent, REQUEST_INFO); + intent.putExtra("nickname", result.getUserinfo().getNickname()); + intent.putExtra("isRegister", isRegister); + activity.startActivity(intent); + MaleToast.showMessage(activity, "个人资料不完善,请更新"); + if (isRegister == 2) { + activity.finish(); + } + } else { + NimUIKit.login(new LoginInfo(result.getUserinfo().getUser_id() + "", result.getUserinfo().getIm_token()), new RequestCallback() { + @Override + public void onSuccess(LoginInfo loginInfo) { + + SPUtils.saveString(activity, "im_account", loginInfo.getAccount()); + SPUtils.saveString(activity, "im_token", loginInfo.getToken()); + +// DemoCache.setAccount(loginInfo.getAccount()); + + //保存用户信息 + BaseApplication.getInstance().setUserInfo(result.getUserinfo()); + + //保存用户信息 + StorageManager.getInstance(activity).putBean("loginBean", result); + UserManager.setUserInfo(result.getUserinfo()); + +// activity.setResult(RESULT_LOGIN); + Intent intent = new Intent(activity, MainActivity.class); + intent.putExtra("isRegister", isRegister); + intent.putExtra("isLogin", 1); +// //创建一条客服消息 +// NIMClient.getService(MsgService.class).createEmptyRecentContact("4", +// SessionTypeEnum.P2P, +// RecentContactsFragment.RECENT_TAG_STICKY, +// System.currentTimeMillis(), +// true); + activity.startActivity(intent); + activity.finish(); + } + + @Override + public void onFailed(int i) { + MaleToast.showFailureMsg(activity, "登录失败" + i); + } + + @Override + public void onException(Throwable throwable) { + MaleToast.showFailureMsg(activity, "登录失败"); + } + }); + +// ChatManager.getInstance().doManualLogin(activity, result.getUserinfo().getUser_id(), +// result.getUserinfo().getIm_token()); + + } + } + + public static void install(String filePath, Context context) { + File apkFile = new File(filePath); + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + Uri contentUri = FileProvider.getUriForFile( + context + , "com.fengliyan.tianlesue.fileprovider" + , apkFile); + intent.setDataAndType(contentUri, "application/vnd.android.package-archive"); + } else { + intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); + } + context.startActivity(intent); + } + + public static int getVersionCode(Context context) { + int versionCode = 0; + try { + versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode; + } catch (PackageManager.NameNotFoundException e) { + } + return versionCode; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/luck/LuckFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/luck/LuckFragment.java new file mode 100644 index 0000000..d9ca080 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/luck/LuckFragment.java @@ -0,0 +1,550 @@ +package com.fengliyan.tianlesue.view.luck; + +import static android.app.Activity.RESULT_OK; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.ScaleAnimation; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.eventBus.TurntableEvent; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.FirstChargeGiftDialog; +import com.fengliyan.tianlesue.view.base.utils.view.LuckWheelDialog; +import com.fengliyan.tianlesue.view.main.CityPickerActivity; +import com.fengliyan.tianlesue.view.main.GenderUserAndMibiRankActivity; +import com.fengliyan.tianlesue.view.main.SearchActivity; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.rank.ZhiRankActivity; +import com.fengliyan.tianlesue.view.settings.InvitationActivity; +import com.fengliyan.tianlesue.view.settings.MyCoverFlowAdapter; +import com.fengliyan.tianlesue.view.settings.dialog.GirlAuthDialog; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * A simple {@link Fragment} subclass. + * Use the {@link LuckFragment#newInstance} factory method to + * create an instance of this fragment. + */ +public class LuckFragment extends Fragment implements View.OnClickListener, LuckListFragment.SetSpeedImages { + private static final String TAG = "LuckFragment"; + // private AppBarLayout app_bar_layout; + private LinearLayout rl_main_title; + private RelativeLayout title_view_0, title_view_1; + private ConstraintLayout title_view_2; + private TextView tv_0, tv_1, tv_2; + private View title_bottom_line_0, title_bottom_line_1, title_bottom_line_2; + private ImageView iv_luck_rank, iv_luck_hi, iv_luck_search; + // private ConstraintLayout lin_video_speed; +// private ConstraintLayout lin_voice_speed; + // private CoverFlowView cf_luck_img; + private RelativeLayout main_yaoqing_layout; + private ImageView main_yaoqing, main_yaoqing_end; + private LinearLayout main_turntable; + private ImageView main_turntable_end, iv_main_turntable; + + private List channelBeanList = new ArrayList<>(); + + private static final String ARG_PARAM1 = "param1"; + private static final String ARG_PARAM2 = "param2"; + + private String mParam1; + private String mParam2; + + private ViewPager viewPager; + + private MainViewPagerAdapter mViewPagerAdapter; + private List mChannelFragments = new ArrayList<>(); + private LuckListFragment luckListFragment1; + private LuckListFragment luckListFragment2; + private LuckListFragment luckListFragment3; + + private MyCoverFlowAdapter adapter; + + public LuckFragment() { + // Required empty public constructor + } + + public static LuckFragment newInstance(String param1, String param2) { + LuckFragment fragment = new LuckFragment(); + Bundle args = new Bundle(); + args.putString(ARG_PARAM1, param1); + args.putString(ARG_PARAM2, param2); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mParam1 = getArguments().getString(ARG_PARAM1); + mParam2 = getArguments().getString(ARG_PARAM2); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_luck, container, false); + initView(view); + initListener(); + EventBus.getDefault().register(this); + return view; + } + + private void initView(View view) { +// app_bar_layout = view.findViewById(R.id.app_bar_layout); + rl_main_title = view.findViewById(R.id.rl_main_title); + viewPager = view.findViewById(R.id.main_view_pager); + title_view_0 = view.findViewById(R.id.title_view_0); + title_view_1 = view.findViewById(R.id.title_view_1); + title_view_2 = view.findViewById(R.id.title_view_2); + tv_0 = view.findViewById(R.id.tv_0); + tv_1 = view.findViewById(R.id.tv_1); + tv_2 = view.findViewById(R.id.tv_2); + title_bottom_line_0 = view.findViewById(R.id.title_bottom_line_0); + title_bottom_line_1 = view.findViewById(R.id.title_bottom_line_1); + title_bottom_line_2 = view.findViewById(R.id.title_bottom_line_2); + iv_luck_rank = view.findViewById(R.id.iv_luck_rank); + iv_luck_hi = view.findViewById(R.id.iv_luck_hi); + iv_luck_search = view.findViewById(R.id.iv_luck_search); +// cf_luck_img = view.findViewById(R.id.cf_luck_img); +// lin_video_speed = view.findViewById(R.id.lin_video_speed); +// lin_voice_speed = view.findViewById(R.id.lin_voice_speed); + main_yaoqing_layout = view.findViewById(R.id.main_yaoqing_layout); + main_yaoqing = view.findViewById(R.id.main_yaoqing); + main_yaoqing_end = view.findViewById(R.id.main_yaoqing_end); + main_turntable = view.findViewById(R.id.main_turntable); + main_turntable_end = view.findViewById(R.id.main_turntable_end); + iv_main_turntable = view.findViewById(R.id.iv_main_turntable); + + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + iv_luck_rank.setVisibility(View.GONE); +// main_turntable.setVisibility(View.GONE); + } else { + iv_luck_rank.setVisibility(View.VISIBLE); +// main_turntable.setVisibility(View.VISIBLE); + } + } + + private void initListener() { +// lin_video_speed.setOnClickListener(this); +// lin_voice_speed.setOnClickListener(this); + title_view_0.setOnClickListener(this); + title_view_1.setOnClickListener(this); + title_view_2.setOnClickListener(this); + iv_luck_rank.setOnClickListener(this); + iv_luck_hi.setOnClickListener(this); + iv_luck_search.setOnClickListener(this); + main_yaoqing.setOnClickListener(this); + main_yaoqing_end.setOnClickListener(this); + main_turntable.setOnClickListener(this); + main_turntable_end.setOnClickListener(this); +// cf_luck_img.setOnTopViewClickListener((position, itemView) -> { +// if (StrU.isFastClick()) { +// Intent videoSpeedIntent = new Intent(getActivity(), SpeedDatingActivity.class); +// videoSpeedIntent.putExtra(SpeedDatingActivity.SPEED_TYPE, 0); +// videoSpeedIntent.putStringArrayListExtra(SpeedDatingActivity.IMAGE_LIST, imageList); +// startActivity(videoSpeedIntent); +// } +// }); + +// app_bar_layout.addOnOffsetChangedListener(new AppBarStateChangeListener() { +// @Override +// public void onStateChanged(AppBarLayout appBarLayout, State state) { +// if (state == State.EXPANDED) { +// //展开状态 +// rl_main_title.setPadding(UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 4)); +// } else if (state == State.COLLAPSED) { +// //折叠状态 +// rl_main_title.setPadding(UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 32), UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 4)); +// } else { +// //中间状态 +// rl_main_title.setPadding(UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 16), UiUtils.dip2px(getActivity(), 4)); +// } +// } +// }); + Animation animation = new ScaleAnimation(0.9f, 1.0f, 0.9f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + animation.setDuration(500);//动画时间 + animation.setRepeatCount(-1);//动画的反复次数 + animation.setRepeatMode(Animation.REVERSE); + animation.setFillAfter(true);//设置为true,动画转化结束后被应用 + iv_main_turntable.startAnimation(animation);//開始动画 + + Bundle args1 = new Bundle(); + Bundle args2 = new Bundle(); + Bundle args3 = new Bundle(); + args1.putInt(LuckListFragment.ARG_PARAM1, 1); + args2.putInt(LuckListFragment.ARG_PARAM1, 2); + args3.putInt(LuckListFragment.ARG_PARAM1, 3); + luckListFragment1 = new LuckListFragment(); + luckListFragment1.setArguments(args1); + luckListFragment1.setSetSpeedImages(this); + luckListFragment2 = new LuckListFragment(); + luckListFragment2.setArguments(args2); + luckListFragment3 = new LuckListFragment(); + luckListFragment3.setArguments(args3); + mChannelFragments.add(luckListFragment1); + mChannelFragments.add(luckListFragment2); + mChannelFragments.add(luckListFragment3); + + mViewPagerAdapter = new MainViewPagerAdapter(getChildFragmentManager(), + mChannelFragments); + + viewPager.setAdapter(mViewPagerAdapter); + mViewPagerAdapter.notifyDataSetChanged(); + + if (UserManager.getUserInfo().isWomen()) { + viewPager.setCurrentItem(1); + setTitleChange(1); + } else { + viewPager.setCurrentItem(0); + setTitleChange(0); + } + + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int i, float v, int i1) { + } + + @Override + public void onPageSelected(int i) { + setTitleChange(i); + } + + @Override + public void onPageScrollStateChanged(int i) { + } + }); + viewPager.setOffscreenPageLimit(1); + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + if (!hidden) { + ((BaseActivity) getActivity()).hideTitleBar(); +// if (channelBeanList != null && channelBeanList.size() > 0 && cf_luck_img != null) { +// cf_luck_img.startAutoPlay(2000); +// } + if (UserManager.getUserInfo().getGender() == 2) { + getRechargeInfo(); + } + } else { +// cf_luck_img.stopAutoPlay(); + } + } + + public void onEventMainThread(TurntableEvent event) { +// if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { +// main_turntable.setVisibility(View.GONE); +// } else { +// if (event.getType() == 1) { +// main_turntable.setVisibility(View.VISIBLE); +// } else { +// main_turntable.setVisibility(View.GONE); +// } +// } + } + + @Override + public void onResume() { + super.onResume(); + Log.i(TAG, "onResume: "); +// if (channelBeanList != null && channelBeanList.size() > 0 && cf_luck_img != null) { +// cf_luck_img.startAutoPlay(2000); +// } + } + + @Override + public void onPause() { + super.onPause(); +// cf_luck_img.stopAutoPlay(); + } + + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); +// cf_luck_img.stopAutoPlay(); + } + + public void setTitleChange(int index) { + String city = SPUtils.getString(getActivity(), ConsUser.PICKER_CITY); + if (!TextUtils.isEmpty(city)) { + tv_2.setText(city); + } + switch (index) { + case 0: + tv_0.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + tv_0.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + tv_0.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + tv_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + tv_1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + tv_1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + tv_2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + tv_2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + title_bottom_line_0.setVisibility(View.VISIBLE); + title_bottom_line_1.setVisibility(View.GONE); + title_bottom_line_2.setVisibility(View.GONE); + break; + case 1: + tv_0.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + tv_0.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + tv_0.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + tv_1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + tv_1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + tv_2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + tv_2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + tv_2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + title_bottom_line_0.setVisibility(View.GONE); + title_bottom_line_1.setVisibility(View.VISIBLE); + title_bottom_line_2.setVisibility(View.GONE); + break; + case 2: + tv_0.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + tv_0.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + tv_0.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + tv_1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + tv_1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + tv_2.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + tv_2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + tv_2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + title_bottom_line_0.setVisibility(View.GONE); + title_bottom_line_1.setVisibility(View.GONE); + title_bottom_line_2.setVisibility(View.VISIBLE); + break; + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.lin_video_speed://视频速配 + if (StrU.isFastClick()) { + Intent videoSpeedIntent = new Intent(getActivity(), SpeedDatingActivity.class); + videoSpeedIntent.putExtra(SpeedDatingActivity.SPEED_TYPE, 0); + videoSpeedIntent.putStringArrayListExtra(SpeedDatingActivity.IMAGE_LIST, imageList); + startActivity(videoSpeedIntent); + } + break; + case R.id.lin_voice_speed://语音速配 + if (StrU.isFastClick()) { + Intent voiceSpeedIntent = new Intent(getActivity(), SpeedDatingActivity.class); + voiceSpeedIntent.putExtra(SpeedDatingActivity.SPEED_TYPE, 1); + voiceSpeedIntent.putStringArrayListExtra(SpeedDatingActivity.IMAGE_LIST, imageList); + startActivity(voiceSpeedIntent); + } + break; + case R.id.title_view_0: + viewPager.setCurrentItem(0); + break; + case R.id.title_view_1: + viewPager.setCurrentItem(1); + break; + case R.id.title_view_2: + if (viewPager.getCurrentItem() == 2) { + Intent intent = new Intent(getActivity(), CityPickerActivity.class); + startActivityForResult(intent, 1002); + } else { + viewPager.setCurrentItem(2); + } + break; + case R.id.iv_luck_rank://榜单 + Intent intent = new Intent(getActivity(), ZhiRankActivity.class); + startActivity(intent); + break; + case R.id.iv_luck_hi://招呼 + if (UserManager.getUserInfo().getGender() == 1) { + if (UserManager.getUserInfo().getIs_anchor() == 1 && UserManager.getUserInfo().getIs_face_status() == 1) { + groupHello(); + } else { + GirlAuthDialog dialog = new GirlAuthDialog(getActivity()); + dialog.show(); + MaleToast.showMessage(getActivity(), "通过真人认证才能使用该功能"); + } + } else { + Intent intentIntent = new Intent(getActivity(), GenderUserAndMibiRankActivity.class); + startActivity(intentIntent); + } + break; + case R.id.iv_luck_search://搜索 + Intent searchIntent = new Intent(getActivity(), SearchActivity.class); + startActivity(searchIntent); + break; + case R.id.main_yaoqing: + if (is_first_recharge) { + if (mRechargeListBean != null && mRechargeListBean.size() > 2) { + FirstChargeGiftDialog dialog = new FirstChargeGiftDialog(getActivity(), mRechargeListBean, show_wx_pay_type, show_alipay_pay_type); + dialog.setCanceledOnTouchOutside(false); + dialog.show(); + } + } else { + Intent invitationIntent = new Intent(getContext(), InvitationActivity.class); + startActivity(invitationIntent); + } + break; + case R.id.main_yaoqing_end: + main_yaoqing_layout.setVisibility(View.GONE); + break; + case R.id.main_turntable: + LuckWheelDialog dialog = new LuckWheelDialog(getActivity()); + dialog.show(); + break; + case R.id.main_turntable_end: + main_turntable.setVisibility(View.GONE); + break; + } + } + + /** + * 打招呼 + */ + public void groupHello() { + CustomAlertDialog dialog = new CustomAlertDialog(getActivity()); + dialog.hideTitle(true); + dialog.setContent("确定一键给" + NoClearSPUtils.getInt(getContext(), ConsUser.SEND_USER_TOTAL) + "人打招呼吗?\n每天可群发" + NoClearSPUtils.getInt(getContext(), ConsUser.GREET_DAY_TOTAL) + "次,每次需间隔" + NoClearSPUtils.getInt(getContext(), ConsUser.GREET_GAP_HOUR) + "分钟"); + dialog.setRightOnClickListener(() -> MainManager.sendGroupCall((BaseActivity) getActivity(), -1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + MaleToast.showMessage(activity, "发送成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "发送失败"); + } + })); + dialog.show(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 1002 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(getActivity(), ConsUser.PICKER_CITY + "", city); + tv_2.setText(city); + if (!TextUtils.isEmpty(city)) { + String cityId = GlobalManager.getCityMap().get(city); + SPUtils.saveString(getActivity(), ConsUser.PICKER_CITY_ID + "", cityId); + if (null != luckListFragment3) { + luckListFragment3.setCityChoose(cityId); + } + } + } + } + } + + // 审核模式隐藏邀请好友 + public void setMarketStatus(int marketStatus) { + if (marketStatus == 0 || UserManager.getUserInfo().getGender() != 2 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + main_yaoqing_layout.setVisibility(View.GONE); + } else { + main_yaoqing_layout.setVisibility(View.VISIBLE); + } + } + + private boolean is_first_recharge; + private List mRechargeListBean; + private int show_wx_pay_type = 1;//显示微信支付 1显示0不显示 + private int show_alipay_pay_type = 1; + + //男生未充值过显示首充图标 + private void getRechargeInfo() { + SettingManager.getRechargeInfo((BaseActivity) getActivity(), 2, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RechargeListBean result, String message) { + if (result != null) { + mRechargeListBean = result.getGift_bag_list(); + show_wx_pay_type = result.getShow_wx_pay_type(); + show_alipay_pay_type = result.getShow_alipay_pay_type(); + // 1=已经首充过、0=没有首充过 + if (UserManager.getUserInfo().getGender() == 2 && result.getIs_first_recharge() == 0) { + main_yaoqing.setImageResource(R.drawable.ic_lqhl); + is_first_recharge = true; + main_yaoqing_layout.setVisibility(View.VISIBLE); + } else { +// main_yaoqing.setImageResource(R.drawable.yqzq_ic); + is_first_recharge = false; + main_yaoqing_layout.setVisibility(View.GONE); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + // 设置视频速配滚动头像 + private ArrayList imageList = new ArrayList<>(); + + @Override + public void setImagesData(List list) { + channelBeanList.clear(); + imageList.clear(); + channelBeanList.addAll(list); + adapter = new MyCoverFlowAdapter(getActivity(), channelBeanList); +// cf_luck_img.setAdapter(adapter); +// if (channelBeanList != null && channelBeanList.size() > 0) { +// cf_luck_img.setVisibility(View.VISIBLE); +// cf_luck_img.startAutoPlay(2000); +// for (AnchorBean bean : channelBeanList) { +// imageList.add(StrU.getResourcePath(bean.getCover(), getContext())); +// } +// } else { +// cf_luck_img.setVisibility(View.GONE); +// } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/luck/LuckListFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/luck/LuckListFragment.java new file mode 100644 index 0000000..5b36a7f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/luck/LuckListFragment.java @@ -0,0 +1,259 @@ +package com.fengliyan.tianlesue.view.luck; + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.main.adapter.LuckListAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2018/12/25. + * 最新 + */ + +public class LuckListFragment extends Fragment implements LuckListAdapter.OnClickedListener, View.OnClickListener { + private static final String TAG = "LuckListFragment"; + public static final String ARG_PARAM1 = "TYPE"; + private int mType = 1; + private RecyclerView mListView; + private List mChannelAnchors = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + private int mItemCount; + private LuckListAdapter mAdapter; + private SwipeRefreshLayout mRefresh; + private View headerView; + private ConstraintLayout lin_video_speed; + private ConstraintLayout lin_voice_speed; + private ImageView iv_luck_video_speed_bg; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mType = getArguments().getInt(ARG_PARAM1); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_luck_list, container, false); + initView(v); + if (getUserVisibleHint() || mType == 1) { + mPage = 1; + getChannelData(mType, 1, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + } + return v; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); //防止数据预加载, 只预加载View,不预加载数据 + if (isVisibleToUser && isVisible()) { + mPage = 1; + getChannelData(mType, 1, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + } + } + + private void initView(View v) { + mListView = v.findViewById(R.id.luck_list); + mRefresh = v.findViewById(R.id.luck_refresh); + LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false); + mListView.setLayoutManager(layoutManager); + mAdapter = new LuckListAdapter(getActivity()); + mListView.setAdapter(mAdapter); + mAdapter.setOnClickedListener(this); + mListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int i, int i1) { + LinearLayoutManager mLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); + int itemCount = mLayoutManager.getItemCount(); +// Log.i("TAG", "onScrolled: " + itemCount + " --- " + mItemCount + " --- " + mPageLoad + "--------" + mLayoutManager.findLastVisibleItemPosition()); + if (!mPageLoad && itemCount > mItemCount) { + mPageLoad = true; + } + if (itemCount - mLayoutManager.findLastVisibleItemPosition() < 2 && mPageLoad) { + mPageLoad = false; + mItemCount = itemCount; + getChannelData(mType, mPage, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + } + } + }); + + headerView = getLayoutInflater().inflate(R.layout.layout_main_top_view, null); + lin_video_speed = headerView.findViewById(R.id.lin_video_speed); + lin_voice_speed = headerView.findViewById(R.id.lin_voice_speed); + iv_luck_video_speed_bg = headerView.findViewById(R.id.iv_luck_video_speed_bg); + lin_video_speed.setOnClickListener(this); + lin_voice_speed.setOnClickListener(this); + if (UserManager.getUserInfo().isWomen()) { + iv_luck_video_speed_bg.setImageResource(R.mipmap.icon_main_video_speed_man); + } else { + iv_luck_video_speed_bg.setImageResource(R.mipmap.icon_main_video_speed_women); + } + mAdapter.addHeaderView(headerView); + + mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getChannelData(mType, mPage, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + } + }); + } + + public void setCityChoose(String cityId) { + mPage = 1; + getChannelData(mType, mPage, cityId); + } + + private SetSpeedImages mSetSpeedImages; + + public void setSetSpeedImages(SetSpeedImages mSetSpeedImages) { + this.mSetSpeedImages = mSetSpeedImages; + } + + public interface SetSpeedImages { + void setImagesData(List list); + } + + private void getChannelData(int mType, int page, String cityId) { + MainManager.getLuckList((BaseActivity) getActivity(), mType, cityId, mPage, getHttpUiCallBack()); + } + + private HttpUiCallBack getHttpUiCallBack() { + return new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() == 0) { + } else { + if (mPage == 1) { + mItemCount = 0; + mChannelAnchors.clear(); + mChannelAnchors.addAll(result.getList().getList()); + mAdapter.setList(mChannelAnchors); + } else { + List list = result.getList().getList(); + //外循环是循环的次数 + for (int i = 0; i < mChannelAnchors.size(); i++) { + //内循环是 外循环一次比较的次数 + for (int j = list.size() - 1; j > i; j--) { + if (mChannelAnchors.get(i).getUserid() == list.get(j).getUserid()) { + list.remove(j); + } + } + } + mChannelAnchors.addAll(list); + mAdapter.addData(list); + } + if (mSetSpeedImages != null && mPage == 1) { + mSetSpeedImages.setImagesData(mChannelAnchors); + for (AnchorBean bean : mChannelAnchors) { + imageList.add(StrU.getResourcePath(bean.getCover(), getContext())); + } + } + } + } + } + } + mPage++; + mRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mRefresh.setRefreshing(false); + } + }; + } + + @Override + public void onItemClick(int position, int type, ImageView imageView) { + + } + + @Override + public void onSendGreedOne(AnchorBean luckItemBean, String useId) { + sendGreetOne(luckItemBean, useId); + } + + //单独打招呼 + private void sendGreetOne(AnchorBean luckItemBean, String useId) { + MainManager.sendGreetSendOne((BaseActivity) getActivity(), useId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + MaleToast.showMessage(activity, "发送成功"); + luckItemBean.setGreet_status(0); + mAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "发送失败"); + } + }); + } + + private ArrayList imageList = new ArrayList<>(); + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.lin_video_speed://视频速配 + if (StrU.isFastClick()) { + Intent videoSpeedIntent = new Intent(getActivity(), SpeedDatingActivity.class); + videoSpeedIntent.putExtra(SpeedDatingActivity.SPEED_TYPE, 0); + videoSpeedIntent.putStringArrayListExtra(SpeedDatingActivity.IMAGE_LIST, imageList); + startActivity(videoSpeedIntent); + } + break; + case R.id.lin_voice_speed://语音速配 + if (StrU.isFastClick()) { + Intent voiceSpeedIntent = new Intent(getActivity(), SpeedDatingActivity.class); + voiceSpeedIntent.putExtra(SpeedDatingActivity.SPEED_TYPE, 1); + voiceSpeedIntent.putStringArrayListExtra(SpeedDatingActivity.IMAGE_LIST, imageList); + startActivity(voiceSpeedIntent); + } + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/luck/SpeedDatingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/luck/SpeedDatingActivity.java new file mode 100644 index 0000000..7f3f6ad --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/luck/SpeedDatingActivity.java @@ -0,0 +1,260 @@ +package com.fengliyan.tianlesue.view.luck; + +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Bundle; +import android.view.View; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; +import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.AutoPollAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.main.SpeedInfoBean; +import com.fengliyan.tianlesue.utils.AutoPollRecyclerView; +import com.fengliyan.tianlesue.utils.WaveView; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.SpeedWebSocket; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; +import com.fengliyan.tianlesue.view.settings.video.UIUtil; +import com.fengliyan.uikit.toast.MaleToast; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class SpeedDatingActivity extends BaseActivity implements View.OnClickListener { + private static final String TAG = "SpeedDatingActivity"; + + private ImageView iv_speed_back; + private RelativeLayout rl_speed_bg; + private TextView tv_speed_type; + private SVGAImageView svgaImageView; + private WaveView mWaveView; + private ConstraintLayout rl_speed_avatar; + private SimpleDraweeView iv_speed_avatar1, iv_speed_avatar2, iv_speed_avatar3, iv_speed_avatar4, iv_speed_avatar5; + private AutoPollRecyclerView rv_banner1, rv_banner2; + private TextView tv_speed_hint2; + private AutoPollAdapter adapter; + private AutoPollAdapter adapter1; + + public static final String SPEED_TYPE = "SPEED_TYPE"; + public static final String IMAGE_LIST = "IMAGE_LIST"; + private int speedType; + private List imagesList = new ArrayList<>(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_speed_dating); + hideTitleBar(); + Utils.StatusBarLightMode(this, false); + iv_speed_back = findViewById(R.id.iv_speed_back); + rl_speed_bg = findViewById(R.id.rl_speed_bg); + svgaImageView = findViewById(R.id.svga_image_view); + mWaveView = findViewById(R.id.waveView); + tv_speed_type = findViewById(R.id.tv_speed_type); + rl_speed_avatar = findViewById(R.id.rl_speed_avatar); + iv_speed_avatar1 = findViewById(R.id.iv_speed_avatar1); + iv_speed_avatar2 = findViewById(R.id.iv_speed_avatar2); + iv_speed_avatar3 = findViewById(R.id.iv_speed_avatar3); + iv_speed_avatar4 = findViewById(R.id.iv_speed_avatar4); + iv_speed_avatar5 = findViewById(R.id.iv_speed_avatar5); + rv_banner1 = findViewById(R.id.rv_banner1); + rv_banner2 = findViewById(R.id.rv_banner2); + tv_speed_hint2 = findViewById(R.id.tv_speed_hint2); + iv_speed_back.setOnClickListener(this); + + //速配头像展示 + imagesList = getIntent().getStringArrayListExtra(IMAGE_LIST); + if (imagesList != null && imagesList.size() > 0) { + iv_speed_avatar1.setImageURI(imagesList.get(0)); + if (imagesList.size() > 1) { + iv_speed_avatar2.setImageURI(imagesList.get(1)); + } + if (imagesList.size() > 2) { + iv_speed_avatar3.setImageURI(imagesList.get(2)); + } + if (imagesList.size() > 3) { + iv_speed_avatar4.setImageURI(imagesList.get(3)); + } + if (imagesList.size() > 4) { + iv_speed_avatar5.setImageURI(imagesList.get(4)); + } + } + + speedType = getIntent().getIntExtra(SPEED_TYPE, 0); + + SVGAParser svgaParser = new SVGAParser(this); + + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(UIUtil.getScreenWidth(this), UIUtil.getScreenWidth(this)); + params.setMargins(0, (UIUtil.getScreenHeight(this) - UIUtil.getScreenWidth(this)) / 2 - UIUtil.dip2px(this, 30), 0, 0); + rl_speed_avatar.setLayoutParams(params); + + if (speedType == 0) { + tv_speed_type.setText("视频匹配中..."); + getCallSpeedInfo("2"); + SpeedWebSocket.getInstance().sedText("{\"method\":\"startSpeed\",\"data\":{\"call_type\":2,\"source_id\":1}}"); + } else { + tv_speed_type.setText("语音匹配中..."); + getCallSpeedInfo("3"); + SpeedWebSocket.getInstance().sedText("{\"method\":\"startSpeed\",\"data\":{\"call_type\":3,\"source_id\":1}}"); + } + + String svgaFile; + if (UserManager.getUserInfo().getGender() == 1) {//女 + rl_speed_bg.setBackgroundResource(R.drawable.ic_speed_women_bg); + mWaveView.setVisibility(View.GONE); + if (speedType == 0) { + svgaFile = "svga/speed_video_women.svga"; + } else { + svgaFile = "svga/speed_voice_women.svga"; + } + tv_speed_hint2.setText("通话时间越长收益越多,不足15秒无收益"); + tv_speed_hint2.setTextColor(Color.parseColor("#CCFFFFFF")); + + } else { + rl_speed_bg.setBackgroundResource(R.drawable.ic_speed_man_bg); + mWaveView.setVisibility(View.VISIBLE); + mWaveView.setLayoutParams(params); + mWaveView.setStyle(Paint.Style.FILL); + mWaveView.setColor(Color.parseColor("#FFFFFF")); + mWaveView.setInterpolator(new LinearOutSlowInInterpolator()); + mWaveView.start(); + if (speedType == 0) { + svgaFile = "svga/speed_video_man.svga"; + } else { + svgaFile = "svga/speed_voice_man.svga"; + } + tv_speed_hint2.setText("每分钟消费50金币起"); + tv_speed_hint2.setTextColor(Color.parseColor("#FFFFFF")); + tv_speed_hint2.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(this, R.mipmap.coin), null, null, null); + } + + svgaParser.decodeFromAssets(svgaFile, new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity videoItem) { + SVGADrawable drawable = new SVGADrawable(videoItem); + svgaImageView.setImageDrawable(drawable); + svgaImageView.startAnimation(); + } + + @Override + public void onError() { + } + }); + + adapter = new AutoPollAdapter(this); + adapter1 = new AutoPollAdapter(this); + rv_banner1.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + rv_banner1.setAdapter(adapter); + rv_banner2.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + rv_banner2.setAdapter(adapter1); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_speed_back: + finish(); + break; + } + } + + private void getCallSpeedInfo(String type) { + SettingManager.getCallSpeedInfo(this, type, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SpeedInfoBean result, String message) { + if (result != null) { + if (UserManager.getUserInfo().getGender() == 1) {//女 + tv_speed_hint2.setText("通话时间越长收益越多,不足" + result.getIncome_second() + "秒无收益"); + } else { + tv_speed_hint2.setText("每分钟消费" + result.getPrice() + "金币起"); + } + + if (result.getSpeed_list() != null && result.getSpeed_list().size() > 0) { + List mList = new ArrayList<>(); + List mList1 = new ArrayList<>(); + for (int i = 0; i < result.getSpeed_list().size(); i++) { + if (i > 9) { + mList1.add(result.getSpeed_list().get(i)); + } else { + mList.add(result.getSpeed_list().get(i)); + } + } + if (mList.size() > 0) { + rv_banner1.setVisibility(View.VISIBLE); + adapter.setmData(mList); + rv_banner1.start(); + } else { + rv_banner1.setVisibility(View.INVISIBLE); + } + if (mList1.size() > 0) { + rv_banner2.setVisibility(View.VISIBLE); + adapter1.setmData(mList1); + rv_banner2.start(); + } else { + rv_banner2.setVisibility(View.INVISIBLE); + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + protected void onRestart() { + super.onRestart(); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + if (speedType == 0) { + SpeedWebSocket.getInstance().sedText("{\"method\":\"startSpeed\",\"data\":{\"call_type\":2,\"source_id\":1}}"); + } else { + SpeedWebSocket.getInstance().sedText("{\"method\":\"startSpeed\",\"data\":{\"call_type\":3,\"source_id\":1}}"); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + mWaveView.stop(); + if (speedType == 0) { + SpeedWebSocket.getInstance().sedText("{\"method\":\"quitSpeed\",\"data\":{\"call_type\":2,\"source_id\":1}}"); + } else { + SpeedWebSocket.getInstance().sedText("{\"method\":\"quitSpeed\",\"data\":{\"call_type\":3,\"source_id\":1}}"); + } + } + + //获取当前速配类型 + public int getSpeedType() { + if (speedType == 0) { + return 2; + } else { + return 3; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/AddGroupCallActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/AddGroupCallActivity.java new file mode 100644 index 0000000..c05fa95 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/AddGroupCallActivity.java @@ -0,0 +1,141 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Context; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +/** + * Created by zhangbin on 2019/1/28. + */ + +public class AddGroupCallActivity extends BaseActivity implements View.OnClickListener { + + private View mTitleView; + private TextView mBack; + private TextView mTvSubmit; + private EditText mEtInputMessage; + private TextView mTvInputCount; + private String mText = ""; + private RelativeLayout mRlAddGroupCall; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_add_group_call); + initTitle(); + initView(); + } + + private void initView() { + mEtInputMessage = findViewById(R.id.et_input_message); + mTvInputCount = findViewById(R.id.tv_input_count); + mRlAddGroupCall = findViewById(R.id.rl_add_group_call); + mRlAddGroupCall.setOnClickListener(this); + + initEdit(); + } + + private void initTitle() { + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(android.R.color.white); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.item_add_group_call_title, null); + mBack = mTitleView.findViewById(R.id.tv_cancel); + mTvSubmit = mTitleView.findViewById(R.id.tv_submit); + mBack.setOnClickListener(this); + mTvSubmit.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + } + + private void initEdit() { + + mEtInputMessage.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + String str = s.toString(); + if (!TextUtils.isEmpty(str)) { + if (str.length() <= 50) { + mTvInputCount.setText(str.length() + ""); + mText = str.trim(); + } else { + MaleToast.showMessage(AddGroupCallActivity.this, "最多输入50字"); + } + } + + } + }); + } + + @Override + public void onClick(View view) { + if (view == mBack) { + finish(); + } else if (view == mTvSubmit) { + if (!TextUtils.isEmpty(mText)) { + setGroupCallContent(mText); + } + } else if (view == mRlAddGroupCall) { +// mEtInputMessage.setFocusable(true); +// mEtInputMessage.setFocusableInTouchMode(true); +// mEtInputMessage.requestFocus(); +// getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); + mEtInputMessage.requestFocus();//setFocus方法无效 //addAddressRemarkInfo is EditText + + } + } + + private void setGroupCallContent(String text) { + MainManager.setAddGroupCall(this, text, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(activity, "等待审核"); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/AgoraWithFUVideoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/AgoraWithFUVideoActivity.java new file mode 100644 index 0000000..40b3858 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/AgoraWithFUVideoActivity.java @@ -0,0 +1,2761 @@ +package com.fengliyan.tianlesue.view.main; + +import android.Manifest; +import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; +import android.app.NotificationManager; +import android.content.ContentResolver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.database.ContentObserver; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.provider.MediaStore; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Base64; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.TextureView; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.Space; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.model.facebeauty.FaceBeauty; +import com.faceunity.core.model.facebeauty.FaceBeautyBlurTypeEnum; +import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum; +import com.faceunity.nama.FURenderer; +import com.faceunity.nama.control.FaceBeautyControlView; +import com.faceunity.nama.data.FaceUnityDataFactory; +import com.faceunity.nama.repo.FaceBeautySource; +import com.faceunity.nama.ui.FaceUnityView; +import com.flyco.roundview.RoundLinearLayout; +import com.google.android.exoplayer2.DefaultRenderersFactory; +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.ui.PlayerView; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.fengliyan.base.base.permission.AbsPermissionResultCallBack; +import com.fengliyan.base.base.permission.PermissionHelper; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.http.httprequest.OkHttp.CaiWebSocket; +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.messaging.EventBusGiftMessage; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.RtcEngineEventHandler; +import com.fengliyan.tianlesue.agora.RtcEngineEventHandlerProxy; +import com.fengliyan.tianlesue.agora.framework.PreprocessorFaceUnity; +import com.fengliyan.tianlesue.agora.framework.RtcVideoConsumer; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.main.adapter.VideoAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.news.manager.NewsManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.ChatShootBean; +import com.fengliyan.tianlesue.model.main.ContactBean; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.model.main.PornCheckBeanV2; +import com.fengliyan.tianlesue.model.main.VideoGuardBean; +import com.fengliyan.tianlesue.model.main.VideoRequestBean; +import com.fengliyan.tianlesue.model.main.VideoRequestDataBean; +import com.fengliyan.tianlesue.model.main.websocket.GiftBean; +import com.fengliyan.tianlesue.model.main.websocket.HangUpBean; +import com.fengliyan.tianlesue.model.main.websocket.NoticeBean; +import com.fengliyan.tianlesue.model.main.websocket.NoticeGiftBean; +import com.fengliyan.tianlesue.model.main.websocket.RoomIdBean; +import com.fengliyan.tianlesue.model.main.websocket.TextBean; +import com.fengliyan.tianlesue.model.main.websocket.TimeRemainingBean; +import com.fengliyan.tianlesue.model.main.websocket.TipBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketChatBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketRequestBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketResultBean; +import com.fengliyan.tianlesue.utils.AnimUtils; +import com.fengliyan.tianlesue.utils.BeautySPUtils; +import com.fengliyan.tianlesue.utils.FrameAnimation; +import com.fengliyan.tianlesue.utils.GlideUtils; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.SoftKeyBoardListener; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.utils.TimeZoneUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.GuardDialog; +import com.fengliyan.tianlesue.view.base.utils.view.HangUpDialog; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.main.dialog.SvgaDialog; +import com.fengliyan.tianlesue.view.main.utils.DefaultExoConfig; +import com.fengliyan.tianlesue.view.news.fragment.EmotionFragment; +import com.fengliyan.tianlesue.view.settings.CaibeiRechargeActivity; +import com.fengliyan.tianlesue.view.settings.QuickRechargeActivity; +import com.fengliyan.uikit.UiUtils; +import com.fengliyan.uikit.dialog.BottomGiftDialog; +import com.fengliyan.uikit.dialog.DialogGiftBean; +import com.fengliyan.uikit.dialog.GiftListBean; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.lang.reflect.Type; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import de.greenrobot.event.EventBus; +import eightbitlab.com.blurview.BlurTarget; +import eightbitlab.com.blurview.BlurView; +import io.agora.capture.video.camera.CameraVideoManager; +import io.agora.capture.video.camera.VideoCapture; +import io.agora.rtc.Constants; +import io.agora.rtc.RtcEngine; +import io.agora.rtc.RtcEngineConfig; +import io.agora.rtc.mediaio.AgoraTextureView; +import io.agora.rtc.video.VideoCanvas; +import io.agora.rtc.video.VideoEncoderConfiguration; + +/** + * Created by zhangbin on 2019/1/26. + */ +public class AgoraWithFUVideoActivity extends BaseActivity implements View.OnClickListener, RtcEngineEventHandler, SensorEventListener { + private static final String TAG = "AgoraWithFUVideoActivit"; + public static int mCallID = 110; + private String mSocketUrl; + private int mRoomId; + + private Timer heartTimer; + private TimerTask heartTask; + private Timer countTimer; + private TimerTask countTask; + private Timer maskTimer; + private TimerTask maskTask; + private int count = 40; + private boolean isCaller; //false为被叫 true为主叫 + // private BaseMessageDialog mMessageDialog; + private BottomGiftDialog mGiftDialog; + // private BaseMessageDialog mConfirmDialog; + private long mBaseTime; + private Timer mCallingTimer; + private TimerTask mCallingTimerTask; + private boolean isCameraSwitch; //切换前后摄像头 + private boolean isLocalMain = false; //点击小视频,false为自己是小窗口,对方为大窗口 + private boolean videoOn = true; //是否开启视频 `l + private boolean isMute = true; + private boolean isStarted; //视频是否开始 + private MediaPlayer mMediaPlayer; + private boolean isShowBlur = false;//是否展示模糊遮罩 + + private List mChatBeanList = new ArrayList<>(); + private VideoAdapter mVideoChatAdapter; + + private FURenderer mFURenderer = FURenderer.getInstance(); + private FaceUnityDataFactory mFaceUnityDataFactory; + private PreprocessorFaceUnity preprocessor; + private FaceBeauty faceBeauty; + private SensorManager mSensorManager; + private RtcEngine mRtcEngine; + private RtcEngineEventHandlerProxy mRtcEventHandler; + private CameraVideoManager mVideoManager; + + private int isOpenDetection; //是否开启鉴黄 + private int detectionTime; //图片上传间隔 + private boolean mMuted = false; //对方是否关掉了视频 true代表已关闭 + private PornCheckBeanV2 mPornCheckBeanV2; + private boolean needChatShoot = true; + private List mPornCheckV2List; + private int check_from_user; + private int maskSecond; + + private ImageView mIv_guard; + private ImageView mIv_guard1; + private int mDiff_num; + private int mGuard_price; + private GuardDialog mGuardDialog; + + private int mRemainTime; + private Timer mRemainTimer; + private TimerTask mRemainTimerTask; + private int REQUEST_RECHARGE = 1005; + + private int callType;//0.视频 1.语音 + private boolean isSpeed;//是否是速配 + private CallBean bean;//封面视频 + private HangUpDialog hangUpDialog; + private boolean isRisk;//是否是风险用户 + + private boolean isFirstShow = true; + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == 0) { //发送心跳包 + sendHeartbeat(); + } else if (msg.what == 1) { //检测心跳倒计时 + count = --count; + if (count == 0) { + stopTimer(); + MainManager.reconnectWebSocket(mSocketUrl + "&reconnect=1"); + } + } else if (msg.what == 4) { //显示通话时长 + mVideoDuration.setText(msg.obj + ""); + tv_voice_time.setText(msg.obj + ""); + } else if (msg.what == 5) { //显示剩余时长 + int time = (int) msg.obj; + /*String hh = new DecimalFormat("00").format(time / 3600); + String mm = new DecimalFormat("00").format(time % 3600 / 60); + String ss = new DecimalFormat("00").format(time % 60); + String timeFormat = new String(hh + ":" + mm + ":" + ss); + mTvRemainTime.setText(timeFormat); + + if (isCaller) { + if (time <= 1) { + hangUpVideo(); + } + }*/ + } + } + }; + private int mRoomDuration; + private SvgaDialog mSvgaDialog; + + public String Bitmap2StrByBase64(Bitmap bit) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int start; + int end; + int options = 50; + bit.compress(Bitmap.CompressFormat.JPEG, 100, bos);//参数100表示不压缩 + while (bos.toByteArray().length / 1024 > 30) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 + start = bos.toByteArray().length / 1024; + bos.reset();//重置baos即清空baos + bit.compress(Bitmap.CompressFormat.JPEG, options, bos);//这里压缩options%,把压缩后的数据存放到baos中 + if (options > 5) { + options -= 5;//每次都减少10 + } + end = bos.toByteArray().length / 1024; + if (start == end) { + break; + } + } + return Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT); + } + + private String mAvatar; + private String mNickName; + private String mPrice; + private String mFreeNum; + private int mToUid; + private RelativeLayout mVideoStartLayout; + private ImageView mIvVideoBeauty; + private RelativeLayout mRlBeautyContainer; + private RelativeLayout mRlVideoStartLayout; + private RelativeLayout mRlVideoLayout; + private RelativeLayout mRlDealLayout; + private LinearLayout video_action; + private int mWidth; + private LinearLayout mLlEdit; + private EditText mChatEdit; + private TextView mEditSubmitButton; + private int mDialogHeight; + private LinearLayout mLlShowTime; + private ImageView mVideoFinish; + private TextView tv_warn_recharge; + private Handler mReHandler = new Handler(); + + private View mLlRemainTime; + private TextView mTvRemainTime; + + private PhotoObserver mPhotoObserver; + private VideoObserver mVideoObserver; + private long mMillis; + private int mImageId; + private int mVideoId; + + private RoundLinearLayout wxContainer; + private boolean isShowWechat; + private TextView wxAccountTipLabel; + + private RelativeLayout rl_video; + private PlayerView video_view; + private ImageView iv_avatar; + private SimpleDraweeView iv_user_avatar; + private TextView tv_nick_name; + private TextView tv_age; + private ImageView iv_follow; + private TextView tv_hangup; + private ExoPlayer player; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + final Window win = getWindow(); + win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); + setContentView(R.layout.activity_ogora_with_fu_new); + win.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); + String servids = NoClearSPUtils.getString(this, ConsUser.SERVIDS); + ArrayList selectLabelList = new ArrayList<>(Arrays.asList(servids.split(","))); + boolean b = false; + for (int i = 0; i < selectLabelList.size(); i++) { + if (TextUtils.equals(selectLabelList.get(i), UserManager.getUserInfo().getUser_id() + "")) { + b = true; + break; + } + } + if (!b) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); + } + WindowManager manager = this.getWindowManager(); + DisplayMetrics outMetrics = new DisplayMetrics(); + manager.getDefaultDisplay().getMetrics(outMetrics); + mWidth = outMetrics.widthPixels; + + mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); + mVideoManager = new CameraVideoManager(this, new PreprocessorFaceUnity(this)); + BaseApplication.getInstance().setVideo(true); + hideTitleBar(); + getIntentValue(); + initView(); + initRtcEngine();//初始化声网美颜工作线程 + initFUModule(); + mMediaPlayer = MediaPlayer.create(this, R.raw.call_bg); + mMediaPlayer.setLooping(true); + + mMillis = System.currentTimeMillis() / 1000; + mPhotoObserver = new PhotoObserver(new Handler()); + // 注册观察者 + getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, mPhotoObserver); + + mVideoObserver = new VideoObserver(new Handler()); + getContentResolver().registerContentObserver(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true, mVideoObserver); + + //权限允许 + PermissionDialog permissionDialog = new PermissionDialog(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}); + permissionDialog.show(); + PermissionHelper.request(new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, + new AbsPermissionResultCallBack() { + @Override + public void onPermissionGranted() { + permissionDialog.dismiss(); + connectSocket(); + } + + @Override + public void onPermissionDenied(String... permissions) { + String market = DeviceManager.getInstance().getApplicationMarket(); + if (market != null && market.equals("huawei")) { + permissionDialog.dismiss(); + finish(); + return; + } + super.onPermissionDenied(permissions); + permissionDialog.dismiss(); + } + }); + } + + private void initRtcEngine() { + String appId = ""; + if (!StrU.isEmpty(NoClearSPUtils.getString(this, ConsUser.AGORA_APP_ID))) { + appId = NoClearSPUtils.getString(this, ConsUser.AGORA_APP_ID); + } else { + appId = getString(R.string.agora_app_id); + } + if (TextUtils.isEmpty(appId)) { + throw new RuntimeException("NEED TO use your App ID, get your own ID at https://dashboard.agora.io/"); + } + mRtcEventHandler = new RtcEngineEventHandlerProxy(); + try { + // mRtcEngine = RtcEngine.create(this, appId, mRtcEventHandler); + int areaCode = RtcEngineConfig.AreaCode.AREA_CODE_CN; + RtcEngineConfig config = new RtcEngineConfig(); + config.mAreaCode = areaCode; + config.mAppId = appId; + config.mEventHandler = mRtcEventHandler; + config.mContext = this; + mRtcEngine = RtcEngine.create(config); + // mRtcEngine.enableVideo(); + // mRtcEngine.setChannelProfile(io.agora.rtc.Constants.CHANNEL_PROFILE_LIVE_BROADCASTING); + } catch (Exception e) { + throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e)); + } + } + + private void refreshWx(final String userId) { + SettingManager.getWeChat(this, userId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ContactBean.WechatBean result, String tips) { + refreshWeChatStatus(result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + void refreshWeChatStatus(ContactBean.WechatBean mMainPageBean) { + if (mMainPageBean.getStatus() == 2 || mMainPageBean.getIf_forbidden() == 2 || ("oppo".equals(DeviceManager.getInstance().getApplicationMarket()))) { + wxContainer.setVisibility(View.GONE); + isShowWechat = false; + } else { + wxContainer.setVisibility(View.VISIBLE); + isShowWechat = true; + int wechatPrice = 0; + try { + wechatPrice = Integer.parseInt(mMainPageBean.getWechat_price()); + } catch (NumberFormatException e) { + + } + if (mMainPageBean.getGender() == 2) { + if (mMainPageBean.getGiftCoin() >= wechatPrice) { + wxAccountTipLabel.setText("已解锁微信,在你的主页查看"); + } else { + wxAccountTipLabel.setText(String.format("对方解锁微信还需%d金币的礼物", wechatPrice - mMainPageBean.getGiftCoin())); + } + } else { + if (mMainPageBean.getGiftCoin() >= wechatPrice) { + wxAccountTipLabel.setText("已解锁微信,在对方主页查看"); + } else { + wxAccountTipLabel.setText(String.format("解锁微信还需%d金币的礼物", wechatPrice - mMainPageBean.getGiftCoin())); + } + } + } + } + + @Override + protected void onStart() { + super.onStart(); + mRtcEventHandler.addEventHandler(this); + } + + @Override + public void onResume() { + super.onResume(); + if (mSensorManager != null) { + Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL); + } + if (preprocessor != null) { + preprocessor.setRenderEnable(true); + } + if (mVideoManager != null) { + mVideoManager.startCapture(); + } + + ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(MainActivity.mCallID); + + //在视频界面不提醒消息 + NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_ALL, SessionTypeEnum.None); + } + + @Override + protected void onPause() { + super.onPause(); + //不在视频界面提醒消息 + NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE, SessionTypeEnum.None); + if (mSensorManager != null) { + mSensorManager.unregisterListener(this); + } + if (preprocessor != null && mVideoManager != null) { + preprocessor.releaseFURender(); + } + + if (mVideoManager != null) { + mVideoManager.stopCapture(); + } + if (player != null) { + player.pause(); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (player != null) { + player.release(); + } + mRtcEventHandler.removeEventHandler(this); + } + + // 监听图片变化 + class PhotoObserver extends ContentObserver { + public PhotoObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + + if (BaseApplication.getInstance().isFront()) { + //查询出第一条记录 + Cursor c; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Bundle queryArgs = new Bundle(); + // Android 11+ 的官方方式 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + queryArgs.putString(ContentResolver.QUERY_ARG_SQL_LIMIT, String.valueOf(1)); + } + // Android 5.0 - 10 的兼容方式 + else { + queryArgs.putString("limit", String.valueOf(1)); + } + c = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null); + } + // 方法2: 旧版本回退方案 + else { + c = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, "_id DESC LIMIT 1"); + }// Cursor c = getContentResolver().query(uri, null, null, null, "_id DESC LIMIT 1"); + if (c.moveToNext()) { + @SuppressLint("Range") int imageId = c.getInt((c.getColumnIndex(MediaStore.Video.Media._ID))); + @SuppressLint("Range") String title = c.getString(c.getColumnIndex(MediaStore.Files.FileColumns.DATA)); + @SuppressLint("Range") long aLong = c.getLong(c.getColumnIndex(MediaStore.Files.FileColumns.DATE_ADDED)); + posService(aLong, title, imageId); + } + c.close(); + } + } + } + + // 监听视频变化 + class VideoObserver extends ContentObserver { + public VideoObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + + if (BaseApplication.getInstance().isFront()) { + //查询出第一条记录 + Cursor c; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Bundle queryArgs = new Bundle(); + // Android 11+ 的官方方式 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + queryArgs.putString(ContentResolver.QUERY_ARG_SQL_LIMIT, String.valueOf(1)); + } + // Android 5.0 - 10 的兼容方式 + else { + queryArgs.putString("limit", String.valueOf(1)); + } + c = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null); + } + // 方法2: 旧版本回退方案 + else { + c = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, "_id DESC LIMIT 1"); + } + if (c.moveToNext()) { + @SuppressLint("Range") int imageId = c.getInt((c.getColumnIndex(MediaStore.Video.Media._ID))); + @SuppressLint("Range") String title = c.getString(c.getColumnIndex(MediaStore.Files.FileColumns.DATA)); + @SuppressLint("Range") long aLong = c.getLong(c.getColumnIndex(MediaStore.Files.FileColumns.DATE_ADDED)); + + posVideoService(aLong, title, imageId); + } + c.close(); + } + } + } + + private void posService(long aLong, String title, int imageId) { + if (aLong > mMillis) { + if (mImageId != imageId) { + mImageId = imageId; + File file = new File(title); + + if (null != file && file.exists() && file.isFile()) { + file.delete(); + } + + MainManager.postScreenNumber(this, 1, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + getContentResolver().unregisterContentObserver(mPhotoObserver); + getContentResolver().unregisterContentObserver(mVideoObserver); + hangUpVideo(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + } + } + + private void posVideoService(long aLong, String title, int imageId) { + if (aLong > mMillis) { + if (mVideoId != imageId) { + mVideoId = imageId; + File file = new File(title); + + if (null != file && file.exists() && file.isFile()) { + file.delete(); + } + + MainManager.postScreenNumber(this, 2, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + getContentResolver().unregisterContentObserver(mPhotoObserver); + getContentResolver().unregisterContentObserver(mVideoObserver); + hangUpVideo(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + } + } + + /** + * 获取界面跳转带过来的值 + */ + private void getIntentValue() { + Intent intent = getIntent(); + mSocketUrl = intent.getStringExtra(Constant.SOCKET_URL); + mRoomId = intent.getIntExtra("roomId", 0); + isCaller = intent.getBooleanExtra("isCaller", false); + mAvatar = intent.getStringExtra("avatar"); + mNickName = intent.getStringExtra("nickName"); + mPrice = intent.getStringExtra("price"); + mFreeNum = intent.getStringExtra("free_num"); + mToUid = intent.getIntExtra("toUid", 0); + callType = intent.getIntExtra("callType", 0); + isSpeed = intent.getBooleanExtra("isSpeed", false); + bean = (CallBean) intent.getSerializableExtra("bean"); + isRisk = intent.getBooleanExtra("isRisk", false); + + mPornCheckBeanV2 = (PornCheckBeanV2) intent.getSerializableExtra("porn_check_bean_v2"); + if (mPornCheckBeanV2 != null) { + isOpenDetection = mPornCheckBeanV2.getIs_open(); + detectionTime = mPornCheckBeanV2.getInterval(); + mPornCheckV2List = mPornCheckBeanV2.getPeriodArray(); + check_from_user = mPornCheckBeanV2.getCheck_from_user(); + maskSecond = mPornCheckBeanV2.getShow_mask_second(); + } + + mDiff_num = intent.getIntExtra("diff_num", 0); + mGuard_price = intent.getIntExtra("guard_price", 0); + + + } + + private SimpleDraweeView mBackground; + private SimpleDraweeView mStartPhoto; + private TextView mStartName; + private TextView mStartCost; + private TextView mStartCountDownTimeText; + private TextView mStartHint; + private TextView mStartHint1; + private TextView mCallerCancelButton; + private TextView mCalleeCancelButton; + private TextView mCalleeAnswerButton; + private FrameLayout mRemoteVideoView; + private AgoraTextureView localVideoNew; + private BlurTarget target; + private BlurView blurView; + private BlurTarget target1; + private BlurView blurView1; + private FrameLayout mLocalVideoView; + private LinearLayout mBackAndCost; + private ImageView mVideoEnd; + private TextView mVideoDuration; + private ImageView mVideoCameraSwitcher; + private LinearLayout mVideoSocialBoard; + private ImageView mVideoSwitcher; + private ImageView mVideoMuteSwitcher; //扬声器的关闭 + private ImageView videoOpenMic; //麦克风的关闭 + private ImageView mVideoGift; + private LoadMoreListView mVideoChatList; + private ImageView mVideoChat; + private EmotionFragment mEmotionFragment; + private LinearLayout lin_voice_btn; + private ImageView tv_voice_mic; + private ImageView tv_voice_cancel; + private ImageView tv_voice_spk; + private TextView tv_voice_time; + private Space sp_voice_action; + + private int clickCount = 0;//点击次数 + private long firstClick = 0;//第一次点击时间 + private long secondClick = 0;//第二次点击时间 + + private float remoteX1 = 0; + private float remoteX2 = 0; + + private int localClickCount = 0; + private long localFirstClick = 0; + private long localSecondClick = 0; + + private float localX1 = 0; + private float localX2 = 0; + + private boolean isScreen = true; //是否在屏幕内 + + /** + * 两次点击时间间隔,单位毫秒 + */ + private final int totalTime = 500; + + private String chatText; + FrameAnimation guardAnimation; + //初始化布局 + + private void initView() { + rl_video = findViewById(R.id.rl_video); + video_view = findViewById(R.id.video_view); + iv_avatar = findViewById(R.id.iv_avatar); + iv_user_avatar = findViewById(R.id.iv_user_avatar); + tv_nick_name = findViewById(R.id.tv_nick_name); + tv_age = findViewById(R.id.tv_age); + iv_follow = findViewById(R.id.iv_follow); + tv_hangup = findViewById(R.id.tv_hangup); + + wxContainer = findViewById(R.id.wxContainer); + wxAccountTipLabel = findViewById(R.id.wxAccountTipLabel); + //视频前头像大背景 + mBackground = findViewById(R.id.video_background); + //视频前的一些展示 + mVideoStartLayout = findViewById(R.id.video_start_layout); + //头像 + mStartPhoto = findViewById(R.id.video_start_photo); + //名字 + mStartName = findViewById(R.id.video_start_name); + //价格 + mStartCost = findViewById(R.id.video_start_cost); + //接听倒计时 + mStartCountDownTimeText = findViewById(R.id.video_start_count_down); + //接听前的提示信息 + mStartHint = findViewById(R.id.video_start_hint); + mStartHint1 = findViewById(R.id.video_start_hint1); + mStartHint1.setText(mFreeNum); + //主叫者取消按钮 + mCallerCancelButton = findViewById(R.id.video_caller_cancel); + //被叫者取消按钮 + mCalleeCancelButton = findViewById(R.id.video_callee_cancel); + //被叫者接听 + mCalleeAnswerButton = findViewById(R.id.video_callee_answer); + //远程的视频展示 + mRemoteVideoView = findViewById(R.id.video_remote_view); + target = findViewById(R.id.target); + blurView = findViewById(R.id.blurView); + target1 = findViewById(R.id.target1); + blurView1 = findViewById(R.id.blurView1); + //本地视频展示 + mLocalVideoView = findViewById(R.id.video_recent_view); + //取消和视频时长 + mBackAndCost = findViewById(R.id.ll_back_and_cost); + //返回按钮 + mVideoEnd = findViewById(R.id.video_end); + //视频中的时长 + mVideoDuration = findViewById(R.id.video_remote_duration); + //视频下面的bottom + mVideoSocialBoard = findViewById(R.id.video_social_board); + //视频窗口切换 + mVideoCameraSwitcher = findViewById(R.id.video_shoot); + //关闭视频窗口 + mVideoSwitcher = findViewById(R.id.video_open_camera); + //关闭声音 + mVideoMuteSwitcher = findViewById(R.id.video_mute); + //麦克风 + videoOpenMic = findViewById(R.id.video_open_mic); + //礼物按钮 + mVideoGift = findViewById(R.id.video_gift); + //礼物列表 + mVideoChatList = findViewById(R.id.video_social_list); + //聊天按钮 + mVideoChat = findViewById(R.id.video_chat); + //聊天输入 +// mBottomEdit = findViewById(R.id.video_bottom_edit); + //美颜框 + mRlBeautyContainer = findViewById(R.id.rl_beauty_container); + //美颜按钮 + mIvVideoBeauty = findViewById(R.id.iv_video_beauty); + //视频前的界面 + mRlVideoStartLayout = findViewById(R.id.rl_video_start_layout); + //视频中的界面 + mRlVideoLayout = findViewById(R.id.rl_video_layout); + //视频中的操作界面 + mRlDealLayout = findViewById(R.id.rl_deal_layout); + //聊天输入框 + mLlEdit = findViewById(R.id.ll_edit); + //聊天编辑 + mChatEdit = findViewById(R.id.edit_edit); + //聊天点击发送按钮 + mEditSubmitButton = findViewById(R.id.edit_submit_button); + + mLlShowTime = findViewById(R.id.ll_show_time); + //视频前的关闭按钮 + mVideoFinish = findViewById(R.id.video_finish); + + //剩余时长 + mLlRemainTime = findViewById(R.id.ll_remain_time); + tv_warn_recharge = findViewById(R.id.tv_warn_recharge); + + //剩余时长文本显示 + mTvRemainTime = findViewById(R.id.tv_remain_time); + + mIv_guard = findViewById(R.id.iv_guard); + mIv_guard1 = findViewById(R.id.iv_guard1); + + //视频操作按钮 + video_action = findViewById(R.id.video_action); + + //语音按钮 + lin_voice_btn = findViewById(R.id.lin_voice_btn); + tv_voice_mic = findViewById(R.id.tv_voice_mic); + tv_voice_cancel = findViewById(R.id.tv_voice_cancel); + tv_voice_spk = findViewById(R.id.tv_voice_spk); + tv_voice_time = findViewById(R.id.tv_voice_time); + sp_voice_action = findViewById(R.id.sp_voice_action); + + if (UserManager.getUserInfo().getGender() == 2) { + tv_warn_recharge.setText("充值"); + mIv_guard.setVisibility(View.VISIBLE); + mIv_guard1.setVisibility(View.GONE); + } else { + tv_warn_recharge.setText("提示充值"); + mIv_guard.setVisibility(View.GONE); + mIv_guard1.setVisibility(View.VISIBLE); + } + + guardAnimation = AnimUtils.startGuardAnimation(this, mIv_guard); +// mGuardDialog = new GuardDialog(this); +// mGuardDialog.setData(mGuard_price, mDiff_num + ""); +// +// mGuardDialog.setOnClickGuard(new GuardDialog.OnClickGuard() { +// @Override +// public void onClickGuard(int count, String price) { +// if (null != mGuardDialog) { +// mGuardDialog.dismiss(); +// } +// guard(mToUid, mRoomId, count, price); +// } +// }); +// } else { +// mIv_guard.setVisibility(View.GONE); +// } + + mBackground.setImageURI(StrU.getResourcePath(mAvatar, this)); + + mStartPhoto.setImageURI(StrU.getResourcePath(mAvatar, this)); + mStartName.setText(mNickName); + mDialogHeight = UiUtils.dip2px(AgoraWithFUVideoActivity.this, 288); + + if (SPUtils.getInt(AgoraWithFUVideoActivity.this, ConsUser.TYPE) == 2) { //特殊账号不显示价格 + mStartCost.setVisibility(View.GONE); + } else { + mStartCost.setVisibility(View.VISIBLE); + if (callType == 0) { + if (UserManager.getUserInfo().getGender() == 2) { + mStartCost.setText("本次视频消耗" + mPrice + "金币/分钟"); + } else { + mStartCost.setText("本次视频收益" + mPrice + "金币/分钟"); + } + } else { + if (UserManager.getUserInfo().getGender() == 2) { + mStartCost.setText("本次语音通话消耗" + mPrice + "金币/分钟"); + } else { + mStartCost.setText("本次语音通话收益" + mPrice + "金币/分钟"); + } + } + } + Drawable windowBackground = getWindow().getDecorView().getBackground(); + blurView.setupWith(target) + .setFrameClearDrawable(windowBackground) + .setBlurRadius(60f); + blurView1.setupWith(target1) + .setFrameClearDrawable(windowBackground) + .setBlurRadius(60f); + mCallerCancelButton.setOnClickListener(this); + mCalleeCancelButton.setOnClickListener(this); + mCalleeAnswerButton.setOnClickListener(this); + mVideoEnd.setOnClickListener(this); + mVideoCameraSwitcher.setOnClickListener(this); + mVideoSwitcher.setOnClickListener(this); +// mLocalVideoView.setOnClickListener(this); +// mRemoteVideoView.setOnClickListener(this); + mVideoMuteSwitcher.setOnClickListener(this); + videoOpenMic.setOnClickListener(this); + mVideoGift.setOnClickListener(this); + mVideoChat.setOnClickListener(this); + mIvVideoBeauty.setOnClickListener(this); + mEditSubmitButton.setOnClickListener(this); +// mRlDealLayout.setOnClickListener(this); +// mRlVideoLayout.setOnClickListener(this); + mVideoFinish.setOnClickListener(this); + mLlRemainTime.setOnClickListener(this); + mIv_guard.setOnClickListener(this); + mIv_guard1.setOnClickListener(this); + lin_voice_btn.setOnClickListener(this); + tv_voice_mic.setOnClickListener(this); + tv_voice_cancel.setOnClickListener(this); + tv_voice_spk.setOnClickListener(this); + tv_hangup.setOnClickListener(this); + + if (bean != null) { + rl_video.setVisibility(View.VISIBLE); + mRlVideoStartLayout.setVisibility(View.GONE); + if (!StrU.isEmpty(bean.getAvatar_url())) { + iv_user_avatar.setImageURI(StrU.getResourcePath(bean.getAvatar_url(), this)); + } + tv_nick_name.setText(bean.getNickname()); + tv_age.setText(bean.getAge() + ""); + if (bean.isIs_follow()) { + iv_follow.setImageResource(R.drawable.ic_play_follow); + } else { + iv_follow.setImageResource(R.drawable.ic_play_unfollow); + } + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "initView: bean.getVideo_url()-------->" + bean.getVideo_url()); + if (!StrU.isEmpty(bean.getVideo_url())) { + iv_avatar.setVisibility(View.GONE); + iv_avatar.setImageResource(0); + video_view.setVisibility(View.VISIBLE); + player = new SimpleExoPlayer.Builder(this, new DefaultRenderersFactory(this).setEnableDecoderFallback(true)).build(); + video_view.setPlayer(player); + player.setMediaSource(new DefaultExoConfig(this).createMediaSource(Uri.parse(StrU.getResourcePath(bean.getVideo_url(), this)))); + player.prepare(); + if (player.getAudioComponent() != null) { + player.getAudioComponent().setVolume(0); + } + player.setRepeatMode(Player.REPEAT_MODE_ONE); + player.setPlayWhenReady(true); + } else { + video_view.setVisibility(View.GONE); + iv_avatar.setVisibility(View.VISIBLE); + GlideUtils.showImage(this, iv_avatar, bean.getAvatar_url()); + } + } else { + rl_video.setVisibility(View.GONE); + } + + mChatEdit.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable s) { + String str = s.toString(); + if (!TextUtils.isEmpty(str)) { + if (str.length() < 200) { + chatText = str.trim(); + } + } + } + }); + + mVideoChatList.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent event) { + touchView(event); + return false; + } + }); + mRemoteVideoView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent event) { + touchView(event); + return true; + } + }); + + mLocalVideoView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent event) { + if (MotionEvent.ACTION_DOWN == event.getAction()) { + localX1 = event.getX(); + localClickCount++;//按下 + hideKeyBoard(); + if (null != mRlBeautyContainer) { + if (mRlBeautyContainer.getVisibility() == View.VISIBLE) { + mRlBeautyContainer.setVisibility(View.GONE); + mRlDealLayout.setVisibility(View.VISIBLE); + mLlShowTime.setVisibility(View.VISIBLE); + wxContainer.setVisibility(isShowWechat ? View.VISIBLE : View.GONE); + } + } + swapLocalRemoteDisplayNew(isLocalMain); + isLocalMain = !isLocalMain; + + } + + if (MotionEvent.ACTION_UP == event.getAction()) { + localX2 = event.getX(); + if (localX1 - localX2 > 100) { //向左滑 + if (isScreen) { //在屏幕内,移除屏幕 + isScreen = false; + ObjectAnimator.ofFloat(mRlDealLayout, "translationX", 0F, -mWidth).setDuration(500).start(); + ObjectAnimator.ofFloat(mLlShowTime, "translationX", 0F, -mWidth).setDuration(500).start(); + if (isShowWechat) { + ObjectAnimator.ofFloat(wxContainer, "translationX", 0F, -mWidth).setDuration(500).start(); + } + } + } else if (localX2 - localX1 > 100) { + if (!isScreen) { //不在屏幕内,则回到屏幕 + isScreen = true; + ObjectAnimator.ofFloat(mRlDealLayout, "translationX", -mWidth, 0F).setDuration(500).start(); + ObjectAnimator.ofFloat(mLlShowTime, "translationX", -mWidth, 0F).setDuration(500).start(); + if (isShowWechat) { + ObjectAnimator.ofFloat(wxContainer, "translationX", -mWidth, 0F).setDuration(500).start(); + } + } + } + } + return true; + } + }); + + mVideoChatAdapter = new VideoAdapter(this); + mVideoChatAdapter.setChatBeanList(mChatBeanList); + mVideoChatList.setAdapter(mVideoChatAdapter); + mVideoChatList.dimissEmptyView(); + mVideoChatList.removeFooterView(mVideoChatList.getLoadMoreView()); + SoftKeyBoardListener.setListener(this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() { + @Override + public void keyBoardShow(int height) { + mChatEdit.requestFocus(); + mLlEdit.setVisibility(View.VISIBLE); +// ObjectAnimator.ofFloat(mLlEdit, "translationY", 0F, -height).setDuration(0).start(); +// ObjectAnimator.ofFloat(mRlDealLayout, "translationY", 0F, -(height + 150)).setDuration(0).start(); + } + + @Override + public void keyBoardHide(int height) { + mLlEdit.setVisibility(View.GONE); +// ObjectAnimator.ofFloat(mLlEdit, "translationY", -height, 0F).setDuration(0).start(); +// ObjectAnimator.ofFloat(mRlDealLayout, "translationY", -(height + 150), 0F).setDuration(0).start(); + } + }); + } + + private void touchView(MotionEvent event) { + if (MotionEvent.ACTION_DOWN == event.getAction()) {//按下 + remoteX1 = event.getX(); + clickCount++; + hideKeyBoard(); + if (null != mRlBeautyContainer) { + if (mRlBeautyContainer.getVisibility() == View.VISIBLE) { + mRlBeautyContainer.setVisibility(View.GONE); + mRlDealLayout.setVisibility(View.VISIBLE); + mLlShowTime.setVisibility(View.VISIBLE); + wxContainer.setVisibility(isShowWechat ? View.VISIBLE : View.GONE); + } + } + if (1 == clickCount) { + firstClick = System.currentTimeMillis();//记录第一次点击时间 + } else if (2 == clickCount) { + secondClick = System.currentTimeMillis();//记录第二次点击时间 + if (secondClick - firstClick < totalTime) {//判断二次点击时间间隔是否在设定的间隔时间之内 + if (isScreen) { //在屏幕内,移除屏幕 + isScreen = false; + ObjectAnimator.ofFloat(mRlDealLayout, "translationX", 0F, -mWidth).setDuration(500).start(); + ObjectAnimator.ofFloat(mLlShowTime, "translationX", 0F, -mWidth).setDuration(500).start(); + if (isShowWechat) { + ObjectAnimator.ofFloat(wxContainer, "translationX", 0F, -mWidth).setDuration(500).start(); + } + } else { + isScreen = true; + ObjectAnimator.ofFloat(mRlDealLayout, "translationX", -mWidth, -0F).setDuration(500).start(); + ObjectAnimator.ofFloat(mLlShowTime, "translationX", -mWidth, -0F).setDuration(500).start(); + if (isShowWechat) { + ObjectAnimator.ofFloat(wxContainer, "translationX", -mWidth, -0F).setDuration(500).start(); + } + } + clickCount = 0; + firstClick = 0; + } else { + firstClick = secondClick; + clickCount = 1; + } + secondClick = 0; + } + } + if (MotionEvent.ACTION_UP == event.getAction()) { + remoteX2 = event.getX(); + if (null != mRlBeautyContainer && (Math.abs(remoteX2 - remoteX1) < 100)) { + if (mRlBeautyContainer.getVisibility() == View.VISIBLE) { + mRlBeautyContainer.setVisibility(View.GONE); +// view_bg_beauty_view.setVisibility(View.GONE); + } + } + if (remoteX1 - remoteX2 > 100) { //向左滑 + if (isScreen) { + isScreen = false; + ObjectAnimator.ofFloat(mRlDealLayout, "translationX", 0F, -mWidth).setDuration(500).start(); + ObjectAnimator.ofFloat(mLlShowTime, "translationX", 0F, -mWidth).setDuration(500).start(); + if (isShowWechat) { + ObjectAnimator.ofFloat(wxContainer, "translationX", 0F, -mWidth).setDuration(500).start(); + } + } + } else if (remoteX2 - remoteX1 > 100) { + if (!isScreen) { + isScreen = true; + ObjectAnimator.ofFloat(mRlDealLayout, "translationX", -mWidth, 0F).setDuration(500).start(); + ObjectAnimator.ofFloat(mLlShowTime, "translationX", -mWidth, 0F).setDuration(500).start(); + if (isShowWechat) { + ObjectAnimator.ofFloat(wxContainer, "translationX", -mWidth, 0F).setDuration(500).start(); + } + } + } + } + } + + private void getGuardInfo() { + NewsManager.getGuardInfo(this, mToUid + "", new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + mGuardDialog = new GuardDialog(AgoraWithFUVideoActivity.this); + mGuardDialog.setData(result.getGuard().getGuard_price(), result.getGuard().getFirst_diff_num() + "", mAvatar, result.getGuard().getAvatar()); + mGuardDialog.setOnClickGuard(new GuardDialog.OnClickGuard() { + @Override + public void onClickGuard(int count, String price) { + if (null != mGuardDialog) { + mGuardDialog.dismiss(); + } + guard(mToUid, mRoomId, count, price); + } + }); + mGuardDialog.show(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "守护信息获取失败: " + tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "守护信息失败: " + e.getMessage()); + } + }); + } + + /** + * 送守护符 + * + * @param toUid + * @param roomId + * @param count + * @param price + */ + private void guard(int toUid, int roomId, int count, String price) { + MainManager.postVideoGuard(this, toUid, roomId, count, price, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, VideoGuardBean result, String message) { +// if (null != mGuardDialog) { +// mGuardDialog.setData(result.getGuard_price(), result.getDiff_num() + ""); +// +// } + MaleToast.showMessage(activity, "守护成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + mGuardDialog.dismiss(); + BaseApplication.getInstance().getRechargeInfo(activity, 0); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showFailureMsg(activity, "守护失败"); + } + }); + } + + private void hideKeyBoard() { + InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mChatEdit.getWindowToken(), 0); + } + + private void connectSocket() { + if (!TextUtils.isEmpty(mSocketUrl)) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "connectSocket: mSocketUrl----------->" + mSocketUrl); + MainManager.createWebSocket(new CaiWebSocket.WebSocketListener() { + @Override + public void onOpen() { + if (heartTimer == null && heartTask == null) { + heartTimer = new Timer(); + heartTask = new TimerTask() { + @Override + public void run() { + Message message = new Message(); + message.what = 0; + mHandler.sendMessage(message); + } + }; + heartTimer.schedule(heartTask, 0, 30000); //每隔30秒使用handler发送一下消息,也就是每隔一秒执行一次,一直重复执行 + } + } + + @Override + public void onMessage(String text) { + final Gson gson = new Gson(); + text = text.replaceAll("@@", ""); + if (BuildConfig.IS_DEV) Log.i(TAG, "onMessage: --------->" + text); + final WebSocketResultBean bean = gson.fromJson(text, WebSocketResultBean.class); + switch (bean.getMethod()) { + case Constant.REQUEST: //主叫者连接成功 + mStartCountDownTimeText.setVisibility(View.VISIBLE); + mStartHint.setVisibility(View.VISIBLE); + mStartHint1.setVisibility(View.VISIBLE); + mCallerCancelButton.setVisibility(View.VISIBLE); + mCalleeCancelButton.setVisibility(View.GONE); + mCalleeAnswerButton.setVisibility(View.GONE); + mVideoFinish.setVisibility(View.GONE); + if (null != mStartCountDownTimer) { + mStartCountDownTimer.start(); + } + + //发送给被叫者 + sendCustomNotificationCall(); + + new Thread(new Runnable() { + @Override + public void run() { + if (null != mMediaPlayer) { + mMediaPlayer.start(); + } + } + }).start(); + mStartHint.setText("正在呼叫中..."); + break; + case Constant.RESPONSE: //被叫者连接成功 + new Thread(new Runnable() { + @Override + public void run() { + if (null != mMediaPlayer) { + mMediaPlayer.start(); + } + } + }).start(); + mStartCountDownTimeText.setVisibility(View.VISIBLE); + mStartHint.setVisibility(View.GONE); + mCallerCancelButton.setVisibility(View.GONE); + mCalleeCancelButton.setVisibility(View.VISIBLE); + mCalleeAnswerButton.setVisibility(View.VISIBLE); + mVideoFinish.setVisibility(View.GONE); + if (null != mStartCountDownTimer) { + mStartCountDownTimer.start(); + } + mStartHint1.setVisibility(View.VISIBLE); + + break; + case Constant.UPDATETIP: //主叫者更新提示信息 + final String upText = text; + WebSocketResultBean tipBean = gson.fromJson(upText, + new TypeToken>() { + }.getType()); + mStartHint.setText(tipBean.getData().getTip()); + mStartHint1.setVisibility(View.VISIBLE); + break; + case Constant.STARTVIDEO: //开始视频 + isStarted = true; + mVideoFinish.setVisibility(View.GONE); + setPlayView(); + + if (UserManager.getUserInfo().getGender() != 2) { + isLocalMain = true; + mVideoSwitcher.setVisibility(View.GONE); + } +// refreshWx(mToUid + ""); + JSONObject jsonObject = null; + mRoomDuration = 0; + try { + jsonObject = new JSONObject(text); + JSONObject jsonObject1 = jsonObject.getJSONObject("data"); + mRoomDuration = jsonObject1.getInt("duration"); + } catch (JSONException e) { + e.printStackTrace(); + } + + initUIAndEvent(); + + startCallingTimer(); + if (null != mStartCountDownTimer) { + mStartCountDownTimer.cancel(); + } + break; + case Constant.HANGUP: //挂断 + leave(); + final String finalText = text; + runOnUiThread(new Runnable() { + @Override + public void run() { + WebSocketResultBean hangUpBean = gson.fromJson(finalText, + new TypeToken>() { + }.getType()); + int type = hangUpBean.getData().getType(); + //1。主动取消 2。拒绝 3.超时 4.被叫者挂断 5.主叫者挂断 6.费用不足 7.其他异常 10.主叫者违规 11.被叫者违规 + switch (type) { + case 1: + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "已取消"); + finish(); + break; + case 2: + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "已拒绝"); + finish(); + break; + case 3: + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "超时无应答"); + finish(); + break; + case 4: + if (isCaller) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "对方已挂断"); + } else { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "通话已结束"); + } + + toVideoFinish(); + break; + case 5: + if (isCaller) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "通话已结束"); + } else { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "对方已挂断"); + } + + toVideoFinish(); + break; + case 6: + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "费用不足已断开"); + toVideoFinish(); + break; + case 7: +// MaleToast.showMessage(AgoraWithFUVideoActivity.this, "其他异常"); + finish(); + break; + case 10: + if (isCaller) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "本次视频违规,请遵守平台相关规则"); + } else { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "因对方视频通话违规系统挂断,请严格遵守平台相关规定。"); + } + toVideoFinish(); + break; + case 11: + if (isCaller) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "因对方视频通话违规系统挂断,请严格遵守平台相关规定。"); + toVideoFinish(); + } else { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "本次视频违规,请遵守平台相关规则"); + } + break; + } + + } + + }); +// MainManager.closeWebSocket(); + finish(); + break; + case Constant.NOTICE: //通知 + WebSocketResultBean noticeBean = gson.fromJson(text, + new TypeToken>() { + }.getType()); + + if (noticeBean.getData() != null) { + switch (noticeBean.getData().getType()) { + case 3: + Gson gson1 = new Gson(); + NoticeGiftBean noticeGiftBean = gson1.fromJson(noticeBean.getData().getContent(), + NoticeGiftBean.class); + if (mSvgaDialog == null) { + mSvgaDialog = new SvgaDialog(AgoraWithFUVideoActivity.this); + } + mSvgaDialog.show(noticeGiftBean.getGift_effect()); + break; + } + } + + WebSocketChatBean chatBean = new WebSocketChatBean(); + chatBean.setData(noticeBean.getData()); + mChatBeanList.add(chatBean); +// if (mChatBeanList.size() > 5) { +// mChatBeanList.remove(0); +// } + mVideoChatAdapter.notifyDataSetChanged(); + mVideoChatList.smoothScrollToPosition(mVideoChatAdapter.getCount() - 1); + if (StrU.equals("2", noticeBean.getData().getLink_type()) && "rechargeCoin".equals(noticeBean.getData().getLink_url())) { + BaseApplication.getInstance().getRechargeInfo(AgoraWithFUVideoActivity.this, 0); + } + break; + case Constant.HEARTBEAT: //心跳检测 + count = 40; + if (countTimer == null && countTask == null) { + countTimer = new Timer(); + countTask = new TimerTask() { + @Override + public void run() { + Message message = new Message(); + message.what = 1; + mHandler.sendMessage(message); + } + }; + countTimer.schedule(countTask, 0, 1000); + } + break; + case Constant.CANCALLTIME: //剩余时长 + final String timeText = text; + WebSocketResultBean timeRemainBean = gson.fromJson(timeText, + new TypeToken>() { + }.getType()); + + mLlRemainTime.setVisibility(View.VISIBLE); + int time = timeRemainBean.getData().getTip(); + String hh = new DecimalFormat("00").format(time / 3600); + String mm = new DecimalFormat("00").format(time % 3600 / 60); + String ss = new DecimalFormat("00").format(time % 60); + String timeFormat = new String(hh + ":" + mm + ":" + ss); + mTvRemainTime.setText(timeFormat); + if (time / 60 <= 0) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (isFirstShow) { + BaseApplication.getInstance().getRechargeInfo(AgoraWithFUVideoActivity.this, 0); + isFirstShow = false; + } + } + }); + } + //startRemainTimeTimer(); + break; + case Constant.PROMPTMANRECHARGE://显示充值弹窗 + if (UserManager.getUserInfo().getGender() == 2) { + BaseApplication.getInstance().getRechargeInfo(AgoraWithFUVideoActivity.this, 0); + } else { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, bean.getMessage()); + } + break; + case Constant.PORN_MASK: + isShowBlur = true; + if (isLocalMain) { + blurView.setVisibility(View.VISIBLE); + } else { + blurView1.setVisibility(View.VISIBLE); + } + if (maskTimer == null && maskTask == null) { + maskTimer = new Timer(); + maskTask = new TimerTask() { + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + isShowBlur = false; + blurView.setVisibility(View.GONE); + blurView1.setVisibility(View.GONE); + maskTimer.cancel(); + maskTimer = null; + maskTask.cancel(); + maskTask = null; + } + }); + } + }; + maskTimer.schedule(maskTask, maskSecond * 1000L); + } + break; + } + } + + @Override + public void onClosing() { +// Log.d("nail","onClosing"); + } + + @Override + public void onClosed() { +// Log.d("nail","onClosed"); +// finish(); + } + + @Override + public void onFailure(String reason) { + if (null != mReHandler) { + mReHandler.postDelayed(new Runnable() { + @Override + public void run() { + MainManager.reconnectWebSocket(mSocketUrl + "&reconnect=1"); + } + }, 1000); + } + } + }, mSocketUrl + "&reconnect=0", this); + } + } + + //音视频接通后界面调整 + private void setPlayView() { + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + } + if (player != null) { + player.stop(); + } + if (callType == 0) { + rl_video.setVisibility(View.GONE); + mRlVideoStartLayout.setVisibility(View.GONE); + mRlVideoLayout.setVisibility(View.VISIBLE); + mRemoteVideoView.setVisibility(View.VISIBLE); + mLocalVideoView.setVisibility(View.VISIBLE); + mRlDealLayout.setVisibility(View.VISIBLE); + video_action.setVisibility(View.VISIBLE); + mVideoChat.setVisibility(View.VISIBLE); + mIvVideoBeauty.setVisibility(View.VISIBLE); + lin_voice_btn.setVisibility(View.GONE); + mBackAndCost.setVisibility(View.VISIBLE); + tv_voice_cancel.setVisibility(View.GONE); + sp_voice_action.setVisibility(View.GONE); + } else { + mRlDealLayout.setVisibility(View.VISIBLE); + video_action.setVisibility(View.GONE); + lin_voice_btn.setVisibility(View.VISIBLE); + mVideoChat.setVisibility(View.GONE); + mIvVideoBeauty.setVisibility(View.GONE); + sp_voice_action.setVisibility(View.VISIBLE); + tv_voice_cancel.setVisibility(View.VISIBLE); + mCalleeAnswerButton.setVisibility(View.GONE); + mCallerCancelButton.setVisibility(View.GONE); + mCalleeCancelButton.setVisibility(View.GONE); + mStartHint.setVisibility(View.GONE); + mStartHint1.setVisibility(View.GONE); + mStartCountDownTimeText.setVisibility(View.GONE); + tv_voice_time.setVisibility(View.VISIBLE); + } + } + + + protected void initUIAndEvent() { + mRtcEngine.setClientRole(io.agora.rtc.Constants.CLIENT_ROLE_BROADCASTER); + mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration( + VideoEncoderConfiguration.VD_840x480, + VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_24, VideoEncoderConfiguration.STANDARD_BITRATE, + VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_ADAPTIVE)); + + // TODO: 2023/9/6 声网证书token + mRtcEngine.joinChannel("", mRoomId + "", "AgoraWithBeauty", SPUtils.getInt(AgoraWithFUVideoActivity.this, ConsUser.USER_ID)); + if (callType == 0) { + mRtcEngine.enableVideo(); + } else { + mRtcEngine.disableVideo(); + } + mRtcEngine.enableAudio(); + } + + private void initFUModule() { + if (callType == 0 && mVideoManager != null) { + mVideoManager.setCameraStateListener(new VideoCapture.VideoCaptureStateListener() { + @Override + public void onFirstCapturedFrame(int width, int height) { + Log.i(TAG, "onFirstCapturedFrame: " + width + "x" + height); + } + + @Override + public void onCameraCaptureError(int error, String msg) { + Log.i(TAG, "onCameraCaptureError: error:" + error + " " + msg); + if (mVideoManager != null) { + // When there is a camera error, the capture should + // be stopped to reset the internal states. + mVideoManager.stopCapture(); + } + } + + @Override + public void onCameraClosed() { + + } + }); + + String beautySettings = BeautySPUtils.getString("newFaceBeautySettings"); + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "initFUModule: beautySettings---------->" + beautySettings); + if (beautySettings != null && !beautySettings.isEmpty()) { + Type type = new TypeToken>() { + }.getType(); + HashMap clonedMap = new Gson().fromJson(beautySettings, type); + faceBeauty = FaceBeautySource.hashMapToFaceBeauty(clonedMap); + } + + if (faceBeauty == null) { + Log.i("美颜", "开始设置数据"); + FaceBeauty recommendFaceBeauty = new FaceBeauty(new FUBundleData(FaceBeautySource.BUNDLE_FACE_BEAUTIFICATION)); + recommendFaceBeauty.setFilterName(FaceBeautyFilterEnum.ZIRAN_1); + recommendFaceBeauty.setFilterIntensity(0.4); + /*美肤*/ + recommendFaceBeauty.setBlurType(FaceBeautyBlurTypeEnum.FineSkin); + recommendFaceBeauty.setBlurIntensity(3); // 赋值范围0-6 + recommendFaceBeauty.setColorIntensity(0.3); + recommendFaceBeauty.setRedIntensity(0.3); + recommendFaceBeauty.setSharpenIntensity(0.2); + recommendFaceBeauty.setEyeBrightIntensity(0); + recommendFaceBeauty.setToothIntensity(0); + recommendFaceBeauty.setRemovePouchIntensity(0); + recommendFaceBeauty.setRemoveLawPatternIntensity(0); + + /*美型*/ + recommendFaceBeauty.setCheekThinningIntensity(0);//瘦脸 + recommendFaceBeauty.setCheekVIntensity(0.5);//V脸 + recommendFaceBeauty.setCheekNarrowIntensity(0);//窄脸 + recommendFaceBeauty.setCheekSmallIntensity(0);//小脸 + recommendFaceBeauty.setEyeEnlargingIntensity(0.4);//大眼 + recommendFaceBeauty.setChinIntensity(0.3);//下巴 + recommendFaceBeauty.setForHeadIntensity(0.3);//额头 + recommendFaceBeauty.setNoseIntensity(0.3);//瘦鼻 + recommendFaceBeauty.setMouthIntensity(0.4);//嘴型 + recommendFaceBeauty.setCanthusIntensity(0);//开眼角 + recommendFaceBeauty.setEyeSpaceIntensity(0.5);//眼距 + recommendFaceBeauty.setEyeRotateIntensity(0.5);//眼睛角度 + recommendFaceBeauty.setLongNoseIntensity(0.5);//鼻子长度 + recommendFaceBeauty.setPhiltrumIntensity(0.5);//缩人中 + recommendFaceBeauty.setSmileIntensity(0); //微笑嘴角 + faceBeauty = recommendFaceBeauty; + } + FaceBeautySource.setCustomFaceBeauty(faceBeauty); + preprocessor = (PreprocessorFaceUnity) mVideoManager.getPreprocessor(); + FaceUnityView faceUnityView = findViewById(R.id.fu_view); + faceUnityView.getFaceBeautyControlView().setListener(new FaceBeautyControlView.ViewDownListener() { + @Override + public void ViewDown() { + if (mRlBeautyContainer.getVisibility() == View.VISIBLE) { + mRlBeautyContainer.setVisibility(View.GONE); + mRlDealLayout.setVisibility(View.VISIBLE); + mLlShowTime.setVisibility(View.VISIBLE); + wxContainer.setVisibility(isShowWechat ? View.VISIBLE : View.GONE); + } + } + }); + mFaceUnityDataFactory = new FaceUnityDataFactory(0); + faceUnityView.bindDataFactory(mFaceUnityDataFactory); + + mVideoManager.setPictureSize(840, 480); + mVideoManager.setFrameRate(24); + mVideoManager.setFacing(io.agora.capture.video.camera.Constant.CAMERA_FACING_FRONT); + mVideoManager.setLocalPreviewMirror(io.agora.capture.video.camera.Constant.MIRROR_MODE_AUTO); + localVideoNew = new AgoraTextureView(this); + mLocalVideoView.addView(localVideoNew); + mVideoManager.setLocalPreview(localVideoNew); + + preprocessor.setSurfaceListener(new PreprocessorFaceUnity.SurfaceViewListener() { + @Override + public void onSurfaceCreated() { + mFaceUnityDataFactory.bindCurrentRenderer(); + } + + @Override + public void onSurfaceDestroyed() { + mFURenderer.release(); + } + }); + } + mRtcEngine.setVideoSource(new RtcVideoConsumer()); + mRtcEngine.setEnableSpeakerphone(isOpenSpk); + // 获取 AudioManager 设置默认通话音量 + AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + if (audioManager != null) { + // 获取最大媒体音量 + int maxMusicVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + int maxCallVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); + // 目标音量,比如设置为 50% + int targetMusicVolume = maxMusicVolume / 2; + int targetCallVolume = maxCallVolume / 2; + if (audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) < targetMusicVolume) { + // 设置媒体音量 (第三个参数可传 FLAG_SHOW_UI 显示系统音量条) + audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, targetMusicVolume, 0); + } + if (audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL) < targetCallVolume) { + // 设置媒体音量 (第三个参数可传 FLAG_SHOW_UI 显示系统音量条) + audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, targetCallVolume, 0); + } + } + } + + @Override + public void onSensorChanged(SensorEvent event) { + if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + if (Math.abs(x) > 3 || Math.abs(y) > 3) { + if (Math.abs(x) > Math.abs(y)) { + mFURenderer.setDeviceOrientation(x > 0 ? 0 : 180); + } else { + mFURenderer.setDeviceOrientation(y > 0 ? 90 : 270); + } + } + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + /** + * 跳转到账单界面 + */ + private void toVideoFinish() { + //3期 男用户通话结束页面修改 + if (UserManager.getUserInfo().getGender() == 2) { + Intent intent = new Intent(AgoraWithFUVideoActivity.this, ManVideoFinishActivity.class); + intent.putExtra("roomId", mRoomId); + intent.putExtra("nickName", mNickName); + intent.putExtra("avatar", mAvatar); + intent.putExtra("uid", mToUid); + intent.putExtra("callType", callType); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + } else { + Intent intent = new Intent(AgoraWithFUVideoActivity.this, VideoFinishActivity.class); + intent.putExtra("roomId", mRoomId); + intent.putExtra("isCaller", false); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + } + finishActivity(); + } + + /** + * 通话计时 + */ + private void startCallingTimer() { + mBaseTime = SystemClock.elapsedRealtime(); + mCallingTimer = new Timer(); + mCallingTimerTask = new TimerTask() { + @Override + public void run() { + int time = (int) ((SystemClock.elapsedRealtime() - mBaseTime) / 1000) + mRoomDuration; + String hh = new DecimalFormat("00").format(time / 3600); + String mm = new DecimalFormat("00").format(time % 3600 / 60); + String ss = new DecimalFormat("00").format(time % 60); + String timeFormat = new String(hh + ":" + mm + ":" + ss); + Message msg = new Message(); + msg.what = 4; + msg.obj = timeFormat; + mHandler.sendMessage(msg); +// mDuration = (time - mBaseTime) / 1000; + if (callType == 0) { + shootScreen(time); + } + } + }; + mCallingTimer.scheduleAtFixedRate(mCallingTimerTask, 0, 1000); + } + + private void shootScreen(int time) { + if (!needChatShoot) { + return; + } + if (isOpenDetection == 1 && mPornCheckV2List != null && mPornCheckV2List.size() > 0) { + PornCheckBeanV2.PornCheckV2 pornCheckV2 = mPornCheckV2List.get(0); + long start = pornCheckV2.getStart(); + long end = pornCheckV2.getEnd(); + if (time >= start && time <= end) { + if (time == end) { + mPornCheckV2List.remove(0); + } + if (detectionTime != 0) { + if (time != 0 && (time % detectionTime == 0)) { + if (UserManager.getUserInfo().isWomen()) { //主叫者截取远程视频,则为被叫者图片 + if (null != localVideoNew) { + final Bitmap bitmap = localVideoNew.getBitmap(); + if (null != bitmap) { + final String base64 = Bitmap2StrByBase64(bitmap); + if (!TextUtils.isEmpty(base64)) { + runOnUiThread(new Runnable() { + @Override + public void run() { + MainManager.postChatShootTo(AgoraWithFUVideoActivity.this, mRoomId, base64, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, ChatShootBean result, String message) { + int is_upload = result.getIs_upload(); + needChatShoot = is_upload == 1; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + }); + } + } + } + } else { //被叫者截取远程视频,则为主叫者图片 + if (!mMuted && check_from_user == 1) { + if (null != localVideoNew) { + final Bitmap bitmap = localVideoNew.getBitmap(); + if (null != bitmap) { + final String base64 = Bitmap2StrByBase64(bitmap); + if (!TextUtils.isEmpty(base64)) { + runOnUiThread(new Runnable() { + @Override + public void run() { + MainManager.postChatShootFrom(AgoraWithFUVideoActivity.this, mRoomId, base64, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, ChatShootBean result, String message) { + int is_upload = result.getIs_upload(); + needChatShoot = is_upload == 1; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + }); + } + } + } + } + } + } + } + } + } + } + + /** + * 发送给被叫者 + */ + private void sendCustomNotificationCall() { + if (!isRisk) { + VideoRequestBean requestBean = new VideoRequestBean(); + requestBean.setId(11); + requestBean.setData(new VideoRequestDataBean()); +// requestBean.getData().setCallTime((System.currentTimeMillis() / 1000) + ""); + requestBean.getData().setCallTime((TimeZoneUtils.getTime() / 1000) + ""); + requestBean.getData().setRoomid(mRoomId + ""); + Gson gsonNotification = new Gson(); + String content = gsonNotification.toJson(requestBean); + ChatManager.getInstance().sendVideoRequest(content, mToUid + ""); + } + } + + private void stopTimer() { + if (null != heartTimer) { + heartTimer.cancel(); + heartTimer = null; + } + + if (null != heartTask) { + heartTask.cancel(); + heartTask = null; + } + + if (null != countTimer) { + countTimer.cancel(); + countTimer = null; + } + + if (null != countTask) { + countTask.cancel(); + countTask = null; + } + if (null != maskTimer) { + maskTimer.cancel(); + maskTimer = null; + } + if (null != maskTask) { + maskTask.cancel(); + maskTask = null; + } + } + + /** + * 停止视频时长的计算 + */ + private void stopAdvisory() { + if (null != mCallingTimer) { + mCallingTimer.cancel(); + mCallingTimer = null; + } + + if (null != mCallingTimerTask) { + mCallingTimerTask.cancel(); + mCallingTimerTask = null; + } + + if (null != mRemainTimer) { + mRemainTimer.cancel(); + mRemainTimer = null; + } + + if (null != mRemainTimerTask) { + mRemainTimerTask.cancel(); + mRemainTimerTask = null; + } + + if (null != mReHandler) { + mReHandler.removeCallbacksAndMessages(null); + mReHandler = null; + } + } + + //视频接听倒计时 + private CountDownTimer mStartCountDownTimer = new CountDownTimer(180000, 1000) { + @Override + public void onTick(long l) { + mStartCountDownTimeText.setText((l / 1000) + ""); + } + + @Override + public void onFinish() { + mStartCountDownTimeText.setVisibility(View.GONE); + mStartHint.setVisibility(View.GONE); + mStartHint1.setVisibility(View.GONE); + } + }; + + //监听到未读数后展示 + public void onEventMainThread(EventBusGiftMessage event) { +// refreshWx(mToUid + ""); + } + + @Override + public void onDestroy() { + EventBus.getDefault().unregister(this); + BaseApplication.getInstance().setVideo(false); + BaseApplication.getInstance().setDismissDialog(); + if (preprocessor != null) { + preprocessor.setRenderEnable(false); + preprocessor.releaseFURender(); + } + if (mRtcEngine != null) { + // 停止本地视频预览 +// mRtcEngine.stopPreview(); + // 离开频道 + mRtcEngine.leaveChannel(); + mRtcEngine = null; + // 销毁引擎 + RtcEngine.destroy(); + } + mSensorManager.unregisterListener(this); +// if (mMediaPlayer != null) { +// mMediaPlayer.stop(); +// } + + if (null != mStartCountDownTimer) { + mStartCountDownTimer.cancel(); + mStartCountDownTimer = null; + } + stopTimer(); + stopAdvisory(); + + getContentResolver().unregisterContentObserver(mPhotoObserver); + getContentResolver().unregisterContentObserver(mVideoObserver); + super.onDestroy(); + if (mIv_guard != null) { + if (guardAnimation != null) { + guardAnimation.release(); + } +// if (mIv_guard.getBackground()==null){ +// return; +// } +// AnimationDrawable drawable = (AnimationDrawable)mIv_guard.getBackground(); +// drawable.stop(); + mIv_guard.setBackground(null); + } + } + + /** + * 离开视频通话 + */ + private void leave() { + if (BaseApplication.getInstance().getTopActivity() instanceof QuickRechargeActivity) { + BaseApplication.getInstance().getTopActivity().finish(); + } + BaseApplication.getInstance().setVideo(false); + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + } + if (null != mStartCountDownTimer) { + mStartCountDownTimer.cancel(); + mStartCountDownTimer = null; + } + saveBeauty(); + stopTimer(); + stopAdvisory(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (null != mRlBeautyContainer) { + if (mRlBeautyContainer.getVisibility() == View.VISIBLE) { + mRlBeautyContainer.setVisibility(View.GONE); + mRlDealLayout.setVisibility(View.VISIBLE); + mLlShowTime.setVisibility(View.VISIBLE); + wxContainer.setVisibility(isShowWechat ? View.VISIBLE : View.GONE); + } else { + if (isStarted) { + showLeaveMessage(); + } else { + if (isCaller) { + callerCancelVideo(); + } else { + calleeRefuseVideo(); + } + } + } + } else { + if (isStarted) { + showLeaveMessage(); + } else { + if (isCaller) { + callerCancelVideo(); + } else { + calleeRefuseVideo(); + } + } + } + +// if (isStarted) { +// showLeaveMessage(); +// } else { +// if (isCaller) { +// callerCancelVideo(); +// } else { +// calleeRefuseVideo(); +// } +// } + + return true; + } + return super.onKeyDown(keyCode, event); + } + + /** + * 挂断弹出框 + */ + public void showLeaveMessage() { + hangUpDialog = new HangUpDialog(this, new HangUpDialog.OnHangUpListener() { + @Override + public void onHangUp() { + hangUpVideo(); + } + }); + hangUpDialog.show(); +// +// mMessageDialog = new BaseMessageDialog.Builder(this).setMessage("是否挂断?") +// .setCancelable(true) +// .setPositiveButtonListener(new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialogInterface, int i) { +// hangUpVideo(); +// mMessageDialog.dismiss(); +// } +// }).setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialogInterface, int i) { +// mMessageDialog.dismiss(); +// } +// }).build(); +// +// mMessageDialog.show(); + } + + /** + * 弹出赠送礼物的框 + */ + private void getGiftData() { + MainManager.getGiftBeans(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + mGiftDialog = new BottomGiftDialog(AgoraWithFUVideoActivity.this, + R.style.SelectiveDialog); + + mGiftDialog.setGiftListBean(result); + mGiftDialog.setOnGiftItemClickedListener(new BottomGiftDialog.OnGiftItemClickedListener() { + @Override + public void onGiftClicked(final DialogGiftBean bean) { + if (null != bean) { + mGiftDialog.dismiss(); + sendGift(bean.getId()); + } + } + + @Override + public void onWalletClicked() { + if (UserManager.getUserInfo().getGender() == 2) { + BaseApplication.getInstance().getRechargeInfo(activity, 0); + } else { + Intent intent = new Intent(AgoraWithFUVideoActivity.this, CaibeiRechargeActivity.class); + startActivity(intent); + } + } + }); + + mGiftDialog.setOnShowListener(new DialogInterface.OnShowListener() { + @Override + public void onShow(DialogInterface dialogInterface) { + hideKeyBoard(); + + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + ObjectAnimator.ofFloat(mRlDealLayout, "translationY", 0F, -mDialogHeight).setDuration(0).start(); + } + }, 100); + + } + }); + + mGiftDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + ObjectAnimator.ofFloat(mRlDealLayout, "translationY", -mDialogHeight, -0F).setDuration(0).start(); + } + }); + + mGiftDialog.show(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + if (view == mCallerCancelButton || view == tv_hangup) { + HangUpDialog hangUpDialog = new HangUpDialog(this, new HangUpDialog.OnHangUpListener() { + @Override + public void onHangUp() { + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + } + //主叫者取消拨打 + callerCancelVideo(); + } + }); + hangUpDialog.show(); + } else if (view == mCalleeCancelButton) { + /* // 测试未完成 NotificationManager systemService = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + systemService.cancel(mCallID);*/ + HangUpDialog hangUpDialog = new HangUpDialog(this, new HangUpDialog.OnHangUpListener() { + @Override + public void onHangUp() { + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + } + //被叫者取消拨打 + calleeRefuseVideo(); + } + }); + hangUpDialog.show(); + } else if (view == mCalleeAnswerButton) { + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + } + //被叫者接听 + calleeAgreeVideo(); + } else if (view == mVideoEnd) { + showLeaveMessage(); + } else if (view == mVideoCameraSwitcher) { + //视频前后摄像头切换 + preprocessor.skipFrame(); + onCameraChangeRequested(); + if (isCameraSwitch) { + mVideoCameraSwitcher.setImageResource(R.drawable.ic_video_photo); + } else { + mVideoCameraSwitcher.setImageResource(R.drawable.ic_video_photo); + } + isCameraSwitch = !isCameraSwitch; + + } else if (view == mVideoSwitcher) { //关闭或打开视频 + videoOn = !videoOn; + muteVideoNew(); + } else if (view == mVideoMuteSwitcher) { + isOpenSpk = !isOpenSpk; + mRtcEngine.setEnableSpeakerphone(isOpenSpk); + if (isOpenSpk) { + mVideoMuteSwitcher.setImageResource(R.drawable.ic_video_sound1); + } else { + mVideoMuteSwitcher.setImageResource(R.drawable.ic_video_sound0); + } +// mRtcEngine.muteLocalAudioStream(isMute); +// if (!isMute) { +// mVideoMuteSwitcher.setImageResource(R.drawable.ic_video_sound1); +//// mRtcEngine.enableAudio(); +// } else { +// mVideoMuteSwitcher.setImageResource(R.drawable.ic_video_sound0); +//// mRtcEngine.disableAudio(); +// } +// isMute = !isMute; + } else if (view == videoOpenMic) { + isOpenMic = !isOpenMic; + mRtcEngine.enableLocalAudio(isOpenMic); + if (isOpenMic) { + videoOpenMic.setImageResource(R.drawable.ic_video_mic_on); + } else { + videoOpenMic.setImageResource(R.drawable.ic_video_mic_off); + } + } else if (view == mVideoGift) { + getGiftData(); + } else if (view == mVideoChat) { + mChatEdit.requestFocus(); + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); + } else if (view == mIvVideoBeauty) { //美颜按钮 + mRlBeautyContainer.setVisibility(View.VISIBLE); + mRlDealLayout.setVisibility(View.GONE); + mLlShowTime.setVisibility(View.GONE); + wxContainer.setVisibility(View.GONE); + hideKeyBoard(); + } else if (view == mEditSubmitButton) { //发送聊天信息 + if (!TextUtils.isEmpty(chatText)) { + submitMessage(chatText); + mChatEdit.setText(""); + chatText = ""; + } + } else if (view == mVideoFinish) { //视频前socket未连接上,关闭界面 + leave(); + finish(); + } else if (view == mLlRemainTime) { //跳到媚币充值界面 + if (UserManager.getUserInfo().getGender() == 2) { + BaseApplication.getInstance().getRechargeInfo(AgoraWithFUVideoActivity.this, 0); + } else { + //女生提示男生充值 + promptManRecharge(); +// Intent intent = new Intent(this, CaibeiRechargeActivity.class); +// startActivityForResult(intent, REQUEST_RECHARGE); + } + } else if (view == mIv_guard || view == mIv_guard1) { +// if (UserManager.getUserInfo().getGender() == 2) { +// mGuardDialog.show(); + getGuardInfo(); +// } + } else if (view == tv_voice_mic) {//麦克风 + isOpenMic = !isOpenMic; + mRtcEngine.enableLocalAudio(isOpenMic); + if (isOpenMic) { + tv_voice_mic.setImageResource(R.mipmap.ic_rtc_mic_on); + } else { + tv_voice_mic.setImageResource(R.mipmap.ic_rtc_mic_off); + } + } else if (view == tv_voice_cancel) { + showLeaveMessage(); + } else if (view == tv_voice_spk) {//扬声器 + isOpenSpk = !isOpenSpk; + mRtcEngine.setEnableSpeakerphone(isOpenSpk); + if (isOpenSpk) { + tv_voice_spk.setImageResource(R.mipmap.ic_rtc_spk_on); + } else { + tv_voice_spk.setImageResource(R.mipmap.ic_rtc_spk_off); + } + } + } + + /** + * 切换摄像头 + */ + private void onCameraChangeRequested() { + preprocessor.doGLAction(() -> Log.e("ECRP", "test doGLAction thread id:" + Thread.currentThread().getId())); + mVideoManager.switchCamera(); + } + + private boolean isOpenMic = true; + private boolean isOpenSpk = true; + + /** + * 设置大视频窗口视频源 + * + * @param isLocalSource 是否本地视频源 + */ + private void setBigWindowVideoSource(boolean isLocalSource) { + if (isLocalSource) { + //大窗口展示本地视频 + localVideoNew = new AgoraTextureView(this); + mRemoteVideoView.addView(localVideoNew); + mVideoManager.setLocalPreview(localVideoNew); + blurView.setVisibility(View.GONE); + } else { + //大窗口展示远程视频 + TextureView mRemoteVideoViewNew = RtcEngine.CreateTextureView(this); + mRtcEngine.setupRemoteVideo(new VideoCanvas( + mRemoteVideoViewNew, VideoCanvas.RENDER_MODE_HIDDEN, mRemoteUid)); + mRemoteVideoView.addView(mRemoteVideoViewNew); + if (isShowBlur) { + blurView.setVisibility(View.VISIBLE); + } + } + if (mRemoteVideoView.getChildCount() > 1) { + mRemoteVideoView.removeViewAt(0); + } + } + + /** + * 设置大视频窗口视频源 + * + * @param isLocalSource 是否本地视频源 + */ + private void setSmallWindowVideoSource(boolean isLocalSource) { + if (isLocalSource) { + //小窗口展示本地视频 + localVideoNew = new AgoraTextureView(this); + mLocalVideoView.addView(localVideoNew); + mVideoManager.setLocalPreview(localVideoNew); + blurView1.setVisibility(View.GONE); + } else { + //小窗展示远程视频 + TextureView mRemoteVideoViewNew = RtcEngine.CreateTextureView(this); + mRtcEngine.setupRemoteVideo(new VideoCanvas( + mRemoteVideoViewNew, VideoCanvas.RENDER_MODE_HIDDEN, mRemoteUid)); + mLocalVideoView.addView(mRemoteVideoViewNew); + if (isShowBlur) { + blurView1.setVisibility(View.VISIBLE); + } + } + if (mLocalVideoView.getChildCount() > 1) { + mLocalVideoView.removeViewAt(0); + } + } + + private void swapLocalRemoteDisplayNew(boolean isLocalMainMode) { + if (isLocalMainMode) { + //大窗展示本地视频 + setBigWindowVideoSource(true); + //小窗展示远程视频 + setSmallWindowVideoSource(false); + } else { + //小窗口展示本地视频 + setSmallWindowVideoSource(true); + setBigWindowVideoSource(false); + } + } + + private int convert(int dp) { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); + } + + /** + * 女生提醒男生充值 + */ + private void promptManRecharge() { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(mRoomId); + requestBean.setMethod("prompt_man_recharge"); + MainManager.sendWebSocketMessage(requestBean); + } + + /** + * 被叫者接听 + */ + private void calleeAgreeVideo() { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(mRoomId); + requestBean.setMethod("agree"); + MainManager.sendWebSocketMessage(requestBean); + } + + /** + * 被叫者拒绝接听 + */ + private void calleeRefuseVideo() { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(mRoomId); + requestBean.setMethod("refuse"); + MainManager.sendWebSocketMessage(requestBean); + } + + /** + * 主叫者主动取消 + */ + private void callerCancelVideo() { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(mRoomId); + requestBean.setMethod("cancel"); + MainManager.sendWebSocketMessage(requestBean); + } + + /** + * 发送挂断视频的请求 + */ + private void hangUpVideo() { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(mRoomId); + requestBean.setMethod("hangup"); + MainManager.sendWebSocketMessage(requestBean); + } + + /** + * 发送心跳包 + */ + private void sendHeartbeat() { + WebSocketRequestBean bean = new WebSocketRequestBean<>(); + bean.setMethod("heartbeat"); + bean.setData(new RoomIdBean()); + bean.getData().setRoom_id(mRoomId); + MainManager.sendWebSocketMessage(bean); + } + + /** + * 发送文本聊天 + * + * @param message + */ + public void submitMessage(String message) { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + TextBean bean = new TextBean(); + bean.setTxt(message); + bean.setRoom_id(mRoomId); + requestBean.setMethod("message"); + requestBean.setData(bean); + MainManager.sendWebSocketMessage(requestBean); + } + + /** + * 赠送礼物的socket + * + * @param giftId + */ + private void sendGift(int giftId) { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + GiftBean bean = new GiftBean(); + bean.setGift_count(1); + bean.setGift_id(giftId + ""); + bean.setRoom_id(mRoomId); + requestBean.setMethod("gift"); + requestBean.setData(bean); + MainManager.sendWebSocketMessage(requestBean); + } + + private void sendRechargeSucceed() { + WebSocketRequestBean bean = new WebSocketRequestBean<>(); + bean.setMethod("cancalltime"); + bean.setData(new RoomIdBean()); + bean.getData().setRoom_id(mRoomId); + MainManager.sendWebSocketMessage(bean); + } + + private void setupRemoteVideo(int uid) { + TextureView mRemoteVideoViewNew = RtcEngine.CreateTextureView(this); + mRtcEngine.setupRemoteVideo(new VideoCanvas( + mRemoteVideoViewNew, VideoCanvas.RENDER_MODE_HIDDEN, uid)); + mRemoteVideoView.addView(mRemoteVideoViewNew); + mRemoteVideoView.setVisibility(View.VISIBLE); + } + + @Override + public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) { + if (callType == 0) { + runOnUiThread(new Runnable() { + @Override + public void run() { + setupRemoteVideo(uid); + } + }); + } + } + + @Override + public void onJoinChannelSuccess(String channel, int uid, int elapsed) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (UserManager.getUserInfo().getGender() == 2) { + muteVideoNew(); + } else { + setBigWindowVideoSource(true); + mRemoteVideoView.setVisibility(View.VISIBLE); + } + } + }); + } + + /** + * 摄像头开关 + */ + private void muteVideoNew() { + //取消或恢复发送本地视频流。true:停止发送视频流。false:发送视频流。 + mRtcEngine.muteLocalVideoStream(!videoOn); + if (videoOn) { + isLocalMain = true; + setSmallWindowVideoSource(true); + setBigWindowVideoSource(false); + mVideoSwitcher.setImageResource(R.drawable.ic_video_video); + mLocalVideoView.setVisibility(View.VISIBLE); + } else { + isLocalMain = false; + setBigWindowVideoSource(false); + setSmallWindowVideoSource(true); + mVideoSwitcher.setImageResource(R.drawable.ic_camera_switch_off); + mLocalVideoView.setVisibility(View.INVISIBLE); + } + mRemoteVideoView.setVisibility(View.VISIBLE); + } + + @Override + public void onUserOffline(int uid, int reason) { + runOnUiThread(this::onRemoteUserLeft); + } + + @Override + public void onUserJoined(int uid, int elapsed) { + + } + + @Override + public void onUserMuteVideo(final int uid, final boolean muted) { + this.mMuted = muted; + mRemoteUid = uid; + videoOn = !muted; + isLocalMain = !muted; + if (callType == 0) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (muted) { + //远程流停止 + Log.i(TAG, "触发 onUserMuteVideo 远程流停止"); + setBigWindowVideoSource(true); + setSmallWindowVideoSource(false); + mLocalVideoView.setVisibility(View.INVISIBLE); + } else { + Log.i(TAG, "触发 onUserMuteVideo 远程流开始"); + setSmallWindowVideoSource(true); + setBigWindowVideoSource(false); + mLocalVideoView.setVisibility(View.VISIBLE); + + } + mRemoteVideoView.setVisibility(View.VISIBLE); + } + }); + } + } + + @Override + public void onConnectionStateChanged(int state, int reason, String channelId) { + /*if (reason == Constants.CONNECTION_CHANGED_BANNED_BY_SERVER && !TextUtils.isEmpty(channelId)) { + if (channelId.equals(mRoomId + "") && !isFinishing()) { + toVideoFinish(); + finish(); + } + }*/ + } + + @Override + public void onRemoteVideoStateChanged(int remoteId, int state, int reason, int elapsed) { + Log.i(TAG, "onRemoteVideoStateChanged"); + if (mRemoteUid == -1 && state == Constants.REMOTE_VIDEO_STATE_STARTING) { + runOnUiThread(() -> { + mRemoteUid = remoteId; + setRemoteVideoView(remoteId); + }); + } + } + + private void setRemoteVideoView(int uid) { + TextureView mRemoteVideoViewNew = RtcEngine.CreateTextureView(this); + mRtcEngine.setupRemoteVideo(new VideoCanvas( + mRemoteVideoViewNew, VideoCanvas.RENDER_MODE_HIDDEN, uid)); + mRemoteVideoView.addView(mRemoteVideoViewNew); + mRemoteVideoView.setVisibility(View.VISIBLE); + } + + private int mRemoteUid = -1; + + private void onRemoteUserLeft() { + mRemoteUid = -1; + removeRemoteView(); + } + + private void removeRemoteView() { + mRemoteVideoView.removeAllViews(); + } + + /** + * 保存美颜设置数据 + */ + private void saveBeauty() { + if (mFaceUnityDataFactory != null && mFaceUnityDataFactory.mFaceBeautyDataFactory != null) { + FaceBeauty beauty = mFaceUnityDataFactory.mFaceBeautyDataFactory.getCurrentFaceBeauty(); + if (beauty != null) { + HashMap hashMap = FaceBeautySource.faceBeautyToHashMap(beauty); + Gson gson = new Gson(); + String beautySettings = gson.toJson(hashMap); + BeautySPUtils.saveString("newFaceBeautySettings", beautySettings); + } + } + } + + public long last_net_work_show_time = 0; + + public boolean isNetWorkQualityShow(long showtime) { + if ((showtime / 1000) - (last_net_work_show_time / 1000) > 6) { + return true; + } else { + return false; + } + } + + @Override + public void onNetworkQuality(int uid, int txQuality, int rxQuality) { + Log.i(TAG, "onNetworkQuality:---------------uid--------->" + uid + "txQuality------------>" + txQuality + "--------rxQuality----->" + rxQuality); + runOnUiThread(new Runnable() { + @Override + public void run() { + if (uid == 0) { //自己 + if (txQuality == 0 || rxQuality == 0) { + + } else if (txQuality == 4 || rxQuality == 4) { + if (isNetWorkQualityShow(System.currentTimeMillis())) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "你的网络不佳!"); + last_net_work_show_time = System.currentTimeMillis(); + } + + } else if (txQuality == 5 || rxQuality == 5) { + if (isNetWorkQualityShow(System.currentTimeMillis())) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "你的网络差!"); + last_net_work_show_time = System.currentTimeMillis(); + } + } else if (txQuality == 6 || rxQuality == 6) { + if (isNetWorkQualityShow(System.currentTimeMillis())) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "你的网络很差或无网络!"); + last_net_work_show_time = System.currentTimeMillis(); + } + } + } else { //对方 + if (txQuality == 0 || rxQuality == 0) { + } else if (txQuality == 4 || rxQuality == 4) { + if (isNetWorkQualityShow(System.currentTimeMillis())) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "对方的网络不佳!"); + last_net_work_show_time = System.currentTimeMillis(); + } + } else if (txQuality == 5 || rxQuality == 5) { + if (isNetWorkQualityShow(System.currentTimeMillis())) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "对方的网络差!"); + last_net_work_show_time = System.currentTimeMillis(); + } + } else if (txQuality == 6 || rxQuality == 6) { + if (isNetWorkQualityShow(System.currentTimeMillis())) { + MaleToast.showMessage(AgoraWithFUVideoActivity.this, "对方的网络很差或无网络!"); + last_net_work_show_time = System.currentTimeMillis(); + } + } + } + } + }); + } + + //媚币充值后返回通知 + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_RECHARGE && resultCode == RESULT_OK) { + sendRechargeSucceed(); + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/AllChannelActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/AllChannelActivity.java new file mode 100644 index 0000000..e4c8595 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/AllChannelActivity.java @@ -0,0 +1,78 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.AllChannelRecyclerAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.SkillAnchorBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import java.util.ArrayList; +import java.util.List; + +public class AllChannelActivity extends BaseActivity { + private RecyclerView mChannelList; + private AllChannelRecyclerAdapter mRecyclerAdapter; + private List dataList = new ArrayList<>(); + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_all_channels); + setDefaultTitle(); + setTitleName("技能列表"); + initView(); + getAllChannelData(); + } + + private void initView(){ + mChannelList = findViewById(R.id.all_channel_list_view); + mRecyclerAdapter = new AllChannelRecyclerAdapter(this); + mRecyclerAdapter.setSkillList(dataList); + mChannelList.setAdapter(mRecyclerAdapter); + mChannelList.setLayoutManager(new StaggeredGridLayoutManager(3, + StaggeredGridLayoutManager.VERTICAL)); + + mRecyclerAdapter.setOnItemClickListener(new AllChannelRecyclerAdapter.OnItemClickListener() { + @Override + public void onItemClicked(View v, int position) { +// Intent intent = new Intent(); +// intent.putExtra("skillName", dataList.get(position).getName()); +// setResult(RESULT_OK, intent); +// finish(); + + Intent intent = new Intent(AllChannelActivity.this, SkillActivity.class); + intent.putExtra("skillName", dataList.get(position).getName()); + intent.putExtra("skillId",dataList.get(position).getId()); + startActivity(intent); + } + }); + } + + private void getAllChannelData(){ + MainManager.getAllChannels(this, new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + dataList = result; + mRecyclerAdapter.setSkillList(dataList); + mRecyclerAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/ChannelSelectorActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/ChannelSelectorActivity.java new file mode 100644 index 0000000..1efd7ca --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/ChannelSelectorActivity.java @@ -0,0 +1,6 @@ +package com.fengliyan.tianlesue.view.main; + +import com.fengliyan.tianlesue.view.base.BaseActivity; + +public class ChannelSelectorActivity extends BaseActivity { +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/CityPickerActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/CityPickerActivity.java new file mode 100644 index 0000000..8305239 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/CityPickerActivity.java @@ -0,0 +1,393 @@ +package com.fengliyan.tianlesue.view.main; + +import android.Manifest; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.location.LocationBean; +import com.fengliyan.location.LocationManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.utils.PermissionUtil; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.uikit.picker.citypicker.adapter.CityListAdapter; +import com.fengliyan.uikit.picker.citypicker.adapter.InnerListener; +import com.fengliyan.uikit.picker.citypicker.adapter.decoration.DividerItemDecoration; +import com.fengliyan.uikit.picker.citypicker.adapter.decoration.SectionItemDecoration; +import com.fengliyan.uikit.picker.citypicker.db.DBManager; +import com.fengliyan.uikit.picker.citypicker.model.City; +import com.fengliyan.uikit.picker.citypicker.model.HotCity; +import com.fengliyan.uikit.picker.citypicker.model.LocateState; +import com.fengliyan.uikit.picker.citypicker.model.LocatedCity; +import com.fengliyan.uikit.picker.citypicker.view.SideIndexBar; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +/** + * Created by zhangbin on 2019/1/7. + */ + +public class CityPickerActivity extends BaseActivity implements InnerListener, SideIndexBar.OnIndexTouchedChangedListener, TextWatcher, View.OnClickListener { + private static final String TAG = "CityPickerActivity"; + private boolean isAllPermissionsGranted; + public static final int PERMISSION_REQUEST_CODE = 101; + private Disposable mDisposable; + private DBManager dbManager; + private List mResults; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_city_picker); + hideTitleBar(); +// setDefaultTitle(); + initHotCities(); + initLocatedCity(); + + dbManager = new DBManager(this); + mAllCities = dbManager.getAllCities(); + mAllCities.add(0, mLocatedCity); + //mAllCities.add(1, new HotCity("热门城市", "未知", "0")); + mResults = mAllCities; + initView(); + checkNewPermission(); + LocationManager.getInstance().addLocationObserver(new Observer() { + @Override + public void onSubscribe(Disposable d) { + mDisposable = d; + } + + @Override + public void onNext(LocationBean locationBean) { + LocationManager.getInstance().stop(); + if (null == locationBean) { + locateState = LocateState.FAILURE; + } else { + MainManager.updateRealCity(CityPickerActivity.this, locationBean.getLatitude(), locationBean.getLongitude(), locationBean.getProvince(), locationBean.getCityName(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onSuccess: "); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onFailure: " + tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onSuccess: " + e); + } + }); + + if (TextUtils.isEmpty(locationBean.getCity())) { + locateState = LocateState.FAILURE; + } else { + locateState = LocateState.SUCCESS; + } + } + locationChanged(new LocatedCity(locationBean.getCity(), + locationBean.getProvince(), + locationBean.getCityCode()), locateState); + mDisposable.dispose(); + } + + @Override + public void onError(Throwable e) { + LocationManager.getInstance().stop(); + } + + @Override + public void onComplete() { + } + }); + + +// getPicker(); + + } + + public void locationChanged(LocatedCity location, int state) { + mAdapter.updateLocateState(location, state); + } + + private RecyclerView mRecyclerView; + private LinearLayoutManager mLayoutManager; + private CityListAdapter mAdapter; + private List mAllCities = new ArrayList<>(); + private List mHotCities; + private LocatedCity mLocatedCity; + private int locateState = LocateState.LOCATING; + private View mEmptyView; + private TextView mOverlayTextView; + private SideIndexBar mIndexBar; + private EditText mSearchBox; + private TextView mCancelBtn; + private ImageView mClearAllBtn; + + private void initView() { + mRecyclerView = findViewById(com.fengliyan.uikit.R.id.cp_city_recyclerview); + mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.setHasFixedSize(true); + mRecyclerView.addItemDecoration(new SectionItemDecoration(this, mAllCities), 0); + mRecyclerView.addItemDecoration(new DividerItemDecoration(this), 1); + mAdapter = new CityListAdapter(this, mAllCities, mHotCities, LocateState.LOCATING); + mAdapter.setInnerListener(this); + mAdapter.setLayoutManager(mLayoutManager); + mRecyclerView.setAdapter(mAdapter); + mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + //确保定位城市能正常刷新 + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + mAdapter.refreshLocationItem(); + } + } + }); + + mEmptyView = findViewById(com.fengliyan.uikit.R.id.cp_empty_view); + mOverlayTextView = findViewById(com.fengliyan.uikit.R.id.cp_overlay); + + mIndexBar = findViewById(com.fengliyan.uikit.R.id.cp_side_index_bar); + mIndexBar.setOverlayTextView(mOverlayTextView) + .setOnIndexChangedListener(this); + + mSearchBox = findViewById(com.fengliyan.uikit.R.id.cp_search_box); + mSearchBox.addTextChangedListener(this); + + mCancelBtn = findViewById(com.fengliyan.uikit.R.id.cp_cancel); + mClearAllBtn = findViewById(com.fengliyan.uikit.R.id.cp_clear_all); + mCancelBtn.setOnClickListener(this); + mClearAllBtn.setOnClickListener(this); + } + + private void initHotCities() { + if (mHotCities == null || mHotCities.isEmpty()) { + mHotCities = new ArrayList<>(); + mHotCities.add(new HotCity("北京", "北京", "101010100")); + mHotCities.add(new HotCity("上海", "上海", "101020100")); + mHotCities.add(new HotCity("广州", "广东", "101280101")); + mHotCities.add(new HotCity("深圳", "广东", "101280601")); + mHotCities.add(new HotCity("天津", "天津", "101030100")); + mHotCities.add(new HotCity("杭州", "浙江", "101210101")); + mHotCities.add(new HotCity("南京", "江苏", "101190101")); + mHotCities.add(new HotCity("成都", "四川", "101270101")); + mHotCities.add(new HotCity("武汉", "湖北", "101200101")); + } + } + + private void initLocatedCity() { + mLocatedCity = new LocatedCity(getString(com.fengliyan.uikit.R.string.cp_locating), "未知", "0"); + locateState = LocateState.LOCATING; + } + + private void checkNewPermission() { + String[] permissions = {Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION}; + PermissionDialog permissionDialog = new PermissionDialog(this, permissions); + permissionDialog.show(); + + XXPermissions.with(this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + LocationManager.getInstance().start(); + permissionDialog.dismiss(); + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog dialog = new CustomAlertDialog(CityPickerActivity.this); + dialog.setTitle("私语请求定位手机权限,是否允许?"); + dialog.hideContent(true); + dialog.setRightBtnText("去开启"); + dialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(CityPickerActivity.this); + } + }); + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + dialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + +// String[] permissions = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; +// +// if (needToRequestPermission(permissions)) { +// requestPermission(permissions, PERMISSION_REQUEST_CODE); +// } else { +// isAllPermissionsGranted = true; +// LocationManager.getInstance().start(); +// } + } + + protected boolean needToRequestPermission(String[] permissions) { + boolean ret = false; + for (String permission : permissions) { + if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { + ret = true; + break; + } else { + } + } + return ret; + } + + protected void requestPermission(String[] permissions, int requestCode) { + ArrayList needRequest = new ArrayList(); + for (String permission : permissions) { + if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { + needRequest.add(permission); + } else { + } + } + + //申请WRITE_EXTERNAL_STORAGE权限 + if (needRequest.size() > 0) { + ActivityCompat.requestPermissions(this, needRequest.toArray(new String[]{}), + requestCode); + } + + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == PERMISSION_REQUEST_CODE) { + isAllPermissionsGranted = true; + for (int result : grantResults) { + if (result != PackageManager.PERMISSION_GRANTED) { + isAllPermissionsGranted = false; + } + } + + if (isAllPermissionsGranted) { + LocationManager.getInstance().start(); + } + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + finish(); + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void dismiss(int position, City data) { + Intent intent = new Intent(); + intent.putExtra("city", data.getName()); + setResult(RESULT_OK, intent); + finish(); + } + + @Override + public void locate() { +// if (isAllPermissionsGranted) { +// LocationManager.getInstance().start(); +// } else { +// checkNewPermission(); +// } + + checkNewPermission(); + } + + @Override + public void onIndexChanged(String index, int position) { + //滚动RecyclerView到索引位置 + if (null != mAdapter) + mAdapter.scrollToSection(index); + } + + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable s) { + String keyword = s.toString(); + if (TextUtils.isEmpty(keyword)) { + mClearAllBtn.setVisibility(View.GONE); + mEmptyView.setVisibility(View.GONE); + mResults = mAllCities; + ((SectionItemDecoration) (mRecyclerView.getItemDecorationAt(0))).setData(mResults); + mAdapter.updateData(mResults); + } else { + mClearAllBtn.setVisibility(View.VISIBLE); + //开始数据库查找 + mResults = dbManager.searchCity(keyword); + ((SectionItemDecoration) (mRecyclerView.getItemDecorationAt(0))).setData(mResults); + if (mResults == null || mResults.isEmpty()) { + mEmptyView.setVisibility(View.VISIBLE); + } else { + mEmptyView.setVisibility(View.GONE); + mAdapter.updateData(mResults); + } + } + mRecyclerView.scrollToPosition(0); + } + + @Override + public void onClick(View view) { + if (view == mCancelBtn) { +// dismiss(-1, null); + finish(); + } else if (view == mClearAllBtn) { + mSearchBox.setText(""); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mDisposable && !mDisposable.isDisposed()) { + mDisposable.dispose(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/ComplaintActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/ComplaintActivity.java new file mode 100644 index 0000000..af38cb5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/ComplaintActivity.java @@ -0,0 +1,161 @@ +package com.fengliyan.tianlesue.view.main; + +import android.graphics.Color; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.ComplaintAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.ComplaintListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +public class ComplaintActivity extends BaseActivity implements View.OnClickListener{ + private EditText mComplaintInfoInput; + private TextView mComplaintInputText; + private View mComplaintInputView; + private Button mConfirmButton; + private LoadMoreListView mComplaintList; + private ComplaintAdapter mComplaintAdapter; + private String mUid; + private int mType; + private int mSelectedIndex = -1; + private List mComplaintListBeans = new ArrayList<>(); + private TextWatcher mWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + String length = mComplaintInfoInput.getText().length() + "/300字"; + mComplaintInputText.setText(length); + } + + @Override + public void afterTextChanged(Editable editable) { + + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_complaint); + setDefaultTitle(); + showTitleBottomLine(); + setTitleName("举报"); + mUid = getIntent().getStringExtra("uid"); + mType = getIntent().getIntExtra("type", 0); + initView(); + getComplainInfo(); + } + + private void initView(){ + mComplaintList = findViewById(R.id.complaint_list); + mComplaintInputText = findViewById(R.id.edit_char_count); + mComplaintInfoInput = findViewById(R.id.edit_post); + mComplaintInputView = findViewById(R.id.edit_view); + mConfirmButton = findViewById(R.id.complaint_confirm); + mComplaintInfoInput.setHint("请描述举报的内容"); + mComplaintAdapter = new ComplaintAdapter(this); + mComplaintAdapter.setComplaintList(mComplaintListBeans); + mComplaintList.setAdapter(mComplaintAdapter); + mComplaintInfoInput.addTextChangedListener(mWatcher); + mComplaintInputView.setBackgroundColor(Color.WHITE); + mConfirmButton.setOnClickListener(this); + mComplaintList.removeFooterView(mComplaintList.getLoadMoreView()); + mComplaintAdapter.setOnComplaintCheckerCheckedListener(new ComplaintAdapter.OnComplaintCheckerCheckedListener() { + @Override + public void onComplaintChecked(int index, boolean checker) { + if(!checker){ + mSelectedIndex = -1; + }else { + if (mSelectedIndex != -1) { + ComplaintListBean bean = mComplaintListBeans.get(mSelectedIndex); + bean.setChecked(false); + } + + ComplaintListBean selectedBean = mComplaintListBeans.get(index); + selectedBean.setChecked(true); + mSelectedIndex = index; + mComplaintAdapter.notifyDataSetChanged(); + } + } + }); + } + + private void getComplainInfo(){ + MainManager.getComplaintList(this, new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + mComplaintListBeans.addAll(result); + mComplaintAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void complaint(){ + if (mComplaintListBeans == null || mComplaintListBeans.size() == 0) { + MaleToast.showMessage(this, "举报失败,请重试"); + return; + } + if (mSelectedIndex==-1){ + MaleToast.showMessage(this, "请选择举报类型"); + return; + } + ComplaintListBean bean = mComplaintListBeans.get(mSelectedIndex); + MainManager.doComplaint(this, mType, bean.getId(), mUid, + mComplaintInfoInput.getText().toString(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { + MaleToast.showMessage(ComplaintActivity.this, "举报成功,感谢你的帮助"); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(ComplaintActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(ComplaintActivity.this, "举报失败"); + } + }); + } + + @Override + public void onClick(View view) { + if(view == mConfirmButton){ +// if(TextUtils.isEmpty(mComplaintInfoInput.getText().toString())){ +// MaleToast.showMessage(ComplaintActivity.this, "请描述要举报的内容"); +// return; +// } + + complaint(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/CoverActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/CoverActivity.java new file mode 100644 index 0000000..8a4aa42 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/CoverActivity.java @@ -0,0 +1,646 @@ +package com.fengliyan.tianlesue.view.main; + +import android.Manifest; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.view.View; +import android.widget.ImageView; + +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.login.manager.LoginManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.login.bean.CustomerTipBean; +import com.fengliyan.tianlesue.model.main.SystemVersionBean; +import com.fengliyan.tianlesue.model.main.VersionBean; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.AppStatusCallbacks; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.login.LoginActivity; +import com.fengliyan.tianlesue.view.login.utils.LoginUtils; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.main.dialog.UpdateDialog; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.dialog.PrivateDialog; +import com.fengliyan.uikit.toast.MaleToast; +import com.xinlingwu.share.ShareManager; + +import java.io.File; +import java.util.List; + +public class CoverActivity extends BaseActivity { + private ImageView mCoverView; + + // private PhoneNumberAuthHelper mPhoneNumberAuthHelper; +// private TokenResultListener mTokenResultListener; +// private int mUIType; +// private BaseUIConfig mUIConfig; +// private OnOneKeyCustomClickListener onOneKeyCustomClickListener; +// private boolean isOneKeyQQLogin = false; +// private boolean isOneKeyIsPricyChecked = false; +// public static boolean isShowOldLoginView = false; //是否显示老的登录页面 +// private boolean isLoadingOneKey = true; +// private int loginType; +// private String mUid; +// private String mAccessToken; +// private String mPlatform; + private CountDownTimer mTimer = new CountDownTimer(0, 0) { + @Override + public void onTick(long l) { + + } + + @Override + public void onFinish() { + boolean is_login = SPUtils.getBoolean(CoverActivity.this, ConsUser.IS_LOGIN, false); + if (is_login) { + if (!SPUtils.getBoolean(CoverActivity.this, ConsUser.IS_LOGIN_AGREEMENT_CHECK, false)) { + BaseApplication.getInstance().initSdk(); + } + Intent intent = new Intent(CoverActivity.this, + MainActivity.class); + startActivity(intent); + finish(); + } else { + if (!SPUtils.getBoolean(CoverActivity.this, ConsUser.IS_LOGIN_AGREEMENT_CHECK, false)) { + showLoginDialog(); + } else { +// oneKeyLoginInit(); + checkUpdate(); + } + } + } + }; + + @Override + public SwipeRefreshLayout getRefresh() { + return refreshLayout; + } + + public void showLoginDialog() { + PrivateDialog.getInstace().message("").sure("同意").cancle("不同意并退出") + .setOnTipItemClickListener(new PrivateDialog.OnTipItemClickListener() { + @Override + public void cancleClick() { + finishActivity(); + } + + @Override + public void sureClick() { + SPUtils.saveBoolean(CoverActivity.this, ConsUser.IS_LOGIN_AGREEMENT_CHECK, true);//登录的用户协议,app不卸载的话只弹出一次,点击同意后设置为已同意 + BaseApplication.getInstance().initSdk(); + getMarketStatus(); +// new Handler().postDelayed(new Runnable() { +// @Override +// public void run() { +// oneKeyLoginInit(); +// +// } +// }, 10); + // MaleToast.showMessage(CoverActivity.this,"启动页点了同意隐私,开始初始化sdk"); + + } + + @Override + public void userClick() { + Intent intent = new Intent(CoverActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } + + @Override + public void termsClick() { + Intent intent = new Intent(CoverActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } + }).create(CoverActivity.this); + } + + public void oneKeyLoginInit() { + Intent intent = new Intent(CoverActivity.this, LoginActivity.class); + startActivity(intent); + finish(); +// sdkInit(BuildConfig.AUTH_SECRET); +// onOneKeyCustomClickListener = new OnOneKeyCustomClickListener() { +// @Override +// public void onChangeLoginType() { +// // rl_login_root.setVisibility(View.VISIBLE); +// // isShowOldLoginView = true; +// // rl_login_root.requestFocus(); +// // loginType = 2; +// mPhoneNumberAuthHelper.quitLoginPage(); +// Intent intent = new Intent(CoverActivity.this, LoginActivity.class); +// startActivity(intent); +// finish(); +// } +// +// @Override +// public void onThirdLogin(int type) { +// oneKeyLoginPageThirdLogin(type); +// } +// +// @Override +// public void onCustomerTip() { +// getCustomerTip(); +// } +// }; +// mUIConfig = new CustomXmlConfig(CoverActivity.this, mPhoneNumberAuthHelper, onOneKeyCustomClickListener); +// mPhoneNumberAuthHelper = PhoneNumberAuthHelper.getInstance(getApplicationContext(), mTokenResultListener); +// mPhoneNumberAuthHelper.checkEnvAvailable(); +// mUIConfig.configAuthPage(); +// mPhoneNumberAuthHelper.getLoginToken(CoverActivity.this, 5000); + } + + +// public void sdkInit(String secretInfo) { +// mTokenResultListener = new TokenResultListener() { +// @Override +// public void onTokenSuccess(String s) { +// //dismissProgressBar(); +// isLoadingOneKey = false; +// try { +// TokenRet tokenRet = null; +// tokenRet = TokenRet.fromJson(s); +// if (ResultCode.CODE_START_AUTHPAGE_SUCCESS.equals(tokenRet.getCode())) { +// Log.i("TAG", "唤起授权页成功:" + s); +// loginType = 1; +// } +// final String token = tokenRet.getToken(); +// if (ResultCode.CODE_SUCCESS.equals(tokenRet.getCode())) { +// Log.i("TAG", "获取token成功:" + s); +// //getResultWithToken(tokenRet.getToken()); +// InviteCodeUpdateUtils.getOpeninstallData(new InviteCodeUpdateUtils.CodeCallback() { +// @Override +// public void callback(String code) { +// oneKeyLogin(token, code); +// } +// }); +// mPhoneNumberAuthHelper.setAuthListener(null); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// +// @Override +// public void onTokenFailed(String s) { +// //dismissProgressBar(); +// isLoadingOneKey = false; +// TokenRet tokenRet = null; +// Log.i("TAG", "唤起授权页失败"); +// try { +// tokenRet = TokenRet.fromJson(s); +// if (ResultCode.CODE_ERROR_USER_CANCEL.equals(tokenRet.getCode())) { +// //模拟的是必须登录 否则直接退出app的场景 +// Log.i("TAG", "用户取消快捷"); +// finish(); +// } else { +// isShowOldLoginView = true; +// loginType = 2; +// mPhoneNumberAuthHelper.quitLoginPage(); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// // rl_login_root.setVisibility(View.VISIBLE); +// isShowOldLoginView = true; +// mPhoneNumberAuthHelper.setAuthListener(null); +// Intent intent = new Intent(CoverActivity.this, LoginActivity.class); +// startActivity(intent); +// finish(); +// } +// }; +// mPhoneNumberAuthHelper = PhoneNumberAuthHelper.getInstance(BaseApplication.getInstance().getApplicationContext(), mTokenResultListener); +// mPhoneNumberAuthHelper.getReporter().setLoggerEnable(true); +// mPhoneNumberAuthHelper.setUIClickListener(new AuthUIControlClickListener() { +// @Override +// public void onClick(String s, Context context, String s1) { +// if (s.equals("700003")) { +// //隐私政策勾选回调 +// JSONObject jsonObject = null; +// try { +// jsonObject = new JSONObject(s1); +// isOneKeyIsPricyChecked = jsonObject.getBoolean("isChecked"); +// Log.i("一键登录页", "isChecked:" + isOneKeyIsPricyChecked); +// } catch (JSONException e) { +// e.printStackTrace(); +// } +// +// } +// Log.i("一键登录页", "s:" + s + ";s1" + s1); +// } +// }); +// mPhoneNumberAuthHelper.setAuthSDKInfo(secretInfo); +// } + + +// private void oneKeyLogin(String token, String invite_code) { +// HTProtect.getTokenAsync(3000, "11dfa1f43cd4f2f77dddad305690ada3", new GetTokenCallback() { +// @Override +// public void onResult(AntiCheatResult antiCheatResult) { +// NoClearSPUtils.saveString(CoverActivity.this, "x-risk-engine-token", antiCheatResult.token); +// MainManager.oneKeyLogin(CoverActivity.this, token, invite_code, new HttpUiCallBack() { +// @Override +// public void onSuccess(BaseActivity activity, LoginBean result, String tips) { +// mPhoneNumberAuthHelper.removeAuthRegisterViewConfig(); +// mPhoneNumberAuthHelper.removeAuthRegisterXmlConfig(); +// mPhoneNumberAuthHelper.quitLoginPage(); +// +// LoginUtils.checkLoginStatus(CoverActivity.this, result, 2); +// } +// +// @Override +// public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showFailureMsg(activity, tip); +// } +// +// @Override +// public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showFailureMsg(activity, "登录失败"); +// e.printStackTrace(); +// } +// }); +// } +// }); +// } + + +// private void oneKeyLoginPageThirdLogin(int thirdType) { +// +// +// if (thirdType == 1) { +// if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_WEIXIN)) { +// MaleToast.showMessage(this, "请先安装微信"); +// return; +// } +// // 现在这么配置 +// UMShareConfig config = new UMShareConfig(); +// config.isNeedAuthOnGetUserInfo(true); +// UMShareAPI.get(this).setShareConfig(config); +// ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { +// @Override +// public void success(Map map) { +// +// thirdLogin(map, "wechat"); +// } +// +// @Override +// public void error() { +// +// } +// +// @Override +// public void cancel() { +// +// } +// }, this, ShareManager.TYPE_WEIXIN); +// } else { +// //切换用户就会去获取用户信息,每一次授权都会获取用户信息 +// UMShareConfig config1 = new UMShareConfig(); +// config1.isNeedAuthOnGetUserInfo(true); +// UMShareAPI.get(this).setShareConfig(config1); +// if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_QQ)) { +// MaleToast.showMessage(this, "请先安装QQ"); +// return; +// } +// ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { +// @Override +// public void success(Map map) { +// +// thirdLogin(map, "qq"); +// +// } +// +// @Override +// public void error() { +// isOneKeyQQLogin = false; +// enterOneKeyLogin(); +// } +// +// @Override +// public void cancel() { +// isOneKeyQQLogin = false; +// +// enterOneKeyLogin(); +// } +// }, BaseApplication.getInstance().getTopActivity(), ShareManager.TYPE_QQ); +// isOneKeyQQLogin = true; +// } +// } + + /** + * 进入一键登录 + */ +// private void enterOneKeyLogin() { +// mUIConfig.configAuthPage(); +// mPhoneNumberAuthHelper.getLoginToken(this, 5000); +// // rl_login_root.setVisibility(View.VISIBLE); +// isShowOldLoginView = false; +// } + + + @Override + public boolean needScallfold() { + return false; + } + + SwipeRefreshLayout refreshLayout; + + @Override + public void onCreate(Bundle onSavedInstance) { + AppStatusCallbacks.get().setmAppStatus(AppStatusCallbacks.STATUS_NORMAL); + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_cover); + refreshLayout = findViewById(R.id.refreshLayout); +// 全屏 + // 获取唤醒参数 +// OpenInstall.getWakeUp(getIntent(), wakeUpAdapter); + + if (!isTaskRoot()) { + finish(); + return; + } + if (getIntent() != null) { + if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { + finish(); + return; + } + } + + if (Build.VERSION.SDK_INT >= 21) { + View decorView = getWindow().getDecorView(); + int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; + decorView.setSystemUiVisibility(option); + getWindow().setNavigationBarColor(Color.TRANSPARENT); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + + if (null != getSupportActionBar()) { + getSupportActionBar().hide(); + } +// hideTitleBar(); +// mCoverView = findViewById(R.id.cover_main); + if (!SPUtils.getBoolean(CoverActivity.this, ConsUser.IS_LOGIN_AGREEMENT_CHECK, false)) { + showLoginDialog(); + } else { + getMarketStatus(); + } + SPUtils.saveInt(this, ConsUser.DYNAMICS_TYPE, 0); + } + +// public void thirdLogin(Map params, String platform) { +// String uid = (null == params.get("uid")) ? params.get("unionid") : params.get("uid"); +// String accessToken = params.get("accessToken"); +// mUid = uid; +// mAccessToken = accessToken; +// mPlatform = platform; +// HTProtect.getTokenAsync(3000, "11dfa1f43cd4f2f77dddad305690ada3", new GetTokenCallback() { +// @Override +// public void onResult(AntiCheatResult antiCheatResult) { +// NoClearSPUtils.saveString(CoverActivity.this, "x-risk-engine-token", antiCheatResult.token); +// InviteCodeUpdateUtils.getOpeninstallData(new InviteCodeUpdateUtils.CodeCallback() { +// @Override +// public void callback(String code) { +// LoginManager.thirdLogin(CoverActivity.this, platform, uid, accessToken, +// code, new HttpUiCallBack() { +// @Override +// public void onSuccess(BaseActivity activity, LoginBean result, String message) { +// LoginUtils.checkLoginStatus(CoverActivity.this, result, 2); +// if (null != result.getUserinfo().getInvite_code()) { +// UserManager.setInviteResult(true); +// } +// } +// +// @Override +// public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showFailureMsg(CoverActivity.this, tip); +// } +// +// @Override +// public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showFailureMsg(CoverActivity.this, "登录失败login" + e.getMessage()); +// } +// }); +// } +// }); +// } +// }); +// } + +// AppWakeUpAdapter wakeUpAdapter = new AppWakeUpAdapter() { +// @Override +// public void onWakeUp(AppData appData) { +// // 打印数据便于调试 +// Log.d("OpenInstall", "getWakeUp : wakeupData = " + appData.toString()); +// // 获取渠道数据 +// String channelCode = appData.getChannel(); +// // 获取绑定数据 +// String bindData = appData.getData(); +// +// } +// }; + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + // 此处要调用,否则App在后台运行时,会无法获取 +// OpenInstall.getWakeUp(intent, wakeUpAdapter); + } + + + private void startTimer() { + mTimer.start(); + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + ShareManager.getInstance().onActivityResult(this, requestCode, resultCode, data); + } + + @Override + public void onDestroy() { + super.onDestroy(); +// wakeUpAdapter = null; + if (mTimer != null) { + mTimer.cancel(); + mTimer = null; + } + } + + private void getMarketStatus() { + MainManager.getMarketStatus(this, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, VersionBean result, String message) { + NoClearSPUtils.saveInt(activity, Constans.MARKET_STATUS, result.getMarket_status()); + startTimer(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + e.printStackTrace(); + MaleToast.showFailureMsg(activity, "网络异常,请检查网络连接"); + NoClearSPUtils.saveInt(activity, Constans.MARKET_STATUS, 1); + startTimer(); + } + }); + } + + public void getCustomerTip() { + LoginManager.getCustomerTip(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, CustomerTipBean result, String message) { + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private UpdateDialog mUpdateDialog; + private String mDownloadUrl; + public static final String DOWNLOAD_PATH = ConstUrl.DEFAULT_PATH + "/cache/"; + + private void checkUpdate() { + MainManager.checkUpdate(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final SystemVersionBean result, String message) { + mUpdateDialog = new UpdateDialog(CoverActivity.this, R.style.SelectiveDialog); + mUpdateDialog.setConfirmListener(new UpdateDialog.DownloadConfirmListener() { + @Override + public void onConfirm() { + PermissionDialog permissionDialog = new PermissionDialog(CoverActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}); + permissionDialog.show(); + XXPermissions.with(activity).permission(Manifest.permission.WRITE_EXTERNAL_STORAGE).request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + permissionDialog.dismiss(); + if (all) { + File file = new File(DOWNLOAD_PATH); + if (file.isFile()) { + file.delete(); + } + + if (!file.exists()) { + file.mkdirs(); + } + + MainManager.downloadNewApp(CoverActivity.this, mDownloadUrl, + DOWNLOAD_PATH + "temp.apk", + new HttpCallback() { + @Override + public void onFailure(int httpStatusCode, String message, Throwable throwable) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } + } + + @Override + public void onSuccess(int httpStatusCode, String responseObject) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + if (result.getEnforce() != 1) { + mUpdateDialog.dismiss(); + } + } + LoginUtils.install(DOWNLOAD_PATH + "temp.apk", CoverActivity.this); + } + + @Override + public void onProgress(long bytesCount, long contentLength, boolean done) { + mUpdateDialog.setProgress((int) (((double) bytesCount) / contentLength * 100)); + } + }); + + } else { + if (result.getEnforce() == 1) { + finish(); + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + OnPermissionCallback.super.onDenied(permissions, never); + permissionDialog.dismiss(); + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } + } + }); + } + + @Override + public void onCancel() { + oneKeyLoginInit(); + } + }); + mUpdateDialog.setCancelable(false); + mDownloadUrl = result.getDownloadurl(); + mUpdateDialog.setInfo(result.getUpgradetext()); + mUpdateDialog.setVersionName(result.getNewversion()); + if (result.getVersioncode() > LoginUtils.getVersionCode(CoverActivity.this)) { + if (result.getEnforce() == 1) { + StorageManager.getInstance(CoverActivity.this) + .putBean("UpdateHintDate", null); + mUpdateDialog.setFinishHide(); + mUpdateDialog.show(); + } else { + final Long currentTime = System.currentTimeMillis(); + final Long lastTime = (Long) StorageManager.getInstance(CoverActivity.this).getBean("UpdateHintDate", Long.class); + if (null == lastTime || currentTime - lastTime > 7 * 24 * 60 * 60 * 1000) { + mUpdateDialog.show(); + StorageManager.getInstance(CoverActivity.this) + .putBean("UpdateHintDate", currentTime); + } else { + oneKeyLoginInit(); + } + } + } else { + oneKeyLoginInit(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderActiveFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderActiveFragment.java new file mode 100644 index 0000000..fee6215 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderActiveFragment.java @@ -0,0 +1,121 @@ +package com.fengliyan.tianlesue.view.main; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.main.adapter.GenderUserAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.main.UserGenderListBean; +import com.fengliyan.tianlesue.model.settings.UserInfoBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.refresh.LoadMoreListView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/3/6. + */ + +public class GenderActiveFragment extends Fragment { + + private LoadMoreListView mListView; + private int mPage = 1; + private List mGenderBeanList = new ArrayList<>(); + private GenderUserAdapter mAdapter; + private boolean mPageLoad; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_gender_active, container, false); + initView(v); + mPage = 1; + getGenderUserInfo(SPUtils.getString(getActivity(), ConsUser.GENDER_CITY_ID ), mPage); + return v; + } + + private void initView(View v) { + mListView = v.findViewById(R.id.gender_active_list); + mAdapter = new GenderUserAdapter(getActivity()); + mAdapter.setUserList(mGenderBeanList); + mListView.setAdapter(mAdapter); + + mAdapter.setOnClickItemListener(new GenderUserAdapter.OnClickItemListener() { + @Override + public void onClickItemListener(UserInfoBean userInfoBean) { + NimUIKit.startP2PSession(getActivity(), String.valueOf(userInfoBean.getUserid())); + } + }); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + if(mGenderBeanList.size() != 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mGenderBeanList.size() - 2){ + getGenderUserInfo(SPUtils.getString(getActivity(), ConsUser.GENDER_CITY_ID ), mPage); + mPageLoad = true; + }else if(mListView.getLastVisiblePosition() <= mGenderBeanList.size() - 2){ + mPageLoad = false; + } + + } + }); + + } + + public void getGenderUserInfo(String cityId, int page){ + int gender = 1; + if(UserManager.getUserInfo().getGender() == 1){ + gender = 2; + } + + MainManager.getGenderUserList((BaseActivity) getActivity(), cityId, gender, 0, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, UserGenderListBean result, String message) { + mGenderBeanList.addAll(result.getList().getList()); + for (int i = 0; i < mGenderBeanList.size(); i++) //外循环是循环的次数 + { + for (int j = mGenderBeanList.size() - 1; j > i; j--) //内循环是 外循环一次比较的次数 + { + + if (mGenderBeanList.get(i).getUserid() == mGenderBeanList.get(j).getUserid()) { + mGenderBeanList.remove(j); + } + + } + } + mAdapter.notifyDataSetChanged(); + mPage ++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderCityFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderCityFragment.java new file mode 100644 index 0000000..47db2e9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderCityFragment.java @@ -0,0 +1,127 @@ +package com.fengliyan.tianlesue.view.main; + +import android.os.Bundle; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.main.adapter.GenderUserAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.main.UserGenderListBean; +import com.fengliyan.tianlesue.model.settings.UserInfoBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/3/6. + */ + +public class GenderCityFragment extends Fragment { + + private LoadMoreListView mListView; + private int mPage = 1; + private List mGenderBeanList = new ArrayList<>(); + private GenderUserAdapter mAdapter; + private boolean mPageLoad; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_gender_active, container, false); + initView(v); + mPage = 1; + getGenderUserInfo(SPUtils.getString(getActivity(), ConsUser.GENDER_CITY_ID ), mPage); + return v; + } + + private void initView(View v) { + mListView = v.findViewById(R.id.gender_active_list); + mAdapter = new GenderUserAdapter(getActivity()); + mAdapter.setUserList(mGenderBeanList); + mListView.setAdapter(mAdapter); + + mAdapter.setOnClickItemListener(new GenderUserAdapter.OnClickItemListener() { + @Override + public void onClickItemListener(UserInfoBean userInfoBean) { + NimUIKit.startP2PSession(getActivity(), String.valueOf(userInfoBean.getUserid())); + } + }); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + if(mGenderBeanList.size() != 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mGenderBeanList.size() - 2){ + getGenderUserInfo(SPUtils.getString(getActivity(), ConsUser.GENDER_CITY_ID ), mPage); + mPageLoad = true; + }else if(mListView.getLastVisiblePosition() <= mGenderBeanList.size() - 2){ + mPageLoad = false; + } + + } + }); + } + + public void setCityChoose(String cityId) { + mPage = 1; + getGenderUserInfo(cityId, mPage); + } + + public void getGenderUserInfo(String cityId, final int page){ + int gender = 1; + if(UserManager.getUserInfo().getGender() == 1){ + gender = 2; + } + + MainManager.getGenderUserList((BaseActivity) getActivity(), cityId, gender, 1, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, UserGenderListBean result, String message) { + if (page == 1) { + mGenderBeanList.clear(); + } + mGenderBeanList.addAll(result.getList().getList()); + for (int i = 0; i < mGenderBeanList.size(); i++) //外循环是循环的次数 + { + for (int j = mGenderBeanList.size() - 1; j > i; j--) //内循环是 外循环一次比较的次数 + { + + if (mGenderBeanList.get(i).getUserid() == mGenderBeanList.get(j).getUserid()) { + mGenderBeanList.remove(j); + } + + } + } + mAdapter.notifyDataSetChanged(); + mPage ++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderUserAndMibiRankActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderUserAndMibiRankActivity.java new file mode 100644 index 0000000..48e1f58 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/GenderUserAndMibiRankActivity.java @@ -0,0 +1,265 @@ +package com.fengliyan.tianlesue.view.main; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.settings.dialog.GirlAuthDialog; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/3/6. + */ + +public class GenderUserAndMibiRankActivity extends BaseActivity implements View.OnClickListener { + + private View mTitleView; + private TextView mTitleText1; + private TextView mTitleText2; + private TextView mTitleText3; + private View mTitleBottom1; + private View mTitleBottom2; + private View mTitleBottom3; + private View mTitleTag1; + private View mTitleTag2; + private View mTitleTag3; + private TextView mTvGreet; + private ImageView mIvMoreCity; + private View mBack; + + private ViewPager mMainViewPager; + private List mChannelFragments = new ArrayList<>(); + private MainViewPagerAdapter mViewPagerAdapter; + private GenderActiveFragment mGenderActiveFragment; + private GenderCityFragment mGenderCityFragment; + private boolean isReClick = false; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_gender_user_and_mibi_rank); + initTitle(); + initView(); + } + + private void initTitle() { + Title title = getCustomTitle(); + title.setVisibility(View.VISIBLE); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.item_gender_user_title, null); + mTitleTag1 = mTitleView.findViewById(R.id.title_view_1); + mTitleTag2 = mTitleView.findViewById(R.id.title_view_2); + mTitleTag3 = mTitleView.findViewById(R.id.title_view_3); + mTitleText1 = mTitleView.findViewById(R.id.title_name_1); + mTitleText2 = mTitleView.findViewById(R.id.title_name_2); + mTitleText3 = mTitleView.findViewById(R.id.title_name_3); + mTitleBottom1 = mTitleView.findViewById(R.id.title_bottom_line_1); + mTitleBottom2 = mTitleView.findViewById(R.id.title_bottom_line_2); + mTitleBottom3 = mTitleView.findViewById(R.id.title_bottom_line_3); + mTvGreet = mTitleView.findViewById(R.id.tv_greet); + mIvMoreCity = mTitleView.findViewById(R.id.iv_more_city); + mBack = mTitleView.findViewById(R.id.exchange_title_back); + + if (UserManager.getUserInfo().getGender() == 1) { //女生 + mTvGreet.setVisibility(View.VISIBLE); +// mTitleTag3.setVisibility(View.VISIBLE); + } else { + mTvGreet.setVisibility(View.GONE); +// mTitleTag3.setVisibility(View.GONE); + } + + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + mTitleTag3.setOnClickListener(this); + mTvGreet.setOnClickListener(this); + mBack.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + + } + + private void initView() { + mMainViewPager = findViewById(R.id.view_pager); + + mGenderActiveFragment = new GenderActiveFragment(); + mGenderCityFragment = new GenderCityFragment(); +// if(UserManager.getUserInfo().getGender() == 1){ //女生 +// mMibiRankFragment = new MibiRankFragment(); +// mChannelFragments.add(mGenderActiveFragment); +// mChannelFragments.add(mGenderCityFragment); +// mChannelFragments.add(mMibiRankFragment); +// }else { +// mChannelFragments.add(mGenderActiveFragment); +// mChannelFragments.add(mGenderCityFragment); +// } + + mChannelFragments.add(mGenderActiveFragment); + mChannelFragments.add(mGenderCityFragment); + + mViewPagerAdapter = new MainViewPagerAdapter(getSupportFragmentManager(), + mChannelFragments); + + mMainViewPager.setAdapter(mViewPagerAdapter); + + viewPagerChange(0); + + mMainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if (position == 1) { + isReClick = true; + } else { + isReClick = false; + } + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPagerAdapter.notifyDataSetChanged(); + mMainViewPager.setCurrentItem(0); + } + + private void viewPagerChange(int index) { + + if (null != mTitleText2) { + String city = SPUtils.getString(this, ConsUser.GENDER_CITY); + if (!TextUtils.isEmpty(city)) { + mTitleText2.setText(city); + } + } + + switch (index) { + case 0: + mTitleText1.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom1.setVisibility(View.VISIBLE); + + mTitleText2.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + + mTitleText3.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + break; + case 1: + mTitleText2.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom2.setVisibility(View.VISIBLE); + + mTitleText1.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + + mTitleText3.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo2); + break; + case 2: + mTitleText3.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom3.setVisibility(View.VISIBLE); + + mTitleText1.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + + mTitleText2.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + break; + } + } + + @Override + public void onClick(View view) { + if (view == mTitleTag1) { + mMainViewPager.setCurrentItem(0); + } else if (view == mTitleTag2) { +// mMainViewPager.setCurrentItem(1); + if (isReClick) { + Intent intent = new Intent(GenderUserAndMibiRankActivity.this, CityPickerActivity.class); +// startActivity(intent); + startActivityForResult(intent, 1004); + } else { + mMainViewPager.setCurrentItem(1); + } + } else if (view == mTitleTag3) { + mMainViewPager.setCurrentItem(2); + } else if (view == mTvGreet) { + if (UserManager.getUserInfo().getIs_anchor() == 1 && UserManager.getUserInfo().getIs_face_status() == 1) { + Intent intent = new Intent(GenderUserAndMibiRankActivity.this, GroupCallActivity.class); + startActivity(intent); + } else { + GirlAuthDialog dialog = new GirlAuthDialog(this); + dialog.show(); + MaleToast.showMessage(GenderUserAndMibiRankActivity.this, "通过真人认证才能使用该功能"); + } + } else if (view == mBack) { + finish(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 1004 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(GenderUserAndMibiRankActivity.this, ConsUser.GENDER_CITY, city); + mTitleText2.setText(city); + + if (!TextUtils.isEmpty(city)) { + String cityId = GlobalManager.getCityMap().get(city); + SPUtils.saveString(GenderUserAndMibiRankActivity.this, ConsUser.GENDER_CITY_ID, cityId); + if (null != mGenderCityFragment) { + mGenderCityFragment.setCityChoose(cityId); + } +// mPage = 1; +// mGenderBeanList.clear(); +// getGenderUserInfo(cityId, mType, mPage); + } + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/GiftReceivedActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/GiftReceivedActivity.java new file mode 100644 index 0000000..d558bfe --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/GiftReceivedActivity.java @@ -0,0 +1,102 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.main.adapter.GiftReceivedAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.GiftReceivedBean; +import com.fengliyan.tianlesue.model.main.GiftReceivedItemBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.utils.UiUtils; +import com.fengliyan.tianlesue.view.settings.CaibeiRechargeActivity; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class GiftReceivedActivity extends BaseActivity { + private LoadMoreListView mListView; + private GiftReceivedAdapter mAdapter; + private List mGiftList = new ArrayList<>(); + private View mHeaderView; + private TextView mTotalTextView; + private int mUserId; + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_gift_received); + + setDefaultTitle(); + setTitleName("已收到的礼物"); + mUserId = getIntent().getIntExtra("userId", 0); + initView(); + getReceivedGifts(); + } + + private void initView(){ + mListView = findViewById(R.id.gift_received_list); + mHeaderView = View.inflate(this, R.layout.item_gift_received_header, null); + ViewGroup.LayoutParams params = new + ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + UiUtils.dp2px(this, 74)); + + mHeaderView.setLayoutParams(params); + mTotalTextView = mHeaderView.findViewById(R.id.gift_received_header_info); + mAdapter = new GiftReceivedAdapter(this); + mAdapter.setGiftReceivedList(mGiftList); + mListView.setAdapter(mAdapter); + if((mUserId+"").equals(SPUtils.getInt(GiftReceivedActivity.this, ConsUser.USER_ID) + "")){ + mListView.addHeaderView(mHeaderView); + } + + mHeaderView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(GiftReceivedActivity.this, CaibeiRechargeActivity.class); + startActivity(intent); + } + }); + } + + private void getReceivedGifts(){ + MainManager.receivedGiftList(this, mUserId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftReceivedBean result, String message) { + if(null == result.getList()){ + mTotalTextView.setText("暂未收到礼物"); + return; + } + + mGiftList.addAll(result.getList()); + mAdapter.notifyDataSetChanged(); + Iterator iterator = result.getList().iterator(); + int total = 0; + while (iterator.hasNext()){ + GiftReceivedItemBean bean = iterator.next(); + total += Integer.parseInt(bean.getTotal()); + } + + mTotalTextView.setText("一共收到" + total + "个礼物"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/GroupCallActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/GroupCallActivity.java new file mode 100644 index 0000000..088c91b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/GroupCallActivity.java @@ -0,0 +1,241 @@ +package com.fengliyan.tianlesue.view.main; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.GroupCallAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.GroupCallBean; +import com.fengliyan.tianlesue.model.main.GroupCallListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/28. + */ + +public class GroupCallActivity extends BaseActivity implements View.OnClickListener { + + private RecyclerView mRvCall; + private Button mBtCall; + private GroupCallAdapter mAdapter; + private List mList = new ArrayList<>(); + private int mSize; + private TextView mTvAdd; + private GroupCallListBean mBean; + private boolean mStatus; + private BaseMessageDialog mMessageDialog; + private TextView mTvTitle; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_group_activity); + initTitle(); + initView(); + getData(); + } + + private void getData() { + MainManager.getGroupCallInfo(this, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, GroupCallBean result, String message) { + if (null != result) { + mList.clear(); + mList.addAll(result.getList()); + mAdapter.setData(mList); + mAdapter.notifyDataSetChanged(); + mSize = result.getCount(); + mStatus = result.isStatus(); + + if (null != result.getList()) { + if (result.getList().size() == 0) { + mTvTitle.setText("请点击右上角添加打招呼内容"); + } else { + mTvTitle.setText("请选择打招呼内容"); + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void initView() { + mRvCall = findViewById(R.id.rv_call); + mBtCall = findViewById(R.id.bt_call); + mTvTitle = findViewById(R.id.tv_title); + + mRvCall.setLayoutManager(new LinearLayoutManager(this)); + mAdapter = new GroupCallAdapter(this); + mAdapter.setData(mList); + mRvCall.setAdapter(mAdapter); + mAdapter.setItemOnClickListener(new GroupCallAdapter.ItemOnClickListener() { + @Override + public void itemOnClick(GroupCallListBean bean) { + if (bean.getStatus() == 1) { + mBean = bean; + mAdapter.setSelect(bean.getId(), 1); + mAdapter.notifyDataSetChanged(); + + if (mSize != 0 && !mStatus) { + mBtCall.setEnabled(true); + } else { + mBtCall.setEnabled(false); + } + } + + } + + @Override + public void itemOnLongClick(int position, GroupCallListBean bean) { + showLeaveMessage(position, bean); + } + + + }); + + mBtCall.setOnClickListener(this); + } + + private View mTitleView; + private View mBack; + + private void initTitle() { + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(android.R.color.white); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.item_group_call_title, null); + mBack = mTitleView.findViewById(R.id.exchange_title_back); + mTvAdd = mTitleView.findViewById(R.id.tv_add); + mBack.setOnClickListener(this); + mTvAdd.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + } + + /** + * 挂断弹出框 + */ + public void showLeaveMessage(final int position, final GroupCallListBean bean) { + mMessageDialog = new BaseMessageDialog.Builder(this).setMessage("是否删除?") + .setCancelable(true) + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (null != bean) { + delete(position, bean); + } + mMessageDialog.dismiss(); + } + }).setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mMessageDialog.dismiss(); + } + }).build(); + + mMessageDialog.show(); + } + + private void delete(int position, final GroupCallListBean bean) { + MainManager.deleteGroupCall(this, bean.getId(), new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + if (null != mBean) { + if (mBean.getId() == bean.getId()) { + mBtCall.setEnabled(false); + } + } + getData(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + if (view == mBack) { + finish(); + } else if (view == mBtCall) { + if (null != mBean) { + sendGroupCall(mBean.getId()); + } + } else if (view == mTvAdd) { + if (mSize >= 10) { + MaleToast.showMessage(GroupCallActivity.this, "最多添加10条"); + } else { + Intent intent = new Intent(GroupCallActivity.this, AddGroupCallActivity.class); +// startActivity(intent); + startActivityForResult(intent, 1006); + } + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 1006 && resultCode == RESULT_OK) { + getData(); + } + } + + private void sendGroupCall(final int id) { + MainManager.sendGroupCall(this, id, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(GroupCallActivity.this, "发送成功"); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/GuardRankActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/GuardRankActivity.java new file mode 100644 index 0000000..053e451 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/GuardRankActivity.java @@ -0,0 +1,90 @@ +package com.fengliyan.tianlesue.view.main; + +import android.os.Bundle; +import android.widget.AbsListView; + +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.GuardRankAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.GuardListBean; +import com.fengliyan.tianlesue.model.main.GuardRankBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/12/17. + */ +public class GuardRankActivity extends BaseActivity { + + private LoadMoreListView mListView; + private GuardRankAdapter mAdapter; + private List mDataList = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + private int mUserId; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_guard_rank); + String name = getIntent().getStringExtra("name"); + mUserId = getIntent().getIntExtra("userId", 0); + setTitleName(name + "的守护榜"); + initView(); + getData(mPage); + } + + private void initView() { + mListView = findViewById(R.id.guard_list_view); + + mAdapter = new GuardRankAdapter(this); + mAdapter.setDatas(mDataList); + mListView.setAdapter(mAdapter); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if(mDataList.size() != 0 && mDataList.size() % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mDataList.size() - 2){ + getData(mPage); + mPageLoad = true; + }else if(mListView.getLastVisiblePosition() <= mDataList.size() - 2){ + mPageLoad = false; + } + + } + }); + } + + + private void getData(int page) { + + MainManager.getGuardList(this, page, mUserId + "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GuardListBean result, String message) { + mDataList.addAll(result.getList()); + mAdapter.notifyDataSetChanged(); + mPage ++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/KidConfirmPasswordActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidConfirmPasswordActivity.java new file mode 100644 index 0000000..5d7cdb9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidConfirmPasswordActivity.java @@ -0,0 +1,101 @@ +package com.fengliyan.tianlesue.view.main; + +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.eventBus.KidEvent; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.utils.CaptchaInputView; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class KidConfirmPasswordActivity extends BaseActivity { + + private CaptchaInputView mCaptcha_input_view; + private String mCode; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_kid_confirm_password); + hideTitleBar(); + mCode = getIntent().getStringExtra("code"); + initView(); + } + + private void initView() { + findViewById(R.id.rl_back).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + mCaptcha_input_view = findViewById(R.id.captcha_input_view); + mCaptcha_input_view.setFocusable(true); + mCaptcha_input_view.setFocusableInTouchMode(true); + mCaptcha_input_view.requestFocus(); + mCaptcha_input_view.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + Log.i("TAG", "onTextChanged: -------->" + s); + if (s.toString().length() >= 4) { + if (s.toString().equals(mCode)) { + setPass(s.toString()); + } else { + MaleToast.showMessage(KidConfirmPasswordActivity.this, "密码不正确"); + } + + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + /** + * 确认密码 + * + * @param password + */ + private void setPass(String password) { + + MainManager.setKidPassword(this, password, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + //请求成功 + EventBus.getDefault().post(new KidEvent(-1)); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/KidForgetPasswordActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidForgetPasswordActivity.java new file mode 100644 index 0000000..cdf60b8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidForgetPasswordActivity.java @@ -0,0 +1,205 @@ +package com.fengliyan.tianlesue.view.main; + +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.eventBus.KidEvent; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.CodeUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.editor.CaiEditText; +import com.fengliyan.uikit.toast.MaleToast; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/12/20. + */ +public class KidForgetPasswordActivity extends BaseActivity implements View.OnClickListener { + + private Button mConfirmButton; + private Button mSendCodeButton; + private CaiEditText mPhoneEditText; + private CaiEditText mAuthCodeEditText; + private boolean isCodeSend; + private ImageView captchaImageView; + private String code; + private CaiEditText imageVerifyEditText; + + private CountDownTimer mTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + mSendCodeButton.setText((l / 1000) + ""); + } + + @Override + public void onFinish() { + mSendCodeButton.setEnabled(true); + isCodeSend = false; + mSendCodeButton.setText("获取验证码"); + + } + }; + + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if (!TextUtils.isEmpty(mPhoneEditText.getText()) + && !TextUtils.isEmpty(mAuthCodeEditText.getText())) { + mConfirmButton.setEnabled(true); + } else { + mConfirmButton.setEnabled(false); + } + + if (!TextUtils.isEmpty(mPhoneEditText.getText()) && !isCodeSend) { + mSendCodeButton.setEnabled(true); + } else { + mSendCodeButton.setEnabled(false); + } + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_kid_forget_password); + setTitleName("关闭未成年模式"); + initPicCode(); + initView(); + } + + private void initView() { + mConfirmButton = findViewById(R.id.bind_phone_confirm_confirm); + mSendCodeButton = findViewById(R.id.bind_phone_confirm_code_button); + mPhoneEditText = findViewById(R.id.bind_phone_confirm_edit); + mAuthCodeEditText = findViewById(R.id.bind_phone_confirm_code_input); + captchaImageView= findViewById(R.id.image); + imageVerifyEditText= findViewById(R.id.register_image_verify_edit); + + captchaImageView.setOnClickListener(this); + mSendCodeButton.setEnabled(false); + mConfirmButton.setEnabled(false); + mConfirmButton.setOnClickListener(this); + mSendCodeButton.setOnClickListener(this); + mPhoneEditText.getEditText().addTextChangedListener(mTextWatcher); + mAuthCodeEditText.getEditText().addTextChangedListener(mTextWatcher); + + mPhoneEditText.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + mPhoneEditText.setText(""); + } + }); + } + + public void sendCode(String number) { + if(StringUtil.isEmpty(mPhoneEditText.getText().toString())){ + MaleToast.showFailureMsg(KidForgetPasswordActivity.this, "请输入您的手机号码"); + return; + } + if(StringUtil.isEmpty(imageVerifyEditText.getText().toString())){ + MaleToast.showFailureMsg(KidForgetPasswordActivity.this, "请输入图片验证码"); + return; + } + if(!imageVerifyEditText.getText().toString().toLowerCase().equals(code.toLowerCase())){ + MaleToast.showFailureMsg(KidForgetPasswordActivity.this, "图片验证码错误"); + return; + } + RegisterManager.sendAuthCode(this, number,code, "findadpwd", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + mTimer.start(); + isCodeSend = true; + mSendCodeButton.setEnabled(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "验证码获取失败"); + } + }); + } + + + //获取图形验证码 + public void initPicCode(){ + RegisterManager.getPicCode(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + if(ConstUrl.LOGDEBUG) Log.d("ssz",tips); + code=result.toString(); + captchaImageView.setImageBitmap(CodeUtils.getInstance().createBitmap(code)); + } + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + public void bindPhone(String phone, String code) { + MainManager.kidPhoneCode(this, phone, code, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + //请求成功 + EventBus.getDefault().post(new KidEvent(1)); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onClick(View v) { + if (v == mSendCodeButton) { + sendCode(mPhoneEditText.getText()); + } else if (v == mConfirmButton) { + bindPhone(mPhoneEditText.getText(), mAuthCodeEditText.getText()); + }else if(v==captchaImageView){ + initPicCode(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/KidInputPasswordActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidInputPasswordActivity.java new file mode 100644 index 0000000..e8da733 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidInputPasswordActivity.java @@ -0,0 +1,84 @@ +package com.fengliyan.tianlesue.view.main; + +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.eventBus.KidEvent; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.utils.CaptchaInputView; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/12/20. + */ +public class KidInputPasswordActivity extends BaseActivity { + + private CaptchaInputView mCaptcha_input_view; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_kid_input_password); + hideTitleBar(); + initView(); + } + + private void initView() { + findViewById(R.id.rl_back).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + mCaptcha_input_view = findViewById(R.id.captcha_input_view); + + mCaptcha_input_view.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (s.toString().length() >= 4) { + inputPassword(s.toString()); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + private void inputPassword(String toString) { + MainManager.setOpenKidModel(this, toString, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + //请求成功 + EventBus.getDefault().post(new KidEvent(1)); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/KidModelActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidModelActivity.java new file mode 100644 index 0000000..cfdf2c1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidModelActivity.java @@ -0,0 +1,51 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.eventBus.KidEvent; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/12/24. + */ +public class KidModelActivity extends BaseActivity { + + private Button mBt_kid; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_kid_model); + EventBus.getDefault().register(this); + setTitleName("未成年模式"); + initView(); + } + + private void initView() { + mBt_kid = findViewById(R.id.bt_kid); + mBt_kid.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(KidModelActivity.this, KidSetPasswordActivity.class); + startActivity(intent); + } + }); + } + + //监听青少年模式 + public void onEventMainThread(KidEvent event) { + finish(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/KidSetPasswordActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidSetPasswordActivity.java new file mode 100644 index 0000000..8887cad --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/KidSetPasswordActivity.java @@ -0,0 +1,74 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.eventBus.KidEvent; +import com.fengliyan.tianlesue.utils.CaptchaInputView; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/12/19. + */ +public class KidSetPasswordActivity extends BaseActivity { + + private CaptchaInputView mCaptcha_input_view; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_kid_set_password); + EventBus.getDefault().register(this); + hideTitleBar(); + initView(); + } + + private void initView() { + findViewById(R.id.rl_back).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + mCaptcha_input_view = findViewById(R.id.captcha_input_view); + + mCaptcha_input_view.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (s.toString().length() >= 4) { + Intent intent = new Intent(KidSetPasswordActivity.this, KidConfirmPasswordActivity.class); + intent.putExtra("code",s.toString()); + startActivity(intent); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + //监听青少年模式 + public void onEventMainThread(KidEvent event) { + finish(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainActivity.java new file mode 100644 index 0000000..f8c13c1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainActivity.java @@ -0,0 +1,1892 @@ +package com.fengliyan.tianlesue.view.main; + +import android.Manifest; +import android.animation.ObjectAnimator; +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.ActivityManager; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.view.GestureDetector; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.AlertDialog; +import androidx.core.app.NotificationCompat; + +import com.blankj.utilcode.util.ActivityUtils; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; +import com.facebook.drawee.view.SimpleDraweeView; +import com.google.gson.Gson; +import com.google.gson.internal.LinkedTreeMap; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.huawei.agconnect.config.AGConnectServicesConfig; +import com.huawei.hms.aaid.HmsInstanceId; +import com.huawei.hms.common.ApiException; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.location.LocationManager; +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.messaging.CustomAttachment; +import com.fengliyan.messaging.GiftAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.utils.ToastUtil; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.eventBus.ActiveUpdateEvent; +import com.fengliyan.tianlesue.controller.eventBus.KidEvent; +import com.fengliyan.tianlesue.controller.eventBus.NotificationEvent; +import com.fengliyan.tianlesue.controller.eventBus.RegisterInfoEvent; +import com.fengliyan.tianlesue.controller.eventBus.TurntableEvent; +import com.fengliyan.tianlesue.controller.eventBus.UnReadCountEvent; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.session.activity.P2PMessageActivity; +import com.fengliyan.tianlesue.im.uikit.business.session.constant.Extras; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.SysSPUtils; +import com.fengliyan.tianlesue.im.uikit.impl.customization.DefaultP2PSessionCustomization; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.main.AttentionDialogBean; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.CloseGreetBean; +import com.fengliyan.tianlesue.model.main.DialogAdBean; +import com.fengliyan.tianlesue.model.main.FreeVideoBean; +import com.fengliyan.tianlesue.model.main.GlobalConfigBean; +import com.fengliyan.tianlesue.model.main.IsKidModelBean; +import com.fengliyan.tianlesue.model.main.SpeedInfoBean; +import com.fengliyan.tianlesue.model.main.SystemVersionBean; +import com.fengliyan.tianlesue.model.main.VideoRequestBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.utils.CitySPUtils; +import com.fengliyan.tianlesue.utils.DemoHelper; +import com.fengliyan.tianlesue.utils.LongSpUtils; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.NotificationsUpUtils; +import com.fengliyan.tianlesue.utils.NotificationsUtils; +import com.fengliyan.tianlesue.utils.PermissionUtil; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StatusBarUtil; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.utils.TimeZoneUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.SpeedWebSocket; +import com.fengliyan.tianlesue.view.base.utils.AppStatusCallbacks; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.AttentionDialog; +import com.fengliyan.tianlesue.view.base.utils.view.KidDialog; +import com.fengliyan.tianlesue.view.base.utils.view.KidOpenDialog; +import com.fengliyan.tianlesue.view.dynamics.fragment.DynamicViewPagerFragment; +import com.fengliyan.tianlesue.view.login.LoginActivity; +import com.fengliyan.tianlesue.view.login.utils.LoginUtils; +import com.fengliyan.tianlesue.view.luck.LuckFragment; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.main.dialog.FreeVideoDialog; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.main.dialog.UpdateDialog; +import com.fengliyan.tianlesue.view.main.receiver.NotificationClickReceiver; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.tianlesue.view.main.utils.UiUtils; +import com.fengliyan.tianlesue.view.news.fragment.MainMessageFragment; +import com.fengliyan.tianlesue.view.news.im.DemoCache; +import com.fengliyan.tianlesue.view.settings.BindPhoneConfirmActivity; +import com.fengliyan.tianlesue.view.settings.QuickRechargeActivity; +import com.fengliyan.tianlesue.view.settings.SettingFragment; +import com.fengliyan.tianlesue.view.settings.dialog.GirlAuthDialog; +import com.fengliyan.tianlesue.view.settings.dialog.SpeedCallDialog; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.bottomtab.BottomTab; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.auth.AuthService; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.snail.antifake.deviceid.emulator.EmuCheckUtil; +import com.snail.antifake.jni.EmulatorDetectUtil; +import com.umeng.socialize.UMAuthListener; +import com.umeng.socialize.bean.SHARE_MEDIA; +import com.xinlingwu.share.ShareManager; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import de.greenrobot.event.EventBus; +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +public class MainActivity extends BaseActivity implements DemoHelper.AppIdsUpdater, SpeedWebSocket.SpeedWebSocketListener { + private static final String TAG = "MainActivity"; + public static final String DOWNLOAD_PATH = ConstUrl.DEFAULT_PATH + "/cache/"; + public static final int REQUEST_FINISH = 200; + public static final int RESULT_LOGIN = 201; + public final static int mCallID = 112; + private BottomTab mBottomTab; + private long mExitTime; + private LuckFragment luckFragment; + private SwipeCardFragment swipeCardFragment; + private DynamicViewPagerFragment mDynamicViewPagerFragment; + private MainRecommendFragment mMainRecommendFragment; + private MainMessageFragment mMainMessageFragment; + private SettingFragment mSettingFragment; + private Disposable mDisposable; + private boolean isLoginViewShowed; + private UpdateDialog mUpdateDialog; + private String mDownloadUrl; + private boolean isOne = false; + private AlertDialog mAlertDialog; + int weekTime = 7 * 24 * 60 * 60 * 1000; + private AttentionDialog mAttentionDialog; + private KidDialog mKidDialog; + private KidOpenDialog mKidOpenDialog; + private RelativeLayout mToastLayout; + private FrameLayout mLlRecharge; + private SimpleDraweeView mSvRechargeAvatar; + private TextView mTvRechargeName; + private TextView mTvRechargeTotal; + private RelativeLayout mRlSend; + private SimpleDraweeView mSvSendAvatar; + private TextView mTvSendName; + private TextView mTvReceiveName; + private SimpleDraweeView mSvReceiveAvatar; + private SimpleDraweeView mSvGift; + private TextView mTvGiftTotal; + private DemoHelper demoHelper; + private boolean is_close_greet_dialog_show = false; + + private FrameLayout vipLayout; + private SimpleDraweeView memberUserAvatar; + private TextView memberUserNameLabel; + private String avatar; + private int isLogin; + + @Override + public void onCreate(Bundle savedInstanceState) { + AppStatusCallbacks.get().setmAppStatus(AppStatusCallbacks.STATUS_NORMAL); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); +// BaseApplication.getInstance().userstatisticsSocketConnect(); + EventBus.getDefault().register(this); + init(savedInstanceState); + try { + demoHelper = new DemoHelper(this); + demoHelper.getDeviceIds(MainActivity.this.getApplicationContext()); + + } catch (Exception e) { + + } + //getHuaweiToken(); +// checkNewPermission(); + if (ConstUrl.DEBUG && NoClearSPUtils.getBoolean(this, Constans.ENVIRONMENT_TYPE, true)) { + Toast.makeText(this, "您处于开发环境下", Toast.LENGTH_SHORT).show(); + } + checkWomenAnchorDialog(); + + SpeedWebSocket.getInstance().connect(); + SpeedWebSocket.getInstance().setListener(this); + EmulatorDetectUtil.isEmulatorFromAll(this); + EmuCheckUtil.checkEmulatorFromCache(getApplicationContext(), + new EmuCheckUtil.CheckEmulatorCallBack() { + @Override + public void onCheckSuccess(boolean isEmulator) { + if (isEmulator) { + ToastUtil.showToast(MainActivity.this, "检测到模拟器登录,已退出"); + System.exit(0); + } + } + + @Override + public void onCheckFaild() { + Log.i("TAG", "onCheckFaild: --------->"); + } + }); + } + + void checkWomenAnchorDialog() { +// LoginBean loginBean = (LoginBean) StorageManager.getInstance(MainActivity.this).getBean("loginBean", LoginBean.class); +// if (loginBean != null && loginBean.getUserinfo().getIs_anchor() == 0 && loginBean.getUserinfo().isWomen()) { +// new GirlAuthDialog(this).show(); +// } + } + + private BaseMessageDialog bindMobileDialog; + + @Override + public void onResume() { + super.onResume(); + if (TextUtils.isEmpty(SPUtils.getString(this, ConsUser.MOBILE))) { + if (TextUtils.isEmpty(SPUtils.getString(MainActivity.this, "bindMobile"))) { + bindMobileDialog = new BaseMessageDialog.Builder(this).setTitle("温馨提示").setMessage("为了保证你的账号安全,请绑定手机号!\n若需要协助,添加客服微信 Zdhfa1234").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + bindMobileDialog.dismiss(); + } + }).setPositive("去绑定").setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(MainActivity.this, BindPhoneConfirmActivity.class); + startActivity(intent); + } + }).build(); + bindMobileDialog.show(); + SPUtils.saveString(MainActivity.this, "bindMobile", "1"); + } else { + if (bindMobileDialog != null && bindMobileDialog.isShowing()) { + bindMobileDialog.dismiss(); + } + } + } + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + boolean isFormTask = intent.getBooleanExtra("isFormTask", false); + boolean isMain = intent.getBooleanExtra("isMain", false); + if (isFormTask) { + mBottomTab.change(1); + } + if (isMain) { + int marketStatus = NoClearSPUtils.getInt(this, Constans.MARKET_STATUS, 0); + if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { + mBottomTab.change(0); + } else { + if (UserManager.getUserInfo().isWomen()) { + mBottomTab.change(0); + } else { + mBottomTab.change(2); + } + } + } + } + + /** + * 调起使用这个会弹出hms 下载框 + */ + private void getHuaweiToken() { + new Thread() { + @Override + public void run() { + try { + // read from agconnect-services.json + String appId = AGConnectServicesConfig.fromContext(MainActivity.this).getString("client/app_id"); + String token = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, "HCM"); + Log.i("mix_push 1", "get token:" + token); + } catch (ApiException e) { + Log.i("mix_push 1", e.getMessage()); + } + } + }.start(); + } + + //查询消息免打扰 + public void getGreet() { + if (UserManager.getUserInfo().getGender() == 1) { + return; + } + MainManager.getGreet(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, CloseGreetBean result, String tips) { + if (result != null) { + int is_close = result.getNo_greet(); + if (is_close == 1 && !is_close_greet_dialog_show) { + showCloseGreetDialog(); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + //关闭消息免打扰 + public void closeGreet() { + MainManager.closeGreet(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + MaleToast.showMessage(activity, tips); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + private void checkNewPermission() { + String[] permissions = {Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION}; + XXPermissions.with(this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + LocationManager.getInstance().start(); + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog dialog = new CustomAlertDialog(MainActivity.this); + dialog.setTitle("私语请求定位手机权限,是否允许?"); + dialog.hideContent(true); + dialog.setRightBtnText("去开启"); + dialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(MainActivity.this); + } + }); + dialog.show(); + } + } + }); + } + + public static final int PERMISSION_REQUEST_CODE = 101; + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == PERMISSION_REQUEST_CODE) { + LocationManager.getInstance().start(); + } + } + + private void init(Bundle savedInstanceState) { + long currentTimeMillis = System.currentTimeMillis(); + long time = currentTimeMillis - LongSpUtils.getLong(this, "time"); +// if (time >= weekTime) { +// notificationRun(); +// } + initView(); + + final LoginBean loginBean = (LoginBean) StorageManager.getInstance(this) + .getBean("loginBean", LoginBean.class); + + if (null != loginBean) { + DeviceManager.getInstance().setToken(loginBean.getUserinfo().getToken()); + NoClearSPUtils.saveString(this, "token", loginBean.getUserinfo().getToken()); + UserManager.setUserInfo(loginBean.getUserinfo()); + handleLoginInfo(savedInstanceState); + } else { + SpeedWebSocket.getInstance().close(); + Intent intent = new Intent(this, LoginActivity.class); + startActivityForResult(intent, REQUEST_FINISH); + } + + queryCities(); + getGlobalConfig(); + activeUpdate(); + getKidModel(0); + + int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount(); + //消息tab显示最近未读联系人头像 + avatar = ""; + if (unreadNum > 0) { + NIMClient.getService(MsgService.class).queryRecentContacts().setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List recentContacts, Throwable throwable) { + if (recentContacts != null && recentContacts.size() > 0) { + for (int i = 0; i < recentContacts.size(); i++) { +// if (NIMClient.getService(FriendService.class).isNeedMessageNotify(recentContacts.get(i).getContactId())) { + if (recentContacts.get(i).getUnreadCount() != 0 && Long.parseLong(recentContacts.get(i).getContactId()) > 20 && recentContacts.get(i).getSessionType() == SessionTypeEnum.P2P) { + NimUserInfo userInfo = NIMClient.getService(UserService.class).getUserInfo(recentContacts.get(i).getContactId()); + if (userInfo != null) { + avatar = userInfo.getAvatar(); + if (!TextUtils.isEmpty(avatar)) { + avatar = StrU.getResourcePath(avatar, MainActivity.this); + } + } + break; + } +// } + } + } + setNewsCount(unreadNum, avatar); + } + }); + } else { + setNewsCount(unreadNum, avatar); + } + + ChatManager.getInstance().observeOnlineStatus(new ChatManager.OnlineClientStatusListener() { + @Override + public void onStatusChanged(int status) { + + } + + @Override + public void onKickOff() { + StorageManager.getInstance(MainActivity.this).clear(); + UserManager.getInstance().notifyUserInfoChanged(new BaseUserInfo()); + } + }); + + mKidDialog = new KidDialog(this); + mKidOpenDialog = new KidOpenDialog(this); + + NIMClient.getService(MsgServiceObserve.class).observeReceiveMessage(incomingMessageObserver, true); +// freeAnchor(); + } + + com.netease.nimlib.sdk.Observer> incomingMessageObserver = new com.netease.nimlib.sdk.Observer>() { + @Override + public void onEvent(List imMessages) { + Activity currentActivity = BaseApplication.getInstance().getTopActivity(); + if (currentActivity != null && !currentActivity.isDestroyed()) { + for (int i = 0; i < imMessages.size(); i++) { + IMMessage imMessage = imMessages.get(i); + if (!isAppOnForeground(currentActivity)) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_ACCOUNT, imMessage.getFromAccount()); + if (!"2".equals(imMessage.getFromAccount()) && !"4".equals(imMessage.getFromAccount()) && !"11".equals(imMessage.getFromAccount()) && !"3".equals(imMessage.getFromAccount()) && !"5".equals(imMessage.getFromAccount()) + && !"6".equals(imMessage.getFromAccount()) && !"7".equals(imMessage.getFromAccount()) && !"8".equals(imMessage.getFromAccount()) && !"9".equals(imMessage.getFromAccount()) && !"10".equals(imMessage.getFromAccount())) { //不是系统通知才显示自定义的聊天bar + intent.putExtra(Extras.EXTRA_CUSTOMIZATION, new DefaultP2PSessionCustomization()); + } + intent.setClass(currentActivity, P2PMessageActivity.class); + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "onEvent: imMessage.getContent()----->" + imMessage.getContent()); + PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(currentActivity, 0, + intent, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationManager systemService = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + String channel_id = "120722"; + Notification notificationBuilder = new NotificationCompat.Builder(currentActivity, channel_id) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentTitle(imMessage.getFromNick()) + .setContentText(StrU.isEmpty(imMessage.getContent()) ? "您有一条消息" : imMessage.getContent()) + .setPriority(NotificationCompat.PRIORITY_HIGH) // <--- 高优先级 + .setCategory(NotificationCompat.CATEGORY_CALL) + .setContentIntent(fullScreenPendingIntent) +// .setFullScreenIntent(fullScreenPendingIntent, true)// <--- 全屏 intent + .setAutoCancel(true) + .build(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(channel_id, "私信消息", + NotificationManager.IMPORTANCE_HIGH); + channel.setDescription("私信消息"); +// channel.setSound(Uri.parse("android.resource://" + currentActivity.getPackageName() + "/" + R.raw.call_bg), Notification.AUDIO_ATTRIBUTES_DEFAULT); + channel.enableLights(true); + channel.setLightColor(Color.RED); + channel.enableVibration(true); + channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); + systemService.createNotificationChannel(channel); + } + systemService.notify(mCallID, notificationBuilder); + } + if (StrU.equals(imMessage.getFromAccount(), SPUtils.getString(MainActivity.this, "im_account")) + || StrU.equals(imMessage.getFromAccount(), "2") || StrU.equals(imMessage.getFromAccount(), "11") + || currentActivity instanceof AgoraWithFUVideoActivity || currentActivity instanceof QuickRechargeActivity + || (currentActivity instanceof P2PMessageActivity && StrU.equals(((P2PMessageActivity) currentActivity).getSessionId(), imMessage.getFromAccount()))) { + break; + } + View view = LayoutInflater.from(currentActivity).inflate(R.layout.notice_user, null); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); + int dp14 = UiUtils.dp2px(MainActivity.this, 14f); + params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; + params.leftMargin = dp14; + params.rightMargin = dp14; + params.topMargin = StatusBarUtil.getStatusBarHeight(MainActivity.this) + UiUtils.dp2px(MainActivity.this, 8f); + TextView tvNoticeNickname = view.findViewById(R.id.tvNoticeNickname); + tvNoticeNickname.setText(imMessage.getFromNick()); + TextView tvNoticeContent = view.findViewById(R.id.tvNoticeContent); + SimpleDraweeView ivNoticeAvatar = view.findViewById(R.id.ivNoticeAvatar); + NimUserInfo nimUserInfo = NIMClient.getService(UserService.class).getUserInfo(imMessage.getFromAccount()); + if (nimUserInfo != null) { + tvNoticeNickname.setText(nimUserInfo.getName()); + ivNoticeAvatar.setImageURI(StrU.getResourcePath(nimUserInfo.getAvatar(), MainActivity.this)); + } else { + List list = new ArrayList<>(); + list.add(imMessage.getFromAccount()); + NIMClient.getService(UserService.class).fetchUserInfo(list).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List param) { + tvNoticeNickname.setText(param.get(0).getName()); + ivNoticeAvatar.setImageURI(StrU.getResourcePath(param.get(0).getAvatar(), MainActivity.this)); + } + + @Override + public void onFailed(int code) { + } + + @Override + public void onException(Throwable exception) { + } + }); + } + + switch (imMessage.getMsgType()) { + case image: + tvNoticeContent.setText("[图片]"); + break; + case audio: + tvNoticeContent.setText("[语音]"); + break; + case custom: + MsgAttachment attachment = imMessage.getAttachment(); + CustomAttachment customAttachment = (CustomAttachment) attachment; + if (customAttachment != null) { + if (customAttachment.getType() == 14) { + GiftAttachment giftAttachment = (GiftAttachment) customAttachment; + if (giftAttachment.getFrom_uid() != SPUtils.getInt(getApplicationContext(), ConsUser.USER_ID)) { + tvNoticeContent.setText("[收到礼物]"); + } else { + return; + } + } else { + return; + } + } + break; + default: + tvNoticeContent.setText(imMessage.getContent()); + break; + } + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + removeView(view); + } + }, 5000); + + GestureDetector gestureDetector = new GestureDetector(MainActivity.this, new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapUp(MotionEvent e) { + NimUIKit.startP2PSession(currentActivity, imMessage.getFromAccount()); + removeView(view); + return true; + } + + @Override + public boolean onDown(MotionEvent e) { + return true; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (e1 != null) { + if (e2.getY() < e1.getY() && e1.getY() - e2.getY() >= 30) { + return true; + } + } + return false; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if (e1 != null) { + if (e2.getY() < e1.getY() && e1.getY() - e2.getY() >= 60) { + removeView(view); + return true; + } + } + return false; + } + }); + + view.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return gestureDetector.onTouchEvent(event); + } + }); + currentActivity.addContentView(view, params); + } + } + } + }; + + private void removeView(View view) { + view.setVisibility(View.GONE); + //获取View父层级移除View + if (view.getParent() instanceof ViewGroup) { + ((ViewGroup) (view.getParent())).removeView(view); + } + } + + private void adDialog() { + MainManager.adDialog(this, new HttpUiCallBack() { + @Override + public void onSuccess(final BaseActivity activity, final DialogAdBean result, String message) { + if (result.getAdvert().getStatus() != 1) { +// getKidModel(0); + return; + } + View inflate = View.inflate(activity, R.layout.dialog_ad, null); + final AlertDialog alertDialog = new AlertDialog.Builder(activity).setView(inflate).create(); + alertDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); + final ImageView image = inflate.findViewById(R.id.dialog_ad_imageView); + final ImageView dialog_ad_clear = inflate.findViewById(R.id.dialog_ad_clear); + Point outSize = new Point(); + activity.getWindowManager().getDefaultDisplay().getSize(outSize); + image.getLayoutParams().width = outSize.x * 3 / 4; +// image.getLayoutParams().height = outSize.x * 2 / 3; + Glide.with(activity) + .load(StrU.getResourcePath(result.getAdvert().getImage(), activity)) + .into(new SimpleTarget() { + @Override + public void onResourceReady(Drawable resource, Transition transition) { + image.setImageDrawable(resource); + dialog_ad_clear.setVisibility(View.VISIBLE); + + image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + JumpUtils.jump(result.getAdvert().getLink_type(), result.getAdvert().getLink_url(), activity); + } + }); + } + }); + + dialog_ad_clear.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + alertDialog.dismiss(); + } + }); + alertDialog.show(); + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + private void notificationRun() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (!NotificationsUpUtils.isEnableV26(this)) { + notificationDialog(); + LongSpUtils.saveLong(this, "time", System.currentTimeMillis()); + } + } else { + if (!NotificationsUtils.isNotificationEnabled(this)) { + notificationDialog(); + LongSpUtils.saveLong(this, "time", System.currentTimeMillis()); + } + } + } + + private void notificationDialog() { + final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setTitle("提示"); + builder.setMessage("检测到您没有打开通知权限,可能不能接听视频和回复消息,请打开"); + builder.setCancelable(false); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mAlertDialog.dismiss(); + Intent localIntent = new Intent(); + localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (Build.VERSION.SDK_INT >= 9) { + localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); + localIntent.setData(Uri.fromParts("package", MainActivity.this.getPackageName(), null)); + } else if (Build.VERSION.SDK_INT <= 8) { + localIntent.setAction(Intent.ACTION_VIEW); + + localIntent.setClassName("com.android.settings", + "com.android.settings.InstalledAppDetails"); + + localIntent.putExtra("com.android.settings.ApplicationPkgName", + MainActivity.this.getPackageName()); + } + startActivity(localIntent); + } + }); + + builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mAlertDialog.dismiss(); + } + }); + + mAlertDialog = builder.create(); + //显示 + mAlertDialog.show(); + + Button buttonPos = mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE); + buttonPos.setTextColor(getResources().getColor(R.color.black)); + + Button buttonNeg = mAlertDialog.getButton(DialogInterface.BUTTON_NEGATIVE); + buttonNeg.setTextColor(getResources().getColor(R.color.black)); + } + + @TargetApi(Build.VERSION_CODES.O) + private void createNotificationChannel(String channelId, String channelName, int importance) { + NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); + channel.setShowBadge(true); + NotificationManager notificationManager = (NotificationManager) getSystemService( + NOTIFICATION_SERVICE); + notificationManager.createNotificationChannel(channel); + } + + private void getCallInfoFromRoom(int roomId) { + MainManager.getCallInfoFromRoom(this, roomId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, CallBean result, String message) { + if (!(result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)) { + if (!StrU.isEmpty(result.getSocket_url())) { + Intent intent = new Intent(MainActivity.this, AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", false); + intent.putExtra("callType", result.getCall_type()); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getFrom_avatar()); + intent.putExtra("nickName", result.getFrom_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getFrom_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("free_num", result.getFree_num()); + if (result.getGuard() != null) { + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + } + if (!isAppOnForeground(activity)) { + PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(activity, 0, + intent, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationManager systemService = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + String channel_id = "CHANNEL_ID12"; + Notification notificationBuilder = new NotificationCompat.Builder(activity, channel_id) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentTitle(result.getFrom_nickname()) + .setContentText("邀请您通话") + .setPriority(NotificationCompat.PRIORITY_HIGH) // <--- 高优先级 + .setCategory(NotificationCompat.CATEGORY_CALL) + .setContentIntent(fullScreenPendingIntent) + .setFullScreenIntent(fullScreenPendingIntent, true)// <--- 全屏 intent + .setAutoCancel(true) + .build(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(channel_id, "来电提醒", + NotificationManager.IMPORTANCE_HIGH); + channel.setDescription("来电提醒"); + channel.setSound(Uri.parse("android.resource://" + activity.getPackageName() + "/" + R.raw.call_bg), Notification.AUDIO_ATTRIBUTES_DEFAULT); + channel.enableLights(true); + channel.setLightColor(Color.RED); + channel.enableVibration(true); + channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); + systemService.createNotificationChannel(channel); + } + systemService.notify(mCallID, notificationBuilder); + } + startActivity(intent); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(MainActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(MainActivity.this, "请重试"); + } + }); + } + + //true 在前台 + public static boolean isAppOnForeground(Context context) { + ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService( + Context.ACTIVITY_SERVICE); + String packageName = context.getApplicationContext().getPackageName(); + List appProcesses = activityManager.getRunningAppProcesses(); + if (appProcesses == null) + return false; + for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { + if (appProcess.processName.equals(packageName) + && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { + return true; + } + } + return false; + } + + + private void initView() { + mBottomTab = (BottomTab) findViewById(R.id.main_bottom_tab); + mBottomTab.setOnTabClickListener(new BottomTab.TabClickListener() { + @Override + public void onClick(int position, int currentPosition) { + if ((UserManager.getUserInfo().getIs_anchor() != 1 || UserManager.getUserInfo().getIs_face_status() != 1) && UserManager.getUserInfo().isWomen()) { + new GirlAuthDialog(MainActivity.this).show(); + } + if (position == currentPosition) { //第二次点击 + if (position == 0) { + if (isOne) { + if (null != mMainRecommendFragment) { + mMainRecommendFragment.clickRefresh(); + } + } + isOne = true; + } else if (position == 1) { + if (null != mDynamicViewPagerFragment) { + mDynamicViewPagerFragment.clickRefresh(); + } + } + } else if (position == 0) { //重新点击回来,检测版本更新 + checkUpdate(); + } else if (position == 3) { + // MaleToast.showMessage(MainActivity.this,"点击了消息"); + getGreet(); + + } + + } + }); + + + Intent intent = getIntent(); + int isRegister = intent.getIntExtra("isRegister", 0); + isLogin = intent.getIntExtra("isLogin", 0); +// if (isRegister == 1) { +// showAttentionDialog(); +// } + + mToastLayout = findViewById(R.id.toast_layout); + + mLlRecharge = findViewById(R.id.ll_recharge); + mSvRechargeAvatar = findViewById(R.id.sv_recharge_avatar); + mTvRechargeName = findViewById(R.id.tv_recharge_name); + mTvRechargeTotal = findViewById(R.id.tv_recharge_total); + + mRlSend = findViewById(R.id.rl_send); + mSvSendAvatar = findViewById(R.id.sv_send_avatar); + mTvSendName = findViewById(R.id.tv_send_name); + mTvReceiveName = findViewById(R.id.tv_receive_name); + mSvReceiveAvatar = findViewById(R.id.sv_receive_avatar); + mSvGift = findViewById(R.id.sv_gift); + mTvGiftTotal = findViewById(R.id.tv_gift_total); + + vipLayout = findViewById(R.id.vipLayout); + memberUserAvatar = findViewById(R.id.memberUserAvatar); + memberUserNameLabel = findViewById(R.id.memberUserNameLabel); + } + + private int mPage = 1; + + private void showAttentionDialog() { + //华为审核不要推荐弹窗,审核过不了 + String market = DeviceManager.getInstance().getApplicationMarket(); + if (market != null && market.equals("huawei")) { + return; + } + MainManager.attentionDialogList(this, mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final AttentionDialogBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (result.getList().size() != 0) { + mAttentionDialog = new AttentionDialog(MainActivity.this); + mAttentionDialog.setData(result.getList()); + mAttentionDialog.setOnClickAttention(new AttentionDialog.OnClickAttention() { + @Override + public void onClickChange() { + mPage++; + MainManager.attentionDialogList(MainActivity.this, mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, AttentionDialogBean result, String message) { + if (null != result) { + if (null != result.getList()) { + int size = result.getList().size(); + if (size == 0) { + MaleToast.showMessage(MainActivity.this, "没有更多了"); + } else { + mAttentionDialog.setData(result.getList()); + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClickOneKeyAttention(String uids) { + if (!TextUtils.isEmpty(uids)) { + MainManager.batchFollow(MainActivity.this, uids, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + mAttentionDialog.dismiss(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } else { + MaleToast.showMessage(MainActivity.this, "至少关注一人"); + } + } + + }); + + mAttentionDialog.show(); + } + + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + + + } + + public void showCloseGreetDialog() { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(MainActivity.this); + customAlertDialog.setTitle("遇见你的缘分"); + customAlertDialog.setContent("开启缘分,对你心动的女生将会主动联系你"); + customAlertDialog.setRightBtnText("免费开启");//henxinjujue + customAlertDialog.setLeftBtnText("狠心拒绝");//"mianfeikaiqi" + customAlertDialog.setCanceledOnTouchOutside(false); + customAlertDialog.show(); + is_close_greet_dialog_show = true; + customAlertDialog.setOnDialogClickListener(new CustomAlertDialog.OnDialogLeftClickListener() { + @Override + public void leftClick() { + customAlertDialog.dismiss(); + } + }, new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + closeGreet(); + } + }); + } + + private void addFragments() { + int marketStatus = NoClearSPUtils.getInt(this, Constans.MARKET_STATUS, 0); + if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { + if (swipeCardFragment == null) { + swipeCardFragment = new SwipeCardFragment(); + } + } else { + if (luckFragment == null) { + luckFragment = new LuckFragment(); + } + } + if (mDynamicViewPagerFragment == null) { + mDynamicViewPagerFragment = new DynamicViewPagerFragment(); + } + if (mMainRecommendFragment == null) { + mMainRecommendFragment = new MainRecommendFragment(); + } + if (mMainMessageFragment == null) { + mMainMessageFragment = new MainMessageFragment(); + } + if (mSettingFragment == null) { + mSettingFragment = new SettingFragment(); + } + + if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { + mBottomTab.addTab(swipeCardFragment); + } else { + mBottomTab.addTab(luckFragment); + } + mBottomTab.addTab(mDynamicViewPagerFragment); + mBottomTab.addTab(mMainRecommendFragment); + mBottomTab.addTab(mMainMessageFragment); + mBottomTab.addTab(mSettingFragment); + if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { + mBottomTab.change(0); + } else { + if (UserManager.getUserInfo().isWomen()) { + mBottomTab.change(0); + } else { + mBottomTab.change(2); + } + } + } +// +// @Override +// protected void onSaveInstanceState(Bundle outState) { +// outState.putInt("fragment_id", mBottomTab.getTabIndex()); +// super.onSaveInstanceState(outState); +// } +// +// @Override +// protected void onRestoreInstanceState(Bundle savedInstanceState) { +// super.onRestoreInstanceState(savedInstanceState); +// FragmentManager mFragmentManager = getSupportFragmentManager(); +// int marketStatus = NoClearSPUtils.getInt(this, Constans.MARKET_STATUS, 0); +// if (marketStatus == 0) { +// swipeCardFragment = (SwipeCardFragment) mFragmentManager.findFragmentByTag(SwipeCardFragment.class.getName()); +// } else { +// luckFragment = (LuckFragment) mFragmentManager.findFragmentByTag(LuckFragment.class.getName()); +// } +// mDynamicViewPagerFragment = (DynamicViewPagerFragment) mFragmentManager +// .findFragmentByTag(DynamicViewPagerFragment.class.getName()); +// mMainRecommendFragment = (MainRecommendFragment) mFragmentManager +// .findFragmentByTag(MainRecommendFragment.class.getName()); +// mMainMessageFragment = (MainMessageFragment) mFragmentManager +// .findFragmentByTag(MainMessageFragment.class.getName()); +// mSettingFragment = (SettingFragment) mFragmentManager +// .findFragmentByTag(SettingFragment.class.getName()); +// if (mBottomTab != null && mBottomTab.mFragmentList.size() == 0) { +// if (marketStatus == 0) { +// mBottomTab.addTab(swipeCardFragment); +// } else { +// mBottomTab.addTab(luckFragment); +// } +// mBottomTab.addTab(mDynamicViewPagerFragment); +// mBottomTab.addTab(mMainRecommendFragment); +// mBottomTab.addTab(mMainMessageFragment); +// mBottomTab.addTab(mSettingFragment); +// } +// if (mBottomTab != null) { +// mBottomTab.change(savedInstanceState.getInt("fragment_id")); +// } +// } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + //如果是返回键 + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { + //重写返回键 + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addCategory(Intent.CATEGORY_HOME); + startActivity(intent); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + if (REQUEST_FINISH == requestCode && RESULT_OK == resultCode) { + finish(); + } else if (REQUEST_FINISH == requestCode && RESULT_LOGIN == resultCode) { + handleLoginInfo(null); + } else if (SettingFragment.SETTING_SOCIAL_CHANGE_RESULT == resultCode && SettingFragment.SETTING_SOCIAL_REQUEST == requestCode) { + mSettingFragment.getUserInfo(); + } +// else if (requestCode == 10010 && resultCode == RESULT_OK) { +// checkIsAndroidO(); +// } + + if (null != luckFragment) { + luckFragment.onActivityResult(requestCode & 0xffff, resultCode, intent); + } + if (null != mMainRecommendFragment) { + mMainRecommendFragment.onActivityResult(requestCode & 0xffff, resultCode, intent); + } + +// if (null != mDynamicFragment) { +// mDynamicFragment.onActivityResult(requestCode, resultCode, intent); +// } + + if (null != mDynamicViewPagerFragment) { + mDynamicViewPagerFragment.onActivityResult(requestCode & 0xffff, resultCode, intent); + } + } + + private void getKidModel(final int type) { + MainManager.getIsKidModel(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, IsKidModelBean result, String message) { + if (result.getIs_open() == 1) { + if (null != mKidOpenDialog) { + mKidOpenDialog.setCancelable(false); + mKidOpenDialog.show(); + } + } else { + if (type == 0) { + Long lastTime = (Long) StorageManager.getInstance(MainActivity.this).getBean("KidModel", Long.class); + Long currentTime = System.currentTimeMillis(); + if (null == lastTime || currentTime - lastTime > 7 * 24 * 60 * 60 * 1000) { + if (null != mKidDialog) { + mKidDialog.show(); + StorageManager.getInstance(MainActivity.this) + .putBean("KidModel", currentTime); + } + } + } else if (type == 1) { + if (null != mKidOpenDialog) { + mKidOpenDialog.dismiss(); + } + } + + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void handleLoginInfo(Bundle savedInstanceState) { + checkUpdate(); + try { + NIMClient.initSDK(); + ChatManager.getInstance().kickOtherClient(); + } catch (Exception e) { + Log.i(TAG, "handleLoginInfo: 云信初始化失败"); + } +// if (savedInstanceState == null) { + addFragments(); +// } +// getKidModel(0); + isLoginViewShowed = false; + UserManager.getInstance().registerUserInfoObserver(new Observer() { + @Override + public void onSubscribe(Disposable d) { + mDisposable = d; + } + + @Override + public void onNext(BaseUserInfo userInfo) { + if (null != userInfo && userInfo.getUser_id() == 0 + && !isLoginViewShowed) { + DemoCache.clear(); + NimUIKit.logout(); + SPUtils.clear(MainActivity.this); + SysSPUtils.clear(MainActivity.this); + NIMClient.getService(AuthService.class).logout(); + SPUtils.saveString(MainActivity.this, "im_account", null); + SPUtils.saveString(MainActivity.this, "im_token", null); + SpeedWebSocket.getInstance().close(); + Intent intent = new Intent(MainActivity.this, LoginActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); +// startActivityForResult(intent, REQUEST_FINISH); + isLoginViewShowed = true; + ShareManager.getInstance().delete(MainActivity.this, new UMAuthListener() { + @Override + public void onStart(SHARE_MEDIA share_media) { + + } + + @Override + public void onComplete(SHARE_MEDIA share_media, int i, Map map) { + + } + + @Override + public void onError(SHARE_MEDIA share_media, int i, Throwable throwable) { + + } + + @Override + public void onCancel(SHARE_MEDIA share_media, int i) { + + } + }); + startActivity(intent); + finish(); + } + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + + } + }); + +// if (UserManager.getUserInfo().getGender() == 2) { +// mBottomTab.maleStyle(); +// } + } + + private void checkUpdate() { + MainManager.checkUpdate(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final SystemVersionBean result, String message) { + mUpdateDialog = new UpdateDialog(MainActivity.this, R.style.SelectiveDialog); + mUpdateDialog.setConfirmListener(new UpdateDialog.DownloadConfirmListener() { + @Override + public void onConfirm() { + PermissionDialog permissionDialog = new PermissionDialog(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}); + permissionDialog.show(); + XXPermissions.with(activity).permission(Manifest.permission.WRITE_EXTERNAL_STORAGE).request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + permissionDialog.dismiss(); + if (all) { + File file = new File(DOWNLOAD_PATH); + if (file.isFile()) { + file.delete(); + } + + if (!file.exists()) { + file.mkdirs(); + } + + MainManager.downloadNewApp(MainActivity.this, mDownloadUrl, + DOWNLOAD_PATH + "temp.apk", + new HttpCallback() { + @Override + public void onFailure(int httpStatusCode, String message, Throwable throwable) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } + } + + @Override + public void onSuccess(int httpStatusCode, String responseObject) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + if (result.getEnforce() != 1) { + mUpdateDialog.dismiss(); + } + } +// checkIsAndroidO(); + LoginUtils.install(DOWNLOAD_PATH + "temp.apk", MainActivity.this); + } + + @Override + public void onProgress(long bytesCount, long contentLength, boolean done) { + mUpdateDialog.setProgress((int) (((double) bytesCount) / contentLength * 100)); + } + }); + + } else { + if (result.getEnforce() == 1) { + finish(); + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + OnPermissionCallback.super.onDenied(permissions, never); + permissionDialog.dismiss(); + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } + } + }); + } + + @Override + public void onCancel() { + + } + }); + mUpdateDialog.setCancelable(false); + mDownloadUrl = result.getDownloadurl(); + mUpdateDialog.setInfo(result.getUpgradetext()); + mUpdateDialog.setVersionName(result.getNewversion()); + if (result.getVersioncode() > LoginUtils.getVersionCode(MainActivity.this)) { + if (result.getEnforce() == 1) { + StorageManager.getInstance(MainActivity.this) + .putBean("UpdateHintDate", null); + mUpdateDialog.setFinishHide(); + mUpdateDialog.show(); + } else { + final Long currentTime = System.currentTimeMillis(); + final Long lastTime = (Long) StorageManager.getInstance(MainActivity.this).getBean("UpdateHintDate", Long.class); + if (null == lastTime || currentTime - lastTime > 7 * 24 * 60 * 60 * 1000) { + mUpdateDialog.show(); + StorageManager.getInstance(MainActivity.this) + .putBean("UpdateHintDate", currentTime); + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void ExitApp() { + if ((System.currentTimeMillis() - mExitTime) > 2000) { + MaleToast.showMessage(this, "再按一次退出"); + mExitTime = System.currentTimeMillis(); + } else { + System.exit(0); + } + + } + + //监听青少年模式 + public void onEventMainThread(KidEvent event) { + int type = event.getType(); +// setKid(type, true); + getKidModel(type); //0代表 + } + + //监听到未读数后展示 + public void onEventMainThread(UnReadCountEvent event) { + int count = event.getCount(); + setNewsCount(count, event.getAvatar()); + } + + //切换到前台的监听 + public void onEventMainThread(ActiveUpdateEvent event) { + if (event.isFront()) { + activeUpdate(); + SpeedWebSocket.getInstance().sedText("{\"method\":\"onlineTimeStart\"}"); + } else { + SpeedWebSocket.getInstance().sedText("{\"method\":\"onlineTimeStop\"}"); + } + } + + public void onEventMainThread(RegisterInfoEvent event) { + if (event.getNewerStatus() == 0) { + if (NoClearSPUtils.getInt(this, Constans.MARKET_STATUS) == 1 && SPUtils.getInt(this, ConsUser.TYPE) != 2 && isLogin == 0) { + adDialog(); + } +// getKidModel(0); + } + } + + //切换到前台的监听 + public void onEventMainThread(NotificationEvent event) { + VideoRequestBean videoRequestBean = event.getCustomNotification(); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onEventMainThread: 收到消息了 " + videoRequestBean.getId()); + if (null != videoRequestBean) { + if (11 == videoRequestBean.getId()) { + String callTime = videoRequestBean.getData().getCallTime(); + + if (!TextUtils.isEmpty(callTime)) { + long currentTimeMillis = TimeZoneUtils.getTime() / 1000; +// long currentTimeMillis = System.currentTimeMillis() / 1000; + long time = Long.parseLong(callTime); + long timeValue = currentTimeMillis - time; + if (timeValue <= 180 && !BaseApplication.getInstance().isVideo()) { + String roomId = videoRequestBean.getData().getRoomid(); + if (!TextUtils.isEmpty(roomId)) { + int room_id = Integer.parseInt(roomId); + getCallInfoFromRoom(room_id); + } + } + } + } else if (10 == videoRequestBean.getId()) { + + boolean messageNotice = NoClearSPUtils.getBoolean(this, Constant.NEW_MESSAGE_NOTICE, true); + + if (messageNotice) { + if (!BaseApplication.getInstance().isVideo()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String channelId = "customcaicai"; + String channelName = "私语系统通知"; + int importance = NotificationManager.IMPORTANCE_HIGH; + createNotificationChannel(channelId, channelName, importance); + } + + + Intent intent = new Intent(MainActivity.this, NotificationClickReceiver.class); + intent.putExtra("linkType", videoRequestBean.getData().getLink_type()); + intent.putExtra("linkUrl", videoRequestBean.getData().getLink_url()); + PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + + NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + + Notification customNotification = new NotificationCompat.Builder(MainActivity.this, "customcaicai") + .setContentTitle(videoRequestBean.getData().getTitle()) + .setContentText(videoRequestBean.getData().getContent()) + .setWhen(System.currentTimeMillis()) + .setSmallIcon(R.mipmap.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) + .setAutoCancel(true) + .setContentIntent(pendingIntent) //设置点击响应 + .build(); + manager.notify(1, customNotification); + } + } + } else if (12 == videoRequestBean.getId() || 13 == videoRequestBean.getId()) { + if (NoClearSPUtils.getBoolean(MainActivity.this, Constant.FLUTTER_NOTICE, true)) { + long time = videoRequestBean.getData().getTime(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + long timeValue = currentTimeMillis - time; + if (timeValue <= 1800 && !BaseApplication.getInstance().isVideo()) { + if (BaseApplication.getInstance().isFront()) { +// ClickToastUtils.showToast(this, videoRequestBean, Toast.LENGTH_LONG); + warmAnimator(videoRequestBean); + } + } + } + } + } + } + + private void warmAnimator(final VideoRequestBean videoRequestBean) { + + if (null != videoRequestBean) { + if (12 == videoRequestBean.getId()) { //充值消息 + mLlRecharge.setVisibility(View.VISIBLE); + vipLayout.setVisibility(View.GONE); + mRlSend.setVisibility(View.GONE); + mSvRechargeAvatar.setImageURI(StrU.getResourcePath(videoRequestBean.getData().getAvatar(), this)); + mTvRechargeName.setText(videoRequestBean.getData().getNickname()); + mTvRechargeTotal.setText("充值了" + videoRequestBean.getData().getAmount() + "金币"); + + mLlRecharge.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(MainActivity.this, TransActivity.class); + intent.putExtra("userId", videoRequestBean.getData().getId() + ""); + startActivity(intent); + } + }); + } else if (13 == videoRequestBean.getId()) { //赠送礼物消息 + mRlSend.setVisibility(View.VISIBLE); + mLlRecharge.setVisibility(View.GONE); + vipLayout.setVisibility(View.GONE); + mSvSendAvatar.setImageURI(StrU.getResourcePath(videoRequestBean.getData().getAvatar(), this)); + mTvSendName.setText(videoRequestBean.getData().getNickname()); + mTvReceiveName.setText(videoRequestBean.getData().getTonickname()); + mSvReceiveAvatar.setImageURI(StrU.getResourcePath(videoRequestBean.getData().getToavatar(), this)); + mSvGift.setImageURI(StrU.getResourcePath(videoRequestBean.getData().getGiftimg(), this)); + mTvGiftTotal.setText("X " + videoRequestBean.getData().getGifttotal()); + + mSvSendAvatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(MainActivity.this, TransActivity.class); + intent.putExtra("userId", videoRequestBean.getData().getId() + ""); + startActivity(intent); + } + }); + + mSvReceiveAvatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(MainActivity.this, TransActivity.class); + intent.putExtra("userId", videoRequestBean.getData().getToid() + ""); + startActivity(intent); + } + }); + + mRlSend.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(MainActivity.this, TransActivity.class); + intent.putExtra("userId", videoRequestBean.getData().getToid() + ""); + startActivity(intent); + } + }); + } else if (10 == videoRequestBean.getId()) { + //会员 + mLlRecharge.setVisibility(View.GONE); + vipLayout.setVisibility(View.VISIBLE); + mRlSend.setVisibility(View.GONE); + memberUserAvatar.setImageURI(StrU.getResourcePath(videoRequestBean.getData().getAvatar(), this)); + memberUserNameLabel.setText(videoRequestBean.getData().getNickname()); + vipLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(MainActivity.this, TransActivity.class); + intent.putExtra("userId", videoRequestBean.getData().getId() + ""); + startActivity(intent); + } + }); + } + + ObjectAnimator.ofFloat(mToastLayout, "translationX", 0F, 2000F).setDuration(0).start(); + mToastLayout.setVisibility(View.VISIBLE); + ObjectAnimator.ofFloat(mToastLayout, "translationX", 2000F, 0F).setDuration(2000).start(); + + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + ObjectAnimator.ofFloat(mToastLayout, "translationX", 0F, 2000F).setDuration(2000).start(); + } + }, 4000); + } + } + + @Override + public void onDestroy() { + NIMClient.getService(MsgServiceObserve.class).observeReceiveMessage(incomingMessageObserver, false); +// NIMClient.getService(MsgServiceObserve.class) +// .observeRecentContact((com.netease.nimlib.sdk.Observer>) mMessageObserver, false); + EventBus.getDefault().unregister(this); + super.onDestroy(); + + if (null != mDisposable) { + mDisposable.dispose(); + } + + if (null != mUpdateDialog) { + mUpdateDialog.dismiss(); + } + + if (null != mAttentionDialog) { + mAttentionDialog.dismiss(); + } + + CitySPUtils.clear(this); + } + + private void queryCities() { + GlobalManager.queryCity(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + LinkedTreeMap cityBeanList = (LinkedTreeMap) result; + //cityBeanList = gson.fromJson(result, cityBeanList.getClass()); + GlobalManager.setCityMap(cityBeanList); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + public void setNewsCount(int num, String avatar) { + mBottomTab.setNewCount(num, avatar); + } + + public void setSettingsCount(int num) { + mBottomTab.setSettingsCount(num); + } + + + /** + * 用户活跃更新 + */ + private void activeUpdate() { + MainManager.activeUpdate(this, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void getGlobalConfig() { + MainManager.getGlobalConfig(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GlobalConfigBean result, String message) { + UserManager.setGlobalConfigInfo(result); + StorageManager.getInstance(MainActivity.this).putString(Constans.DEFAULT_PAY_TYPE, result.getConfig().getDefault_pay_type()); + SysSPUtils.saveString(MainActivity.this, ConsUser.SYSID, result.getConfig().getSysId()); + SysSPUtils.saveString(MainActivity.this, ConsUser.SERVID, result.getConfig().getServId()); + NoClearSPUtils.saveString(MainActivity.this, ConsUser.SERVIDS, result.getConfig().getServIds()); + NoClearSPUtils.saveString(MainActivity.this, ConsUser.RESOURCE_VERSION, result.getConfig().getResource_version()); + NoClearSPUtils.saveString(MainActivity.this, ConsUser.WECHAT_STATUS, result.getConfig().getWechat_switch()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.SEND_VIDEO_MAX_NUM, result.getConfig().getSend_video_porn_img_num()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.SEND_VIDEO_INTERVAL, result.getConfig().getSend_video_porn_interval()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.CHAT_REAL_NAME_SWITCH, result.getConfig().getChat_real_name_switch()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.DYNAMIC_REAL_NAME_SWITCH, result.getConfig().getDynamic_real_name_switch()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.RISK_FACE_STATUS, result.getConfig().getRisk_face_status()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.TURNTABLE_COUPON_SWITCH, result.getConfig().getTurntable_coupon_switch()); + EventBus.getDefault().post(new TurntableEvent(result.getConfig().getTurntable_switch())); + if (result.getAgora() != null) { + NoClearSPUtils.saveString(MainActivity.this, ConsUser.AGORA_APP_ID, result.getAgora().getAppid()); + } + + if (result.getVersion() != null) { + NoClearSPUtils.saveInt(activity, Constans.MARKET_STATUS, result.getVersion().getMarket_status()); + if (luckFragment != null) { + luckFragment.setMarketStatus(result.getVersion().getMarket_status()); + } + } + + if (result.getProfile() != null) { + String profile = new Gson().toJson(result.getProfile()); + SysSPUtils.saveString(MainActivity.this, ConsUser.PROFILE, profile); + } + + if (result.getGreet() != null) { + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.SEND_USER_TOTAL, result.getGreet().getSend_user_total()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.GREET_DAY_TOTAL, result.getGreet().getGreet_day_total()); + NoClearSPUtils.saveInt(MainActivity.this, ConsUser.GREET_GAP_HOUR, result.getGreet().getGreet_gap_hour()); + } + + //新人福利弹窗 +// if (result.getNew_user_video_card() != null && result.getNew_user_video_card().size() > 0) { +//// if (!TextUtils.equals(StorageManager.getInstance(activity).getString(SPUtils.getInt(activity, ConsUser.USER_ID) + Constans.NEWCOMER_WELFARE), TimeUtil.getDay())) { +// NewcomerWelfareDialog newcomerWelfareDialog = new NewcomerWelfareDialog(activity, result.getNew_user_video_card()); +// newcomerWelfareDialog.show(); +//// StorageManager.getInstance(activity).putString(SPUtils.getInt(activity, ConsUser.USER_ID) + Constans.NEWCOMER_WELFARE, TimeUtil.getDay()); +//// } +// } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void freeAnchor() { + MainManager.freeAnchor(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FreeVideoBean result, String message) { + if (result.show_status == 1 && result.anchor_list.size() != 0) { + new FreeVideoDialog(activity, result.anchor_list).show(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onFailure: " + tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onException: " + e.getMessage()); + } + }); + } + + @Override + public void onIdsValid(String ids) { + try { + runOnUiThread(() -> { + SPUtils.saveString(MainActivity.this, "OAID", ids); + }); + } catch (Exception e) { + } + } + + // 速配相关 + @Override + public void onMessageListener(int code, String method, String data, String message) { + if (ConstUrl.LOGDEBUG) + Log.i(TAG, "onMessageListener:" + "---code--->" + code + "-----method-------->" + method + "----data---->" + data + "----message--->" + message); + Activity activity = BaseApplication.getInstance().getTopActivity(); + switch (method) { + //开始速配 + case "startSpeed": + if (code == 1003) {//金币不足 + BaseApplication.getInstance().getRechargeInfo((BaseActivity) activity, 0); + } else if (code == 10010) {//未认证 + GirlAuthDialog dialog = new GirlAuthDialog(activity); + dialog.show(); + } + break; + //速配弹窗 + case "speedPopup": + if (!StrU.isEmpty(data)) { + SpeedInfoBean.SpeedListBean bean = new Gson().fromJson(data, SpeedInfoBean.SpeedListBean.class); + if (activity instanceof MainActivity) { + SpeedCallDialog dialog = new SpeedCallDialog(activity, bean); + dialog.show(); + } else { +// SpeedWebSocket.getInstance().sedText("{\"method\":\"refuseSpeed\",\"data\":{\"from_uid\":" + bean.getUser_id() + ",\"call_type\":" + bean.getCall_type() + "}}"); + } + } + break; + case "agreeSpeed": + //同意速配出错时提示 + if (code != 0) { + MaleToast.showMessage(activity, message); + } + break; + //开始速配 + case "speedCallCreate"://发起方 + if (!StrU.isEmpty(data)) { + CallBean result = new Gson().fromJson(data, CallBean.class); + Intent intent = new Intent(activity, AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", true); + if (result.getCall_type() == 2) { + intent.putExtra("callType", 0); + } else { + intent.putExtra("callType", 1); + } + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isSpeed", true); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + startActivity(intent); + } + break; + case "speedCallGetRoom"://接受方 + if (!StrU.isEmpty(data)) { + CallBean result1 = new Gson().fromJson(data, CallBean.class); + Intent intent1 = new Intent(MainActivity.this, AgoraWithFUVideoActivity.class); + intent1.putExtra(Constant.SOCKET_URL, result1.getSocket_url()); + intent1.putExtra("isCaller", false); + if (result1.getCall_type() == 2) { + intent1.putExtra("callType", 0); + } else { + intent1.putExtra("callType", 1); + } + intent1.putExtra("roomId", Integer.valueOf(result1.getRoom_id())); + intent1.putExtra("avatar", result1.getFrom_avatar()); + intent1.putExtra("nickName", result1.getFrom_nickname()); + intent1.putExtra("price", result1.getSkill().getPrice()); + intent1.putExtra("toUid", result1.getFrom_uid()); + intent1.putExtra("porn_check_bean_v2", result1.getPorn_checkV2()); + intent1.putExtra("free_num", result1.getFree_num()); + if (result1.getGuard() != null) { + intent1.putExtra("diff_num", result1.getGuard().getDiff_num()); + intent1.putExtra("guard_price", result1.getGuard().getGuard_price()); + } + intent1.putExtra("isSpeed", true); + if (!isAppOnForeground(activity)) { + PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(activity, 0, + intent1, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationManager systemService = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + String channel_id = "CHANNEL_ID12"; + Notification notificationBuilder = new NotificationCompat.Builder(activity, channel_id) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentTitle(result1.getFrom_nickname()) + .setContentText("邀请您通话") + .setPriority(NotificationCompat.PRIORITY_HIGH) // <--- 高优先级 + .setCategory(NotificationCompat.CATEGORY_CALL) + .setContentIntent(fullScreenPendingIntent) + .setFullScreenIntent(fullScreenPendingIntent, true)// <--- 全屏 intent + .setAutoCancel(true) + .build(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(channel_id, "来电提醒", + NotificationManager.IMPORTANCE_HIGH); + channel.setDescription("来电提醒"); + channel.setSound(Uri.parse("android.resource://" + activity.getPackageName() + "/" + R.raw.call_bg), Notification.AUDIO_ATTRIBUTES_DEFAULT); + channel.enableLights(true); + channel.setLightColor(Color.RED); + channel.enableVibration(true); + channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); + systemService.createNotificationChannel(channel); + } + systemService.notify(mCallID, notificationBuilder); + } + startActivity(intent1); + } + break; + case "push_video": + if (!StrU.isEmpty(data)) { + if (!(ActivityUtils.getTopActivity() instanceof AgoraWithFUVideoActivity) && !(ActivityUtils.getTopActivity() instanceof PushVideoActivity)) { + CallBean result = new Gson().fromJson(data, CallBean.class); + Intent intent = new Intent(activity, PushVideoActivity.class); + intent.putExtra("result", result); + startActivity(intent); + } + } + break; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainDynamicActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainDynamicActivity.java new file mode 100644 index 0000000..500b94d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainDynamicActivity.java @@ -0,0 +1,290 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.AbsListView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.dynamics.adapter.DynamicsAdapter; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.eventBus.DynamicEvent; +import com.fengliyan.tianlesue.model.dynamics.DynamicsItemBean; +import com.fengliyan.tianlesue.model.dynamics.DynamicsListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.HangUpDialog; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * Created by abby on 2018/4/22. + */ + +public class MainDynamicActivity extends BaseActivity implements View.OnClickListener { + public static int REQUEST_POST = 206; + private int mType = 0; + private LoadMoreListView mListView; + private List mImageList = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + private DynamicsAdapter mAdapter; + private int mUserId; + private String mNickName; + private BottomSelectiveDialog mSelectiveDialog; + private BottomSelectiveDialog mDeleteBottomDialog; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.fragment_dynamics); + mUserId = getIntent().getIntExtra("userId", 0); + mNickName = getIntent().getStringExtra("nickName"); + setTitleName(mNickName + "的动态"); + getDynamicList(mUserId + ""); + initView(); + } + + private void initView() { + mListView = findViewById(R.id.dynamics_list); + mAdapter = new DynamicsAdapter(this); + mAdapter.setList(mImageList); + mListView.setAdapter(mAdapter); +// mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { +// @Override +// public void onItemClick(AdapterView parent, View view, int position, long id) { +// Intent intent = new Intent(MainDynamicActivity.this, DynamicDetailActivity.class); +// intent.putExtra("dynamic_id", ((DynamicsItemBean) mAdapter.getItem(position)).getId()); +// startActivity(intent); +// } +// }); + mListView.setOnDataLoadingListener(new LoadMoreListView.OnDataLoadingListener() { + @Override + public void loading() { + //getDynamicList(mType, mPage); + } + }); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (0 != mImageList.size() && mImageList.size() % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mImageList.size() - 2) { + //getDynamicList(mType, mPage); + mPageLoad = true; + } else if (mListView.getLastVisiblePosition() <= mImageList.size() - 2) { + mPageLoad = false; + } + } + }); + + mAdapter.setOnThumbupClickedListener(new DynamicsAdapter.OnThumbupClickedListener() { + @Override + public void onClick(View v, String uid) { + thumbup(uid); + } + }); + mAdapter.setOnGiftSendListener(new DynamicsAdapter.OnGiftSendListener() { + @Override + public void onSend(DynamicsItemBean bean, int quantity) { + sendGift(bean.getId(), quantity, bean); + } + }); + + mAdapter.setOnMenuClickListener(new DynamicsAdapter.OnMenuClickListener() { + @Override + public void onMenuClicked(final int dynamicIndex) { + mSelectiveDialog = new BottomSelectiveDialog(MainDynamicActivity.this, R.style.SelectiveDialog); + + mSelectiveDialog.addSelectButton("举报", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + Intent intent = new Intent(MainDynamicActivity.this, ComplaintActivity.class); + intent.putExtra("uid", mImageList.get(dynamicIndex).getUser_id()); + intent.putExtra("type", 3); + startActivity(intent); + } + }); + + mSelectiveDialog.show(); + } + }); + mAdapter.likeDynamicCallback = new DynamicsAdapter.DynamicLikeCallback() { + @Override + public void likeDynamic(DynamicsItemBean bean) { + likeFeed(bean); + } + }; + //删除动态 + mAdapter.setOnMenuDeleteClickListener(new DynamicsAdapter.OnMenuDeleteClickListener() { + @Override + public void onMenuDelete(final int position, final List mDynamicsItemList) { + HangUpDialog hangUpDialog = new HangUpDialog(MainDynamicActivity.this, new HangUpDialog.OnHangUpListener() { + @Override + public void onHangUp() { + deleteDynamics(mDynamicsItemList.get(position).getId(), position); + } + },"您确定要删除吗?", "确定", "取消"); + hangUpDialog.show(); +// mDeleteBottomDialog = new BottomSelectiveDialog(MainDynamicActivity.this, R.style.SelectiveDialog); +// mDeleteBottomDialog.addSelectButton("删除", new BottomSelectiveDialog.OnButtonSelectListener() { +// @Override +// public void onClicked(View view, int index) { +// mDeleteBottomDialog.dismiss(); +// deleteDynamics(mDynamicsItemList.get(position).getId(), position); +// } +// }); +// mDeleteBottomDialog.show(); + } + }); + } + + void likeFeed(DynamicsItemBean bean) { + boolean isLikeParam = false; + if (bean.getIs_like() == 0) { + isLikeParam = true; + } + DynamicsManager.likeDynamic(this, bean.getId(), isLikeParam, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + bean.setIs_like(1 - bean.getIs_like()); + if (bean.getIs_like() == 1) { + bean.setLike_count(bean.getLike_count() + 1); + } else { + bean.setLike_count(bean.getLike_count() - 1); + } + mAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(MainDynamicActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(MainDynamicActivity.this, "操作失败"); + + } + }); + } + + /** + * 请求网络删除动态 + * + * @param id + */ + private void deleteDynamics(String id, final int index) { + DynamicsManager.deleteDynamics(this, id, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + mAdapter.delete(index); + MaleToast.showMessage(MainDynamicActivity.this, "删除成功"); + EventBus.getDefault().post(new DynamicEvent()); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "删除失败"); + + } + }); + } + + public void getDynamicList(String userId) { + DynamicsManager.getUserDynamicList((BaseActivity) this, userId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, DynamicsListBean result, String message) { + mImageList.addAll(result.getList()); + mPage++; + mAdapter.setList(mImageList); + mAdapter.notifyDataSetChanged(); + mListView.onNoDataLoaded(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(MainDynamicActivity.this, tip); + mListView.onNoDataLoaded(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mListView.onNoDataLoaded(); + } + }); + } + + public void thumbup(String dynamicId) { + DynamicsManager.thumbup((BaseActivity) MainDynamicActivity.this, mType, dynamicId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { +// MaleToast.showMessage(MainDynamicActivity.this, "点赞成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showMessage(MainDynamicActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showMessage(MainDynamicActivity.this, "点赞失败,请重试"); + } + }); + } + + public void sendGift(String dynamicId, final int number, final DynamicsItemBean bean) { + DynamicsManager.sendGifts(MainDynamicActivity.this, dynamicId, number, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(MainDynamicActivity.this, "礼物赠送成功"); + if (null != mAdapter) { + mAdapter.setGiftCount(number + bean.getReward_count(), bean.getId()); + mAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(MainDynamicActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(MainDynamicActivity.this, "赠送失败,请重试"); + } + }); + } + + @Override + public void onClick(View view) { + + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mSelectiveDialog && mSelectiveDialog.isShowing()) { + mSelectiveDialog.dismiss(); + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainPageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainPageActivity.java new file mode 100644 index 0000000..a424e03 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainPageActivity.java @@ -0,0 +1,552 @@ +package com.fengliyan.tianlesue.view.main; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; + +import com.airbnb.lottie.LottieAnimationView; +import com.githang.statusbar.StatusBarCompat; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.WechatDialog; +import com.fengliyan.tianlesue.view.news.im.ImUtils; +import com.fengliyan.tianlesue.view.settings.CaibeiRechargeActivity; +import com.fengliyan.tianlesue.view.settings.dialog.SelectTypeDialog; +import com.fengliyan.uikit.dialog.BottomGiftDialog; +import com.fengliyan.uikit.dialog.DialogGiftBean; +import com.fengliyan.uikit.dialog.GiftListBean; +import com.fengliyan.uikit.toast.MaleToast; + +public class MainPageActivity extends BaseActivity implements View.OnClickListener, SelectTypeDialog.OnSelectListener { + private View mMessage; + private View mGift; + private TextView mVideo; + private View mFrameLayout; + private RelativeLayout mBottomLayout; + private TextView mMessagePrivate; + private int mUid; + private int mSkillId; + private MainPageBean mMainPageBean; + private BottomGiftDialog mGiftDialog; + private boolean mBPrivate; + private LinearLayout womenLayout; + private LinearLayout menLayout; + private ImageView bottomShadow; + private TextView tv_personal_free; + private LinearLayout main_personal_page_follow; + private LinearLayout main_personal_page_wechat; + private ImageView iv_follow; + private TextView tv_follow; + private LinearLayout followBtn; + private ImageView iv_follow1; + private TextView tv_follow1; + // private BaseMessageDialog mConfirmDialog; + private LottieAnimationView animation_view; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_main_personal_page); + StatusBarCompat.setTranslucent(getWindow(), true); + StatusBarCompat.resetActionBarContainerTopMargin(getWindow()); + StatusBarCompat.setLightStatusBar(getWindow(), false); + hideTitleBar(); + initView(); + mUid = getIntent().getIntExtra("userId", 0); + String user_code = getIntent().getStringExtra("userCode"); + getMainPageData(mUid, user_code); + getGiftData(); + } + + private void initView() { + bottomShadow = findViewById(R.id.bottomShadow); + mFrameLayout = findViewById(R.id.main_personal_frame_layout); + mMessagePrivate = findViewById(R.id.main_personal_page_message_private); + mVideo = findViewById(R.id.main_personal_page_video_button); + mMessage = findViewById(R.id.main_personal_page_message); + mGift = findViewById(R.id.main_personal_page_gift); + mBottomLayout = findViewById(R.id.main_personal_page_bottom_board); + womenLayout = findViewById(R.id.womenLayout); + menLayout = findViewById(R.id.menLayout); + tv_personal_free = findViewById(R.id.tv_personal_free); + personalMainV2MainCallTipAnim(tv_personal_free); + main_personal_page_follow = findViewById(R.id.main_personal_page_follow); + main_personal_page_wechat = findViewById(R.id.main_personal_page_wechat); + iv_follow = findViewById(R.id.iv_follow); + tv_follow = findViewById(R.id.tv_follow); + followBtn = findViewById(R.id.followBtn); + iv_follow1 = findViewById(R.id.iv_follow1); + tv_follow1 = findViewById(R.id.tv_follow1); + animation_view = findViewById(R.id.animation_view); + //网络请求之前不让点击 + mVideo.setEnabled(false); + animation_view.setEnabled(false); + mMessage.setEnabled(false); + mGift.setEnabled(false); + findViewById(R.id.msgBtn).setOnClickListener(this); + main_personal_page_follow.setOnClickListener(this); + main_personal_page_wechat.setOnClickListener(this); + followBtn.setOnClickListener(this); + findViewById(R.id.followBtn).setOnClickListener(this); + findViewById(R.id.giftBtn).setOnClickListener(this); + mVideo.setOnClickListener(this); + mMessage.setOnClickListener(this); + mGift.setOnClickListener(this); + animation_view.setImageAssetsFolder("images/"); + animation_view.setAnimation("page_call_video.json"); + animation_view.playAnimation(); + animation_view.setOnClickListener(this); + } + + private final int MIN_DELAY_TIME = 5000; // 两次点击间隔不能少于1000ms + private long lastClickTime; + + public boolean isFastClick() { + boolean flag = true; + long currentClickTime = System.currentTimeMillis(); + if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) { + flag = false; + lastClickTime = currentClickTime; + } + return flag; + } + + + private void getMainPageData(final int userId, String userCode) { + MainManager.getMainPageData(((BaseActivity) this), userId, userCode, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + MainPageFragment fragment = new MainPageFragment(); + fragment.setMainPageData(result); + if (null != result.getSkill() && 0 != result.getSkill().size()) { + mSkillId = result.getSkill().get(0).getId(); + } + + mMainPageBean = result; + if (result.getInfo() != null) { + mUid = result.getInfo().getUserId(); + } + setFragment(fragment); + if (TextUtils.equals("1", result.getCan_free_call())) { + tv_personal_free.setVisibility(View.VISIBLE); + } else { + tv_personal_free.setVisibility(View.GONE); + } + if (mUid == SPUtils.getInt(MainPageActivity.this, ConsUser.USER_ID)) { + dismissControlBoard(); + } + String sysID = ""; + String serverId = ""; + if (UserManager.getGlobalConfigInfo() != null) { + sysID = UserManager.getGlobalConfigInfo().getConfig().getSysId(); + serverId = UserManager.getGlobalConfigInfo().getConfig().getServId(); + } + String userId = String.valueOf(mMainPageBean.getInfo().getUserId()); + String selfUserId = String.valueOf(UserManager.getUserInfo().getUser_id()); + //如果是oppo隐藏 + if (sysID.equals(userId) || serverId.equals(userId) || userId.equals("11") || userId.equals(selfUserId) + || mMainPageBean.getInfo().getGender() == 2 || (mMainPageBean.getContact() != null && mMainPageBean.getContact().getIf_forbidden() == 2) || "oppo".equals(DeviceManager.getInstance().getApplicationMarket()) || mMainPageBean.getContact().getWechat().getStatus() == 2) { + main_personal_page_wechat.setVisibility(View.GONE); + } + + if (mMainPageBean.getInfo().getGender() == 2) { + main_personal_page_follow.setVisibility(View.VISIBLE); + followBtn.setVisibility(View.VISIBLE); + } else { + followBtn.setVisibility(View.GONE); + main_personal_page_follow.setVisibility(View.GONE); + } +// mVideo.setEnabled(true); + mMessage.setEnabled(true); + mGift.setEnabled(true); + + int video_status = mMainPageBean.getAnchor().getVideo_status(); //视频状态 0 休息中 1 视频中 + int open_video_status = mMainPageBean.getAnchor().getOpen_video_status(); //是否开启视频接听 0 否 1 是 + int open_voice_status = mMainPageBean.getAnchor().getOpen_voice_status(); //是否开启视频接听 0 否 1 是 + if (result.getInfo().getGender() == 2) { + //men + womenLayout.setVisibility(View.VISIBLE); + menLayout.setVisibility(View.GONE); + mVideo.setText("邀请通话"); +// womenLayout.setVisibility(View.GONE); +// menLayout.setVisibility(View.VISIBLE); + } else { + womenLayout.setVisibility(View.VISIBLE); + menLayout.setVisibility(View.GONE); + mVideo.setText("与Ta通话"); + } + if (open_video_status == 0 && open_voice_status == 0) { + womenLayout.setVisibility(View.GONE); + menLayout.setVisibility(View.VISIBLE); +// mVideo.setEnabled(false); +// mVideo.setVisibility(View.GONE); + } else { + if (video_status == 0) { + mVideo.setEnabled(true); +// mVideo.setVisibility(View.VISIBLE); + animation_view.setEnabled(true); + animation_view.setVisibility(View.VISIBLE); + } else { + mVideo.setEnabled(false); + animation_view.setEnabled(true); + animation_view.setVisibility(View.VISIBLE); +// mVideo.setVisibility(View.GONE); + tv_personal_free.setVisibility(View.GONE); + womenLayout.setVisibility(View.GONE); + menLayout.setVisibility(View.VISIBLE); + } + } + mBPrivate = result.getPrivate_letter() == 2; + if (mBPrivate) { + mMessagePrivate.setText("打招呼"); + } + if (mMainPageBean.getInfo().getUserId() == SPUtils.getInt(MainPageActivity.this, ConsUser.USER_ID)) { + main_personal_page_follow.setEnabled(false); + followBtn.setEnabled(false); + } else { + if (mMainPageBean.getInfo().getIs_follow() == 0) { + main_personal_page_follow.setEnabled(true); + followBtn.setEnabled(true); + } else { + main_personal_page_follow.setEnabled(true); + tv_follow.setText("已关注"); + iv_follow.setImageResource(R.mipmap.userhome_follow1); + followBtn.setEnabled(true); + tv_follow1.setText("已关注"); + iv_follow1.setImageResource(R.mipmap.userhome_follow1); + } + } +// mVideo.setEnabled(result.getAnchor().getOpen_video_status() == 1 ? true : false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(MainPageActivity.this, tip); + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(MainPageActivity.this, "主页数据获取失败"); + + } + }); + } + + private void setFragment(Fragment fragment) { + FragmentActivity fragmentActivity = (FragmentActivity) this; + try { + if (!fragment.isAdded()) { + fragmentActivity.getSupportFragmentManager(). + beginTransaction(). + add(R.id.main_personal_frame_layout, fragment). + show(fragment). + commitAllowingStateLoss(); + + } else { + fragmentActivity.getSupportFragmentManager(). + beginTransaction(). + show(fragment). + commitAllowingStateLoss(); + + } + } catch (IllegalStateException e) { + fragmentActivity.getSupportFragmentManager(). + beginTransaction(). + show(fragment). + commit(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); +// if (null != mConfirmDialog && mConfirmDialog.isShowing()) { +// mConfirmDialog.dismiss(); +// } + } + + private void getGiftData() { + MainManager.getGiftBeans(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + mGiftDialog = new BottomGiftDialog(MainPageActivity.this, + R.style.SelectiveDialog); + + mGiftDialog.setGiftListBean(result); + mGiftDialog.setOnGiftItemClickedListener(new BottomGiftDialog.OnGiftItemClickedListener() { + @Override + public void onGiftClicked(final DialogGiftBean bean) { +// mConfirmDialog = new BaseMessageDialog.Builder(MainPageActivity.this) +// .setMessage("确定赠送礼物?").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialogInterface, int i) { +// mConfirmDialog.dismiss(); +// } +// }).setPositiveButtonListener(new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialogInterface, int i) { +// mConfirmDialog.dismiss(); +// sendGift(mUid, bean.getId()); +// } +// }).build(); +// mConfirmDialog.show(); + + if (null != bean) { + sendGift(mUid, bean.getId()); + } + } + + @Override + public void onWalletClicked() { + Intent intent = new Intent(MainPageActivity.this, CaibeiRechargeActivity.class); + startActivity(intent); + } + }); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void sendGift(int toUid, int giftId) { + MainManager.sendGift(this, 1, toUid, giftId, 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + if (null != mGiftDialog) { + mGiftDialog.setCoin(result.getCoin() + ""); + mGiftDialog.dismiss(); + } + + MaleToast.showMessage(MainPageActivity.this, "赠送成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(MainPageActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(MainPageActivity.this, "赠送失败"); + } + }); + } + + @Override + public void onClick(View view) { + if (view == mVideo || view == animation_view) { + if (!isFastClick()) { + SelectTypeDialog selectTypeDialog = new SelectTypeDialog(this); + selectTypeDialog.setSelectListener(this); + selectTypeDialog.show(); + +// getCallInfo(); +// Intent intent = new Intent(MainPageActivity.this, VideoActivity.class); +// intent.putExtra("toUid", mUid); +// intent.putExtra("skillId", mSkillId); +// intent.putExtra("isCaller", true); +// startActivity(intent); + } + } else if (view == mMessage || view.getId() == R.id.msgBtn) { + if (mBPrivate) + ImUtils.sendIMHello(this, mUid + ""); + else { + NimUIKit.startP2PSession(this, mUid + ""); + + } + // + } else if (view == mGift || view.getId() == R.id.giftBtn) { + if (null != mGiftDialog) { + mGiftDialog.show(); + } + } else if (view.getId() == R.id.followBtn || view.getId() == R.id.main_personal_page_follow) { + focus(); + } else if (view == main_personal_page_wechat) { + WechatDialog dialog = new WechatDialog(this, mMainPageBean); + dialog.show(); + } + } + + private void focus() { + DynamicsManager.follow(this, mMainPageBean.getInfo().getUserId() + "", + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + main_personal_page_follow.setEnabled(true); //不能取消关注 + followBtn.setEnabled(true); //不能取消关注 + if (StrU.equals("add", result.getAction())) { + iv_follow.setImageResource(R.mipmap.userhome_follow1); + tv_follow.setText("已关注"); + tv_follow1.setText("已关注"); + iv_follow1.setImageResource(R.mipmap.userhome_follow1); + MaleToast.showMessage(MainPageActivity.this, "关注成功"); + } else { + iv_follow.setImageResource(R.mipmap.userhome_follow); + tv_follow.setText("关注"); + tv_follow1.setText("关注"); + iv_follow1.setImageResource(R.mipmap.userhome_follow); + MaleToast.showMessage(MainPageActivity.this, message); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(MainPageActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(MainPageActivity.this, "关注失败"); + } + }); + } + + private void getCallInfo(int callType) { + MainManager.getCallInfo(this, mUid, mSkillId, callType, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(MainPageActivity.this, AgoraWithFUVideoActivity.class); + + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + + intent.putExtra("isCaller", true); + intent.putExtra("callType", callType); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); +// intent.putExtra("toUid", mUid); +// intent.putExtra("skillId", mSkillId); + + startActivity(intent); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private void dismissControlBoard() { + mBottomLayout.setVisibility(View.GONE); + tv_personal_free.setVisibility(View.GONE); + bottomShadow.setVisibility(View.GONE); + } + + //视频通话 + @Override + public void selectVideo() { + getCallInfo(0); + } + + //语音通话 + @Override + public void selectVoice() { + getCallInfo(1); + } + + public static void personalMainV2MainCallTipAnim(TextView imageView) { + float bigValue = 1.1f; + float middleValue = 1.0f; + float smallValue = 0f; + ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView, "scaleX", smallValue, bigValue); + ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageView, "scaleY", smallValue, bigValue); + ObjectAnimator animator3 = ObjectAnimator.ofFloat(imageView, "scaleX", bigValue, middleValue); + ObjectAnimator animator4 = ObjectAnimator.ofFloat(imageView, "scaleY", bigValue, middleValue); + + ObjectAnimator animator5 = ObjectAnimator.ofFloat(imageView, "scaleX", middleValue, 1.06f); + ObjectAnimator animator6 = ObjectAnimator.ofFloat(imageView, "scaleY", middleValue, 1.06f); + ObjectAnimator animator7 = ObjectAnimator.ofFloat(imageView, "scaleX", 1.06f, middleValue); + ObjectAnimator animator8 = ObjectAnimator.ofFloat(imageView, "scaleY", 1.06f, middleValue); + + ObjectAnimator animator9 = ObjectAnimator.ofFloat(imageView, "scaleX", middleValue, 1.02f); + ObjectAnimator animator10 = ObjectAnimator.ofFloat(imageView, "scaleY", middleValue, 1.02f); + ObjectAnimator animator11 = ObjectAnimator.ofFloat(imageView, "scaleX", 1.02f, middleValue); + ObjectAnimator animator12 = ObjectAnimator.ofFloat(imageView, "scaleY", 1.02f, middleValue); + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.setDuration(850); + //动画1,2同时执行 + animatorSet.play(animator1).with(animator2); + //动画2执行完成后执行动画3 + animatorSet.play(animator3).after(animator2); + animatorSet.play(animator3).with(animator4); + + animatorSet.play(animator5).after(animator4); + animatorSet.play(animator5).with(animator6); + + animatorSet.play(animator7).after(animator5); + animatorSet.play(animator7).with(animator8); + + animatorSet.play(animator9).after(animator7); + animatorSet.play(animator9).with(animator10); + + animatorSet.play(animator11).after(animator9); + animatorSet.play(animator11).with(animator12); + animatorSet.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + } + + @Override + public void onAnimationEnd(Animator animator) { + } + + @Override + public void onAnimationCancel(Animator animator) { + + } + + @Override + public void onAnimationRepeat(Animator animator) { + + } + }); + animatorSet.start(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainPageFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainPageFragment.java new file mode 100644 index 0000000..2799950 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainPageFragment.java @@ -0,0 +1,1164 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.airbnb.lottie.LottieAnimationView; +import com.facebook.drawee.view.SimpleDraweeView; +import com.google.android.exoplayer2.DefaultRenderersFactory; +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.ui.PlayerView; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.messaging.EventBusGiftMessage; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.main.BlackBean; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.ContactBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.model.main.GiftBean; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.utils.AnimUtils; +import com.fengliyan.tianlesue.utils.FrameAnimation; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.GuardDialog; +import com.fengliyan.tianlesue.view.base.utils.view.OtherGuardDialog; +import com.fengliyan.tianlesue.view.base.utils.view.WechatDialog; +import com.fengliyan.tianlesue.view.diooto.Diooto; +import com.fengliyan.tianlesue.view.diooto.config.DiootoConfig; +import com.fengliyan.tianlesue.view.dynamics.activity.PageVideoPlayActivity; +import com.fengliyan.tianlesue.view.main.dialog.ConfirmWXAccountDialog; +import com.fengliyan.tianlesue.view.main.utils.DefaultExoConfig; +import com.fengliyan.tianlesue.view.news.fragment.NewFragment; +import com.fengliyan.tianlesue.view.settings.InfoEditActivity; +import com.fengliyan.uikit.adboard.AdPagesManager; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.sketch.SketchImageView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + + +public class MainPageFragment extends Fragment implements View.OnClickListener { + private ViewPager mViewPager; + private View mPagerView; + private ViewGroup mGroup; + private AdPagesManager mManager; + private View mBack; + private View mMore; + private SimpleDraweeView mPhoto; + private SimpleDraweeView mOtherPhoto; + private TextView mName; + private TextView mAge; + private TextView mSubInfo; + private TextView personal_main_page_ip_province; + private TextView mSubInfoTime; + private TextView mFanNumber; + private TextView mFocusButton; + private ImageView mStatus; + private TextView mSkillScore; + private TextView mSkillSuccessRate; + private TextView mSkillCost; + private TextView tv_signer; + private View mDynamicLayout; + private SimpleDraweeView[] mDynamicImages = new SimpleDraweeView[4]; + private View mGiftLayout; + private SimpleDraweeView[] mGiftImages = new SimpleDraweeView[4]; + private View mGuardLayout; + private RelativeLayout[] mRlGuard = new RelativeLayout[5]; + private SimpleDraweeView[] mSvGuardImages = new SimpleDraweeView[5]; + private MainPageBean mMainPageBean; + private List mBanners = new ArrayList<>(); + private BottomSelectiveDialog mSelectDialog; + private boolean isFromChat; + private boolean isOnTop; + private int mChatIndex; + private List imageList = new ArrayList<>(); //新的图片路径 + private RelativeLayout mSkillLayout; +// private ImageView mIvMemberSign; + + private SimpleDraweeView iv_guard_user_avatar; + private ImageView mIv_guard; + private GuardDialog mGuardDialog; + private OtherGuardDialog mOtherGuardDialog; + private TextView mPersonal_main_page_guard_people; + private TextView mPersonal_main_page_guard_count; + private TextView mIs_black; + + private CardView cv_video; + private PlayerView personal_player; + private View view_end; + private LottieAnimationView iv_video_call; + private ExoPlayer player; + + private LinearLayout wxContainer; + private TextView lookBtn; + private TextView copyBtn; + + private ImageView tagVipImageView; + private ImageView tagSVipImageView; + private ImageView tagNewImageView; + private ImageView tagRealImageView; + private ImageView tagPhoneImageView; + FrameAnimation guardAnimation; +// StandardGSYVideoPlayer playerView; + + private TextView tv_follow_num; + private TextView tv_fans_num; + private TextView tv_scan_num; + + private void addBanner() { + mBanners.addAll(mMainPageBean.getAlbum()); + // GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_DEFAULT); +// String videoUrl = mMainPageBean.getVideo_url(); +//// if (mMainPageBean.getVideo_status() == 1) { +// View videoView = getLayoutInflater().inflate(R.layout.view_video, null); +// videoView.findViewById(R.id.holderView).setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// Intent intent = new Intent(getActivity(), QYPreviewVideoActivity.class); +// intent.putExtra("videoUrl", Constans.IMAGE_URL + videoUrl); +// startActivity(intent); +// } +// }); +// playerView = videoView.findViewById(R.id.video_player); +// playerView.setLooping(true); +// playerView.setVideoAllCallBack(new GSYSampleCallBack() { +// @Override +// public void onPrepared(String url, Object... objects) { +// super.onPrepared(url, objects); +// GSYVideoManager.instance().setNeedMute(true); +// } +// }); +// playerView.getStartButton().setAlpha(0); +// playerView.getStartButton().setVisibility(View.INVISIBLE); +// WindowManager windowManager = getActivity().getWindow().getWindowManager(); +// Point point = new Point(); +// windowManager.getDefaultDisplay().getRealSize(point); +// int width = point.x; +// int height = point.y; +// FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height); +// int top = (height - width) / 2; +//// params.setMargins(0, -top, 0, 0); +// playerView.setLayoutParams(params); +// playerView.setUp(StrU.getResourcePath(videoUrl, getActivity()), true, ""); +// playerView.startPlayLogic(); +// mManager.addVideoView(videoView); +// } + + for (String bannerBean : mBanners) { + mManager.addImageViewByUrl(StrU.getResourcePath(bannerBean, getActivity())); + imageList.add(StrU.getResourcePath(bannerBean, getActivity())); + } + + mManager.manage(); + + } + + @Override + public void onResume() { + super.onResume(); + if (player != null) { + player.play(); + } +// if (personal_player != null) { +// personal_player.onVideoResume(); +// personal_player.startPlayLogic(); +// } + } + + @Override + public void onPause() { + super.onPause(); + if (player != null) { + player.pause(); + } +// if (personal_player != null) { +// personal_player.onVideoPause(); +// } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_personal_main_page, container, false); + isFromChat = getActivity().getIntent().getBooleanExtra("isFromChat", false); + isOnTop = getActivity().getIntent().getBooleanExtra("isOnTop", false); + mChatIndex = getActivity().getIntent().getIntExtra("index", 0); + if (null == mMainPageBean) { + getActivity().finish(); + return v; + } + EventBus.getDefault().register(this); + initView(v); + return v; + } + + public MainPageFragment setMainPageData(MainPageBean mainPageBean) { + mMainPageBean = mainPageBean; + return this; + } + + private void getWeChatInfo(final String userId) { + if (mMainPageBean == null) { + return; + } + if (mMainPageBean.getContact() == null || mMainPageBean.getContact().getWechat() == null) { + try { + int wechatPrice = Integer.parseInt(mMainPageBean.getContact().getWechat().getWechat_price()); + if (mMainPageBean.getContact().getWechat().getGiftCoin() > wechatPrice) { + return; + } + } catch (NumberFormatException e) { + } + } + + SettingManager.getWeChat((BaseActivity) getActivity(), userId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ContactBean.WechatBean result, String tips) { + mMainPageBean.getContact().setWechat(result); + refreshWeChatStatus(mMainPageBean); + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + + void refreshWeChatStatus(MainPageBean mMainPageBean) { + String sysID = ""; + String serverId = ""; + if (UserManager.getGlobalConfigInfo() != null) { + sysID = UserManager.getGlobalConfigInfo().getConfig().getSysId(); + serverId = UserManager.getGlobalConfigInfo().getConfig().getServId(); + } + String userId = String.valueOf(mMainPageBean.getInfo().getUserId()); + String selfUserId = String.valueOf(UserManager.getUserInfo().getUser_id()); + if (sysID.equals(userId) || serverId.equals(userId) || userId.equals("11") || userId.equals(selfUserId) + || mMainPageBean.getInfo().getGender() == 2 || (mMainPageBean.getContact() != null && mMainPageBean.getContact().getIf_forbidden() == 2)) { + wxContainer.setVisibility(View.GONE); + } + //如果是oppo隐藏 + if ("oppo".equals(DeviceManager.getInstance().getApplicationMarket()) || mMainPageBean.getContact().getWechat().getStatus() == 2) { + wxContainer.setVisibility(View.GONE); + } + wxContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WechatDialog dialog = new WechatDialog((BaseActivity) getActivity(), mMainPageBean); + dialog.show(); + } + }); + copyBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mMainPageBean.getContact() == null) { + return; + } + ClipboardManager cm = (ClipboardManager) + getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(null, mMainPageBean.getContact().getWechat().getContent())); + MaleToast.showMessage(getActivity(), "复制成功"); + } + }); + if (mMainPageBean.getInfo().getGender() == 1 && mMainPageBean.getContact() != null) { + if (mMainPageBean.getContact().getWechat().getStatus() != 1) { + lookBtn.setText("暂未填写"); + } else { + copyBtn.setText(String.format("%s 复制", mMainPageBean.getContact().getWechat().getContent())); + } + } else { + lookBtn.setText("暂未填写"); + } + lookBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mMainPageBean.getContact() == null) { + return; + } + ConfirmWXAccountDialog dialog = new ConfirmWXAccountDialog(getActivity(), mMainPageBean.getContact().getWechat()); + dialog.show(); + try { + int price = Integer.parseInt(mMainPageBean.getContact().getWechat().getWechat_price()); + if (mMainPageBean.getContact().getWechat().getGiftCoin() >= price) { + lookBtn.setVisibility(View.GONE); + copyBtn.setVisibility(View.VISIBLE); + } + } catch (Exception e) { + } + } + }); + if (mMainPageBean.getInfo().getGender() == 1 && mMainPageBean.getContact() != null) { + lookBtn.setClickable(mMainPageBean.getContact().getWechat().getStatus() == 1); + } + } + + public void onEventMainThread(EventBusGiftMessage event) { + getWeChatInfo(mMainPageBean.getInfo().getUserId() + ""); + } + + private void initView(View v) { + + RelativeLayout rlBg = v.findViewById(R.id.rl_bg); +// LinearLayout.LayoutParams params= (LinearLayout.LayoutParams); + DisplayMetrics dm = getResources().getDisplayMetrics(); +// width = dm.widthPixels; +// height = dm.heightPixels; + rlBg.setLayoutParams(new LinearLayout.LayoutParams(dm.widthPixels, dm.widthPixels)); + + mViewPager = v.findViewById(R.id.ad_pager); + mPagerView = v.findViewById(R.id.pager_view); + mGroup = v.findViewById(R.id.view_group); + mManager = new AdPagesManager(mViewPager, mGroup, getContext()); + mManager.setOnImageClickListener(new AdPagesManager.ImageClickListener() { + @Override + public void onClick(View v, int position) { + if (null != imageList && imageList.size() != 0) { +// if (playerView != null) { +// clickImage((ArrayList) imageList, position - 1); +// } else { + clickImage((ArrayList) imageList, position); +// } + } + } + }); + + cv_video = v.findViewById(R.id.cv_video); + personal_player = v.findViewById(R.id.personal_player); + view_end = v.findViewById(R.id.view_end); + iv_video_call = v.findViewById(R.id.iv_video_call); + + wxContainer = v.findViewById(R.id.wxContainer); + lookBtn = v.findViewById(R.id.lookBtn); + copyBtn = v.findViewById(R.id.copyBtn); + refreshWeChatStatus(mMainPageBean); + mBack = v.findViewById(R.id.personal_main_page_back); + mMore = v.findViewById(R.id.personal_main_page_more); + mPhoto = v.findViewById(R.id.personal_main_page_photo); + mOtherPhoto = v.findViewById(R.id.personal_main_other_photo); + mName = v.findViewById(R.id.personal_main_page_name); + mAge = v.findViewById(R.id.personal_main_page_age); + mSubInfo = v.findViewById(R.id.personal_main_page_sub_info); + personal_main_page_ip_province = v.findViewById(R.id.personal_main_page_ip_province); + mSubInfoTime = v.findViewById(R.id.personal_main_page_sub_info_time); + mFocusButton = v.findViewById(R.id.personal_main_page_focus_button); + mFanNumber = v.findViewById(R.id.personal_main_page_fans_number); + mStatus = v.findViewById(R.id.personal_main_page_status); + mSkillSuccessRate = v.findViewById(R.id.personal_main_page_skill_success); + mSkillScore = v.findViewById(R.id.personal_main_page_skill_rate); + mSkillCost = v.findViewById(R.id.personal_main_page_skill_cost); + mDynamicLayout = v.findViewById(R.id.personal_main_page_dynamic_photo_layout); + mGiftLayout = v.findViewById(R.id.personal_main_page_gift_layout); + mSkillLayout = v.findViewById(R.id.ll_skill_layout); + tv_signer = v.findViewById(R.id.tv_signer); + mGuardLayout = v.findViewById(R.id.personal_main_page_guard_photo_layout); + mDynamicImages[0] = v.findViewById(R.id.personal_main_page_dynamic_photo_1); + mDynamicImages[1] = v.findViewById(R.id.personal_main_page_dynamic_photo_2); + mDynamicImages[2] = v.findViewById(R.id.personal_main_page_dynamic_photo_3); + mDynamicImages[3] = v.findViewById(R.id.personal_main_page_dynamic_photo_4); +// mDynamicImages[4] = v.findViewById(R.id.personal_main_page_dynamic_photo_5); + mGiftImages[0] = v.findViewById(R.id.personal_main_page_gift_1); + mGiftImages[1] = v.findViewById(R.id.personal_main_page_gift_2); + mGiftImages[2] = v.findViewById(R.id.personal_main_page_gift_3); + mGiftImages[3] = v.findViewById(R.id.personal_main_page_gift_4); +// mGiftImages[4] = v.findViewById(R.id.personal_main_page_gift_5); + + mRlGuard[0] = v.findViewById(R.id.rl_guard_photo_1); + mRlGuard[1] = v.findViewById(R.id.rl_guard_photo_2); + mRlGuard[2] = v.findViewById(R.id.rl_guard_photo_3); + mRlGuard[3] = v.findViewById(R.id.rl_guard_photo_4); +// mRlGuard[4] = v.findViewById(R.id.rl_guard_photo_5); + + mSvGuardImages[0] = v.findViewById(R.id.personal_main_page_guard_photo_1); + mSvGuardImages[1] = v.findViewById(R.id.personal_main_page_guard_photo_2); + mSvGuardImages[2] = v.findViewById(R.id.personal_main_page_guard_photo_3); + mSvGuardImages[3] = v.findViewById(R.id.personal_main_page_guard_photo_4); + + tagVipImageView = v.findViewById(R.id.tagVipImageView); + tagSVipImageView = v.findViewById(R.id.tagSVipImageView); + tagNewImageView = v.findViewById(R.id.tagNewImageView); + tagRealImageView = v.findViewById(R.id.tagRealImageView); + tagPhoneImageView = v.findViewById(R.id.tagPhoneImageView); +// mSvGuardImages[0] = v.findViewById(R.id.personal_main_page_guard_photo_5); + +// mIvMemberSign = v.findViewById(R.id.iv_member_sign); + iv_guard_user_avatar = v.findViewById(R.id.iv_guard_user_avatar); + mIv_guard = v.findViewById(R.id.iv_guard); + mPersonal_main_page_guard_people = v.findViewById(R.id.personal_main_page_guard_people); + mPersonal_main_page_guard_count = v.findViewById(R.id.personal_main_page_guard_count); + + tv_follow_num = v.findViewById(R.id.tv_follow_num); + tv_fans_num = v.findViewById(R.id.tv_fans_num); + tv_scan_num = v.findViewById(R.id.tv_scan_num); + + iv_video_call.setImageAssetsFolder("images/"); + iv_video_call.setAnimation("video_call_btn.json"); + iv_video_call.playAnimation(); + + mBack.setOnClickListener(this); + mFocusButton.setOnClickListener(this); + mGiftLayout.setOnClickListener(this); + mMore.setOnClickListener(this); + mDynamicLayout.setOnClickListener(this); + mIv_guard.setOnClickListener(this); + mOtherPhoto.setOnClickListener(this); + mGuardLayout.setOnClickListener(this); + view_end.setOnClickListener(this); + iv_video_call.setOnClickListener(this); + personal_player.setOnClickListener(this); + cv_video.setOnClickListener(this); + mPhoto.setImageURI(StrU.getResourcePath(mMainPageBean.getInfo().getAvatar(), getActivity())); + mName.setText(mMainPageBean.getInfo().getNickname()); + +// GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_DEFAULT); + String videoUrl = mMainPageBean.getVideo_url(); + if (mMainPageBean.getVideo_status() == 1) { + cv_video.setVisibility(View.VISIBLE); + player = new SimpleExoPlayer.Builder(getActivity(), new DefaultRenderersFactory(getActivity()).setEnableDecoderFallback(true)).build(); + if (player.getAudioComponent() != null) { + player.getAudioComponent().setVolume(0); + } + player.setRepeatMode(Player.REPEAT_MODE_OFF); + personal_player.setPlayer(player); + player.setMediaSource(new DefaultExoConfig(getActivity()).createMediaSource(Uri.parse(StrU.getResourcePath(videoUrl, getActivity())))); + player.prepare(); + player.setPlayWhenReady(true); + + player.addListener(new Player.EventListener() { + @Override + public void onPlaybackStateChanged(int state) { + Player.EventListener.super.onPlaybackStateChanged(state); + if (state == Player.STATE_ENDED) { + view_end.setVisibility(View.VISIBLE); + iv_video_call.setVisibility(View.VISIBLE); + } + } + }); + } + + if (mMainPageBean.getInfo().getGender() == 1) { + Drawable drawableLeft = ContextCompat.getDrawable(getActivity(), R.mipmap.sex_girl1); + drawableLeft.setBounds(0, 0, drawableLeft.getMinimumWidth(), drawableLeft.getMinimumHeight()); + mAge.setBackgroundResource(R.drawable.shape_stroke_age_women); + mAge.setTextColor(Color.parseColor("#FF4F73")); + mAge.setCompoundDrawables(drawableLeft, null, null, null); + } else { + mAge.setBackgroundResource(R.drawable.shape_stroke_age); + Drawable drawableLeft = ContextCompat.getDrawable(getActivity(), R.mipmap.sex_men1); + drawableLeft.setBounds(0, 0, drawableLeft.getMinimumWidth(), drawableLeft.getMinimumHeight()); + mAge.setTextColor(Color.parseColor("#002E9F")); + mAge.setCompoundDrawables(drawableLeft, null, null, null); + } + //男用户不显示真人 + if (0 == mMainPageBean.getInfo().getVip()) { + tagVipImageView.setVisibility(View.VISIBLE); + } else if (1 == mMainPageBean.getInfo().getVip()) { + tagSVipImageView.setVisibility(View.VISIBLE); + } + if (mMainPageBean.getInfo().getGender() == 1) { + tagRealImageView.setVisibility(View.VISIBLE); + } + if (mMainPageBean.getInfo().getMark() == 2) { + tagNewImageView.setVisibility(View.VISIBLE); + } + if (mMainPageBean.getInfo().getMobile_mark() == 1) { + tagPhoneImageView.setVisibility(View.VISIBLE); + } + + if (!StrU.isEmpty(mMainPageBean.getInfo().getSignature())) { + tv_signer.setVisibility(View.VISIBLE); + tv_signer.setText(mMainPageBean.getInfo().getSignature()); + } else { + tv_signer.setVisibility(View.GONE); + } + + mAge.setText(mMainPageBean.getInfo().getAge() + ""); + mSubInfo.setText(mMainPageBean.getInfo().getCity() + " | 用户号:" + mMainPageBean.getInfo().getUsercode()); + mSubInfo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(null, mMainPageBean.getInfo().getUsercode())); + MaleToast.showMessage(getActivity(), "复制成功"); + } + }); + + if (mMainPageBean.getInfo().getFollow_count() > 0) { + tv_follow_num.setVisibility(View.VISIBLE); + String s = "关注 " + mMainPageBean.getInfo().getFollow_count(); + StrU.setSpanTextColorSizeBold(s, 2, s.length(), tv_follow_num, R.color.color_2d2d2d, 13, true, getContext()); + } else { + tv_follow_num.setVisibility(View.GONE); + } + if (mMainPageBean.getInfo().getFans_count() > 0) { + tv_fans_num.setVisibility(View.VISIBLE); + String s = "粉丝 " + mMainPageBean.getInfo().getFans_count(); + StrU.setSpanTextColorSizeBold(s, 2, s.length(), tv_fans_num, R.color.color_2d2d2d, 13, true, getContext()); +// mFanNumber.setVisibility(View.VISIBLE); +// mFanNumber.setText(mMainPageBean.getInfo().getFans_count() + "粉丝"); + } else { + mFanNumber.setVisibility(View.GONE); + tv_fans_num.setVisibility(View.GONE); + } + if (mMainPageBean.getInfo().getVisitor_count() > 0) { + tv_scan_num.setVisibility(View.VISIBLE); + String s = "访客 " + mMainPageBean.getInfo().getVisitor_count(); + StrU.setSpanTextColorSizeBold(s, 2, s.length(), tv_scan_num, R.color.color_2d2d2d, 13, true, getContext()); + } else { + tv_scan_num.setVisibility(View.GONE); + } + if (!TextUtils.isEmpty(mMainPageBean.getInfo().getIp_province())) { + personal_main_page_ip_province.setVisibility(View.VISIBLE); + String s = "IP " + mMainPageBean.getInfo().getIp_province(); + StrU.setSpanTextColorSizeBold(s, 2, s.length(), personal_main_page_ip_province, R.color.color_2d2d2d, 13, true, getContext()); + } else { + personal_main_page_ip_province.setVisibility(View.GONE); + } +// mStatus.setText(mMainPageBean.getAnchor().getVideo_status() == 0? "空闲中" : "繁忙"); + + int online_status = mMainPageBean.getInfo().getOnline_status(); //在线 1 休息中 2 离线 + int video_status = mMainPageBean.getAnchor().getVideo_status(); //视频状态 0 休息中 1 视频中 + int open_video_status = mMainPageBean.getAnchor().getOpen_video_status(); //是否开启视频接听 0 否 1 是 + int open_voice_status = mMainPageBean.getAnchor().getOpen_voice_status(); //是否开启视频接听 0 否 1 是 + +// if (open_video_status == 0) { +// mStatus.setText("勿扰"); +// mStatus.setBackgroundResource(R.drawable.shape_button_disable); +// } else { +// if (video_status == 0) { +// mStatus.setText("空闲中"); +// mStatus.setBackgroundResource(R.drawable.shape_main_page_status); +// } else { +// mStatus.setText("咨询中"); +// mStatus.setBackgroundResource(R.drawable.shape_personal_main_start_video_button); +// +// } +// } + +// mFocusButton.setEnabled(mMainPageBean.getInfo().getIs_follow() == 0); + if (null != mMainPageBean.getSkill() && 0 != mMainPageBean.getSkill().size()) { + if (mMainPageBean.getInfo().getGender() == 1) { + //女生 + mSkillLayout.setVisibility(View.VISIBLE); + } else { + mSkillLayout.setVisibility(View.VISIBLE); + mSkillCost.setVisibility(View.GONE); + mSkillScore.setVisibility(View.GONE); + } + mSkillScore.setText("评分:" + mMainPageBean.getSkill().get(0).getScore() + "分"); + if (mMainPageBean.getSkill().get(0).getService_count() > 0) { + mSkillSuccessRate.setVisibility(View.VISIBLE); + mSkillSuccessRate.setText("接听次数:" + mMainPageBean.getSkill().get(0).getService_count() + "次"); + } else { + mSkillSuccessRate.setVisibility(View.GONE); + } + mSkillCost.setText("视频通话:" + mMainPageBean.getSkill().get(0).getPrice() + "币/分钟\n语音通话:" + mMainPageBean.getSkill().get(0).getVoice_price() + "币/分钟"); + + if (ConstUrl.LOGDEBUG) Log.i("TAG", "initView: online_status------------->" + online_status); + if (online_status == 1) { + if (open_video_status == 0 && open_voice_status == 0) { +// mStatus.setText("勿扰"); + mStatus.setImageResource(R.mipmap.icon_status2); + } else { + if (video_status == 0) { +// mStatus.setText("空闲中"); + mStatus.setImageResource(R.mipmap.icon_status1); + } else { +// mStatus.setText("视频中"); + mStatus.setImageResource(R.mipmap.icon_status3); + } + } + } else if (online_status == 2) { + mStatus.setImageResource(R.mipmap.icon_status4); + } else { + mStatus.setImageResource(R.mipmap.icon_status1); + } + mOtherPhoto.setVisibility(View.VISIBLE); + + } else { + if (mMainPageBean.getInfo().getGender() == 1) { //女生 + if (online_status == 1) { + if (open_video_status == 0 && open_voice_status == 0) { +// mStatus.setText("勿扰"); + mStatus.setImageResource(R.mipmap.icon_status2); + } else { + if (video_status == 0) { +// mStatus.setText("空闲中"); + mStatus.setImageResource(R.mipmap.icon_status1); + } else { +// mStatus.setText("视频中"); + mStatus.setImageResource(R.mipmap.icon_status3); + } + } + } else if (online_status == 2) { + mStatus.setImageResource(R.mipmap.icon_status4); + } else { + mStatus.setImageResource(R.mipmap.icon_status1); + } + } else { //男生 + if (online_status == 1) { + if (video_status == 0) { +// mStatus.setText("空闲中"); + mStatus.setImageResource(R.mipmap.icon_status1); + } else { +// mStatus.setText("咨询中"); + mStatus.setImageResource(R.mipmap.icon_status3); + } + } else if (online_status == 2) { + mStatus.setImageResource(R.mipmap.icon_status4); + } else { + mStatus.setImageResource(R.mipmap.icon_status1); + } + } + mOtherPhoto.setVisibility(View.GONE); + } + if (mMainPageBean.getInfo().getGender() != 1) { + mSkillCost.setVisibility(View.GONE); + mSkillScore.setVisibility(View.GONE); + } + mSubInfoTime.setText("最近活跃时间: " + mMainPageBean.getInfo().getUpdate_time()); + + if (null != mMainPageBean.getGuard()) { + if (!StrU.isEmpty(mMainPageBean.getGuard().getAvatar())) { + iv_guard_user_avatar.setImageURI(StrU.getResourcePath(mMainPageBean.getGuard().getAvatar(), getContext())); + mIv_guard.setImageResource(R.mipmap.icon_guard); + } else { + mIv_guard.setImageResource(0); + guardAnimation = AnimUtils.startGuardAnimation(getActivity(), mIv_guard); + } + mOtherPhoto.setImageURI(StrU.getResourcePath(mMainPageBean.getGuard().getAvatar(), getActivity())); + + mOtherGuardDialog = new OtherGuardDialog(getActivity()); + mOtherGuardDialog.setData(mMainPageBean.getGuard(), mMainPageBean.getInfo().getAvatar(), mMainPageBean.getInfo().getNickname()); + mOtherGuardDialog.setOnClickOtherGuard(new OtherGuardDialog.OnClickOtherGuard() { + @Override + public void onClickOtherGuard() { + mGuardDialog.show(); + } + }); + + mGuardDialog = new GuardDialog(getActivity()); + mGuardDialog.setData(mMainPageBean.getGuard().getGuard_price(), mMainPageBean.getGuard().getFirst_diff_num() + "", mMainPageBean.getInfo().getAvatar(), mMainPageBean.getGuard().getAvatar()); + mGuardDialog.setOnClickGuard(new GuardDialog.OnClickGuard() { + @Override + public void onClickGuard(int count, String price) { + guard(mMainPageBean.getInfo().getUserId(), count, price); + } + }); + + mPersonal_main_page_guard_people.setText("Ta的守护(" + mMainPageBean.getGuard().getGuard_person_total() + "人)"); + mPersonal_main_page_guard_count.setText("共" + mMainPageBean.getGuard().getGuard_symbol_total() + "个守护符"); + //守护 + if (null != mMainPageBean.getGuard().getList() && mMainPageBean.getGuard().getList().size() != 0) { + mGuardLayout.setVisibility(View.VISIBLE); + for (int i = 0; i < 4; i++) { + if (i < mMainPageBean.getGuard().getList().size()) { + String url = mMainPageBean.getGuard().getList().get(i); + mRlGuard[i].setVisibility(View.VISIBLE); + mSvGuardImages[i].setImageURI(StrU.getResourcePath(url, getActivity())); + } else { + mRlGuard[i].setVisibility(View.INVISIBLE); + } + } + } + } + + if (null != mMainPageBean.getDynamic() && mMainPageBean.getDynamic().size() != 0) { + mDynamicLayout.setVisibility(View.VISIBLE); +// for(int i = 0; i < mMainPageBean.getDynamic().size(); i++){ +// String url = mMainPageBean.getDynamic().get(i); +// mDynamicImages[i].setImageURI(ConstUrl.IMAGE_URL + url); +// } + + for (int i = 0; i < mMainPageBean.getDynamic().size(); i++) { + if (i < 4) { + String url = mMainPageBean.getDynamic().get(i); + mDynamicImages[i].setImageURI(StrU.getResourcePath(url, getActivity())); + } + + } + } + + if (null != mMainPageBean.getGifts() && mMainPageBean.getGifts().size() != 0) { + mGiftLayout.setVisibility(View.VISIBLE); +// for(int i = 0; i < mMainPageBean.getGifts().size(); i++){ +// GiftBean bean = mMainPageBean.getGifts().get(i); +// mGiftImages[i].setImageURI(ConstUrl.IMAGE_URL + bean.getImg()); +// } + + for (int i = 0; i < mMainPageBean.getGifts().size(); i++) { + if (i < 4) { + GiftBean bean = mMainPageBean.getGifts().get(i); + mGiftImages[i].setImageURI(StrU.getResourcePath(bean.getImg(), getActivity())); + } + } + } + + if (mMainPageBean.getInfo().getUserId() == SPUtils.getInt(getActivity(), ConsUser.USER_ID) || mMainPageBean.getInfo().getGender() == 2) { +// mFocusButton.setEnabled(false); +// mFocusButton.setBackgroundResource(R.drawable.shape_button_disable); + mFocusButton.setVisibility(View.GONE); + } else { + mFocusButton.setVisibility(View.VISIBLE); + if (mMainPageBean.getInfo().getIs_follow() == 0) { +// mFocusButton.setEnabled(true); +// mFocusButton.setBackgroundResource(R.drawable.shape_button_enable); + mFocusButton.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(getContext(), R.mipmap.userhome_follow), null, null); + mFocusButton.setTextColor(Color.parseColor("#666666")); + mFocusButton.setText("关注"); + } else { +// mFocusButton.setEnabled(false); +// mFocusButton.setBackgroundResource(R.drawable.shape_button_disable); +// mFocusButton.setText("已关注"); + mFocusButton.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(getContext(), R.mipmap.userhome_follow1), null, null); + mFocusButton.setTextColor(Color.parseColor("#925BF7")); + mFocusButton.setText("已关注"); + } + } + + addBanner(); + mSelectDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + + if (mMainPageBean.getInfo().getUserId() + == SPUtils.getInt(getActivity(), ConsUser.USER_ID)) { + mSelectDialog.addSelectButton("编辑资料", + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + Intent intent = new Intent(getActivity(), InfoEditActivity.class); + startActivity(intent); + mSelectDialog.dismiss(); + } + }); + } else { + mSelectDialog.addSelectButton("举报", + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectDialog.dismiss(); + Intent intent = new Intent(getActivity(), ComplaintActivity.class); + intent.putExtra("uid", mMainPageBean.getInfo().getUserId() + ""); + intent.putExtra("type", 1); + startActivity(intent); + } + }); + + mIs_black = mSelectDialog.addSelectButton(mMainPageBean.getInfo().getIs_black() == 0 ? "拉黑" : "取消拉黑", + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectDialog.dismiss(); + black(); + } + }); + + if (isFromChat) { + if (isOnTop) { + mSelectDialog.addSelectButton("取消置顶", + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectDialog.dismiss(); + ChatManager.getInstance() + .removeTag(mMainPageBean.getInfo().getUserId() + + "", NewFragment.RECENT_TAG_STICKY); + + ChatManager.getInstance().queryRecentContacts(); + MaleToast.showMessage(getActivity(), "成功取消置顶"); + } + }); + } else { + mSelectDialog.addSelectButton("置顶聊天", + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectDialog.dismiss(); + ChatManager.getInstance() + .addTag(mMainPageBean.getInfo().getUserId() + + "", NewFragment.RECENT_TAG_STICKY); + + ChatManager.getInstance().queryRecentContacts(); + MaleToast.showMessage(getActivity(), "成功置顶聊天"); + } + }); + } + + mSelectDialog.addSelectButton("清空聊天记录", + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + ChatManager.getInstance() + .clearChattingHistory(mMainPageBean.getInfo().getUserId() + ""); + mSelectDialog.dismiss(); + MaleToast.showMessage(getActivity(), "成功清空聊天记录"); + } + }); + } + } +// //'用户类型:0普通用户1内部用户2 审核人员账号' +// if (UserManager.getUserInfo().getType() == 2) { +// mSkillCost.setVisibility(View.GONE); +// mSkillScore.setVisibility(View.GONE); +// } + } + + /** + * 守护 + * + * @param count + * @param price + */ + private void guard(final int user_id, int count, String price) { + MainManager.postGuard((BaseActivity) getActivity(), user_id + "", count, price, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(getActivity(), "守护成功"); + if (null != mGuardDialog) { + mGuardDialog.dismiss(); + } + + getPageData(user_id); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + mGuardDialog.dismiss(); + BaseApplication.getInstance().getRechargeInfo(activity, 0); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private void getPageData(int userId) { + MainManager.getMainPageData((BaseActivity) getActivity(), userId, "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + + mMainPageBean = result; + + if (null != mMainPageBean.getSkill() && 0 != mMainPageBean.getSkill().size()) { //有大咖技能 + + mOtherPhoto.setVisibility(View.VISIBLE); + + if (null != mMainPageBean.getGuard()) { + mOtherPhoto.setImageURI(StrU.getResourcePath(mMainPageBean.getGuard().getAvatar(), getActivity())); + mGuardDialog.setData(mMainPageBean.getGuard().getGuard_price(), mMainPageBean.getGuard().getFirst_diff_num() + "", mMainPageBean.getInfo().getAvatar(), mMainPageBean.getGuard().getAvatar()); + mOtherGuardDialog.setData(mMainPageBean.getGuard(), mMainPageBean.getInfo().getAvatar(), mMainPageBean.getInfo().getNickname()); + if (!StrU.isEmpty(mMainPageBean.getGuard().getAvatar())) { + iv_guard_user_avatar.setImageURI(StrU.getResourcePath(mMainPageBean.getGuard().getAvatar(), getContext())); + mIv_guard.setImageResource(R.mipmap.icon_guard); + if (guardAnimation != null) { + guardAnimation.release(); + } + } else { + mIv_guard.setImageResource(0); + guardAnimation = AnimUtils.startGuardAnimation(getActivity(), mIv_guard); + } + + mPersonal_main_page_guard_people.setText("她的守护(" + mMainPageBean.getGuard().getGuard_person_total() + "人)"); + mPersonal_main_page_guard_count.setText("共" + mMainPageBean.getGuard().getGuard_symbol_total() + "个守护符"); + //守护 + if (null != mMainPageBean.getGuard().getList() && mMainPageBean.getGuard().getList().size() != 0) { + mGuardLayout.setVisibility(View.VISIBLE); + for (int i = 0; i < 4; i++) { + if (i < mMainPageBean.getGuard().getList().size()) { + String url = mMainPageBean.getGuard().getList().get(i); + mRlGuard[i].setVisibility(View.VISIBLE); + mSvGuardImages[i].setImageURI(StrU.getResourcePath(url, getActivity())); + } else { + mRlGuard[i].setVisibility(View.INVISIBLE); + } + } + } + } + + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + /** + * 跳到图片展示页 + * + * @param pathList + * @param innerCount + */ + private void clickImage(ArrayList pathList, int innerCount) { + String[] strings = new String[pathList.size()]; + View[] views = new View[pathList.size()]; + for (int i = 0; i < pathList.size(); i++) { + strings[i] = pathList.get(i); + views[i] = mViewPager.getChildAt(i); + } + Diooto diooto = new Diooto(getContext()) + .urls(strings) + .type(DiootoConfig.PHOTO) + .immersive(true) + .position(innerCount, 0) + .views(views) + .loadPhotoBeforeShowBigImage(new Diooto.OnLoadPhotoBeforeShowBigImageListener() { + @Override + public void loadView(SketchImageView sketchImageView, int position) { +// Glide.with(context).load(normalImageUlr[position]).into(sketchImageView); +// sketchImageView.displayImage(normalImageUlr[position]); + sketchImageView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { +// Toast.makeText(getContext(), "Long click", Toast.LENGTH_SHORT).show(); + return false; + } + }); + } + }) + .start(); + } + + private void black() { + MainManager.doBlack((BaseActivity) getActivity(), mMainPageBean.getInfo().getUserId() + "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BlackBean result, String message) { + if (null != result) { + String action = result.getAction(); + if (!TextUtils.isEmpty(action)) { + if (action.equals("add")) { + mIs_black.setText("取消拉黑"); + MaleToast.showMessage(getActivity(), "你已将对方拉黑"); + } else if (action.equals("delete")) { + mIs_black.setText("拉黑"); + MaleToast.showMessage(getActivity(), "你已将对方移除黑名单"); + } + } + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "拉黑失败"); + } + }); + } + + private void focus() { + DynamicsManager.follow((BaseActivity) getActivity(), + mMainPageBean.getInfo().getUserId() + "", + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + if (result != null) { + if (StrU.equals("add", result.getAction())) { +// mFocusButton.setEnabled(false); //不能取消关注 + mFocusButton.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(getContext(), R.mipmap.userhome_follow1), null, null); + mFocusButton.setTextColor(Color.parseColor("#925BF7")); + mFocusButton.setText("已关注"); +// mFocusButton.setBackgroundResource(R.drawable.shape_button_disable); +// mFocusButton.setText("已关注"); + MaleToast.showMessage(getActivity(), "关注成功"); + } else { + mFocusButton.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(getContext(), R.mipmap.userhome_follow), null, null); + mFocusButton.setTextColor(Color.parseColor("#666666")); + mFocusButton.setText("关注"); +// mFocusButton.setBackgroundResource(R.drawable.shape_button_enable); +// mFocusButton.setText("+关注"); + MaleToast.showMessage(getActivity(), message); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "关注失败"); + } + }); + } + + private void getCallInfo(int callType) { + MainManager.getCallInfo((BaseActivity) getActivity(), mMainPageBean.getInfo().getUserId(), 0, callType, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(activity, AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", true); + intent.putExtra("callType", 0); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + CallBean callBean = new CallBean(); + callBean.setUser_id(mMainPageBean.getInfo().getUserId() + ""); + callBean.setAge(mMainPageBean.getInfo().getAge()); + callBean.setVideo_url(mMainPageBean.getVideo_url()); + callBean.setNickname(mMainPageBean.getInfo().getNickname()); + callBean.setAvatar_url(mMainPageBean.getInfo().getAvatar()); + callBean.setIs_follow(mMainPageBean.getInfo().getIs_follow() != 0); + intent.putExtra("bean", callBean); + startActivity(intent); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onClick(View view) { + if (view == mBack) { + getActivity().finish(); + } else if (view == mFocusButton) { + focus(); + } else if (view == mGiftLayout) { + Intent intent = new Intent(getActivity(), GiftReceivedActivity.class); + intent.putExtra("userId", mMainPageBean.getInfo().getUserId()); + startActivity(intent); + } else if (view == mMore) { + mSelectDialog.show(); + } else if (view == mDynamicLayout) { + Intent intent = new Intent(getActivity(), MainDynamicActivity.class); + intent.putExtra("userId", mMainPageBean.getInfo().getUserId()); + intent.putExtra("nickName", mMainPageBean.getInfo().getNickname()); + getActivity().startActivity(intent); + } else if (view == mIv_guard) { + //点击守护 + if (null != mGuardDialog) { + mGuardDialog.show(); + } + } else if (view == mOtherPhoto) { + //点击守护的头像 + if (null != mOtherGuardDialog) { + mOtherGuardDialog.show(); + } + } else if (view == mGuardLayout) { + Intent intent = new Intent(getActivity(), GuardRankActivity.class); + intent.putExtra("name", mMainPageBean.getInfo().getNickname()); + intent.putExtra("userId", mMainPageBean.getInfo().getUserId()); + startActivity(intent); + } else if (view == iv_video_call || view == view_end) { + getCallInfo(0); + } else if (view == personal_player || view == cv_video) { + Intent intent = new Intent(getActivity(), PageVideoPlayActivity.class); + intent.putExtra("userId", mMainPageBean.getInfo().getUserId()); + intent.putExtra("videoUrl", mMainPageBean.getVideo_url()); + intent.putExtra("age", mMainPageBean.getInfo().getAge()); + intent.putExtra("nickname", mMainPageBean.getInfo().getNickname()); + intent.putExtra("avatar_url", mMainPageBean.getInfo().getAvatar()); + intent.putExtra("is_follow", mMainPageBean.getInfo().getIs_follow()); + startActivity(intent); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (mIv_guard != null) { + if (mIv_guard.getBackground() == null) { + return; + } + if (guardAnimation != null) { + guardAnimation.release(); + } +// AnimationDrawable drawable = (AnimationDrawable)mIv_guard.getBackground(); +// drawable.stop(); + mIv_guard.setBackground(null); + + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (player != null) { + player.release(); + player = null; + } +// GSYVideoManager.releaseAllVideos(); + EventBus.getDefault().unregister(this); + if (null != mSelectDialog && mSelectDialog.isShowing()) { + mSelectDialog.dismiss(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendActiveFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendActiveFragment.java new file mode 100644 index 0000000..c64cdd3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendActiveFragment.java @@ -0,0 +1,405 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.MainChannelAdapter1; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.utils.BaseUtils; +import com.fengliyan.tianlesue.utils.GlideImageLoader; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.uikit.adboard.AdPagesManager; +import com.youth.banner.Banner; +import com.youth.banner.listener.OnBannerListener; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/11. + */ + +public class MainRecommendActiveFragment extends Fragment { + private RecyclerView mRvMainChannel; + // private MainChannelAdapter mAdapter; + private MainChannelAdapter1 mAdapter; + + private List mChannelAnchors = new ArrayList<>(); + private int[] mImage_bg; + private SwipeRefreshLayout mChannelRefresh; + private Banner mImageBanner; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_main_recommend_active, container, false); + mImage_bg = new int[]{getColor("#e5c9c9"), getColor("#c9d8e5"), getColor("#c9d3c1"), getColor("#cbcbc8"), getColor("#d3cbe4"), getColor("#cdd1d6")}; +// mImage_bg = new int[]{R.drawable.shape_bg_1, R.drawable.shape_bg_2, R.drawable.shape_bg_3, R.drawable.shape_bg_4, R.drawable.shape_bg_5, R.drawable.shape_bg_6}; + initView(v); + mPage = 1; + getChannelData(mPage); + return v; + } + + private int getColor(String color) { + return Color.parseColor(color); + } + + private View mPageView; + private ViewPager mViewPager; + private ViewGroup mGroup; + private AdPagesManager mManager; + private List mBanners = new ArrayList<>(); + + private void initView(View v) { + mRvMainChannel = v.findViewById(R.id.rv_main_channel); + mRvMainChannel.setLayoutManager(new WrapStaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + + RecyclerView.LayoutManager mLayoutManager = mRvMainChannel.getLayoutManager(); + int[] into = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()]; + int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(into); + + int lastVisibleItemPosition = lastVisibleItemPositions[1] + 1; + if (mChannelAnchors.size() != 0 && newPage < mPage && !isNodata && lastVisibleItemPosition > mChannelAnchors.size() - 2) { + getChannelData(mPage); + } + return super.canScrollVertically(); + } + }); + +// mAdapter = new MainChannelAdapter(getActivity(), mImage_bg); + mAdapter = new MainChannelAdapter1(getActivity(), "active"); + mAdapter.setShowNewPeople(true); + mAdapter.setOnPlay(new MainChannelAdapter1.OnPlay() { + @Override + public void goPlayVideoList() { + if (beanList != null && beanList.size() > 0) { + Intent intent = new Intent(getActivity(), PlayVideoActivity.class); + intent.putExtra("videoUrlList", (Serializable) beanList); + intent.putExtra("position", videoPosition - 1); + intent.putExtra("page", page); + startActivity(intent); + } + } + + @Override + public void getVideo(@NonNull AnchorBean data) { + isPlay = true; + if (isResume) { + setVideoBean(); + } + } + }); +// mAdapter.setAnchorListBeans(mChannelAnchors); + mRvMainChannel.setAdapter(mAdapter); + + mChannelRefresh = v.findViewById(R.id.channel_refresh); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + page = 1; + videoPosition = 0; + beanList.clear(); + mAdapter.setPlay(false); + getChannelData(mPage); + } + }); + + AppBarLayout appBarLayout = v.findViewById(R.id.channel_app_bar); + appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if (verticalOffset == 0) { + mChannelRefresh.setEnabled(true); + + } else { + mChannelRefresh.setEnabled(false); + } + } + }); + + mBanners.clear(); + mImageBanner = v.findViewById(R.id.image_banner); + + } + + public void setChannelRefresh() { + mChannelRefresh.post(new Runnable() { + + @Override + public void run() { + mChannelRefresh.setRefreshing(true); + } + }); + } + + List images = new ArrayList<>(); + + private void addBanner() { +// Iterator bannerBeanIterator = mBanners.iterator(); +// mManager.clear(); +// while (bannerBeanIterator.hasNext()) { +// BannerBean bannerBean = bannerBeanIterator.next(); +// mManager.addImageViewByUrl(ConstUrl.IMAGE_URL + bannerBean.getImage()); +// } +// +// mManager.manage(); + images.clear(); + if (null != mBanners) { + if (mBanners.size() != 0) { + for (int i = 0; i < mBanners.size(); i++) { + images.add(StrU.getResourcePath(mBanners.get(i).getImage(), getActivity())); + } + } + } + + //简单使用 + BaseUtils.setBannerLayoutParams(mImageBanner).setImages(images) + .setImageLoader(new GlideImageLoader()) + .setOnBannerListener(new OnBannerListener() { + @Override + public void OnBannerClick(int position) { + if (null != mBanners) { + int size = mBanners.size(); + if (size != 0) { + int i = position % size; + JumpUtils.jump(mBanners.get(i).getLink_type(), + mBanners.get(i).getLink_url(), getActivity()); + } + } + } + }) + .setDelayTime(3000) + .start() + .setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == 1) { + mChannelRefresh.setEnabled(false);//设置不可触发 + } else if (state == 2) { + mChannelRefresh.setEnabled(true);//设置可触发 + } + + } + }); + } + + @Override + public void onResume() { + super.onResume(); + Log.e("TAG", "onResume: --------->"); + isResume = true; + if (isPlay) { + setVideoBean(); + } + } + + @Override + public void onPause() { + super.onPause(); + Log.e("TAG", "onPause: ------------->"); + isResume = false; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + isResume = false; + } + + private boolean isPlay; + private boolean isResume; + private int mPage = 1; + private int newPage = 1; + private boolean isNodata; + + private void getChannelData(int page) { + newPage = page; + MainManager.getActiveAnchors((BaseActivity) getActivity(), mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() == 0) { + isNodata = true; + } else { + isNodata = false; + if (mPage == 1) { + mChannelAnchors.clear(); + mChannelAnchors.addAll(result.getList().getList()); + mAdapter.setList(result.getList().getList()); + } else { + List list = result.getList().getList(); + // 创建一个临时列表存储去重后的数据 + List filteredList = new ArrayList<>(); + for (AnchorBean newAnchor : list) { + boolean duplicate = false; + // 检查是否在mChannelAnchors中已存在 + for (AnchorBean existingAnchor : mChannelAnchors) { + if (newAnchor.getUserid() == existingAnchor.getUserid()) { + duplicate = true; + break; + } + } + // 如果不是重复数据,则添加到过滤列表 + if (!duplicate) { + filteredList.add(newAnchor); + } + } + // 添加去重后的数据 + mChannelAnchors.addAll(filteredList); + mAdapter.addData(filteredList); + } + + if (mPage == 1 && result.getVideo_list() != null) { + getCoverVideo(); +// result.getVideo_list().setVideo(true); +// beanList.add(result.getVideo_list()); +// mChannelAnchors.add(3, result.getVideo_list()); + } + } + } + } + if (mPage == 1) { + if (null != mBanners && mBanners.size() == 0) { + mBanners = result.getBanner(); +// addBanner(); + } + } + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + private List beanList = new ArrayList<>(); + private int videoPosition = 0; + private int page = 1; + private boolean canRemove; + + private void setVideoBean() { + if (beanList.size() > videoPosition) { + AnchorBean bean = beanList.get(videoPosition); + bean.setVideo(true); + if (videoPosition == 0) { + mChannelAnchors.add(3, bean); + mAdapter.addData(3, bean); + } else { + mChannelAnchors.set(3, bean); + mAdapter.setData(3, bean); + } + canRemove = true; + isPlay = false; + videoPosition++; + } else { + getCoverVideo(); + } + } + + private void getCoverVideo() { + MainManager.getCoverVideo((BaseActivity) getActivity(), page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList() && result.getList().getList().size() > 0) { + if (mAdapter.getItemCount() > 3) { + beanList.addAll(result.getList().getList()); +// if (page == 1) { +// beanList.remove(0); +// } + setVideoBean(); +// AnchorBean bean = result.getList().getList().get(0); +// bean.setVideo(true); +// mAdapter.setData(3, bean); +// isPlay = false; + } + page++; + } else { + if (canRemove) { + mAdapter.removeAt(3); + canRemove = false; + } + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + public void refresh() { + mPage = 1; + page = 1; + videoPosition = 0; + beanList.clear(); + if (getActivity() != null) { + if (mAdapter != null) { + mAdapter.setPlay(false); + } + getChannelData(mPage); + } + if (null != mRvMainChannel) { + mRvMainChannel.scrollToPosition(0); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendCityFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendCityFragment.java new file mode 100644 index 0000000..b8e37ab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendCityFragment.java @@ -0,0 +1,313 @@ +package com.fengliyan.tianlesue.view.main; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.uikit.adboard.AdPagesManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.main.adapter.MainChannelAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.utils.BaseUtils; +import com.fengliyan.tianlesue.utils.GlideImageLoader; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.youth.banner.Banner; +import com.youth.banner.listener.OnBannerListener; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/11. + */ + +public class MainRecommendCityFragment extends Fragment { + + private RecyclerView mRvMainChannel; + private MainChannelAdapter mAdapter; + + private List mChannelAnchors = new ArrayList<>(); + private int[] mImage_bg; + private SwipeRefreshLayout mChannelRefresh; + private Banner mImageBanner; + + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_main_recommend_city, container, false); + mImage_bg = new int[]{getColor("#e5c9c9"), getColor("#c9d8e5"), getColor("#c9d3c1"), getColor("#cbcbc8"), getColor("#d3cbe4"), getColor("#cdd1d6")}; +// mImage_bg = new int[]{R.drawable.shape_bg_1, R.drawable.shape_bg_2, R.drawable.shape_bg_3, R.drawable.shape_bg_4, R.drawable.shape_bg_5, R.drawable.shape_bg_6}; + initView(v); + mPage = 1; + getChannelData(mPage, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + return v; + } + + private int getColor(String color) { + return Color.parseColor(color); + } + + private View mPageView; + private ViewPager mViewPager; + private ViewGroup mGroup; + private AdPagesManager mManager; + private List mBanners = new ArrayList<>(); + + private void initView(View v) { + mRvMainChannel = v.findViewById(R.id.rv_main_channel); + mRvMainChannel.setLayoutManager(new WrapStaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + + RecyclerView.LayoutManager mLayoutManager = mRvMainChannel.getLayoutManager(); + int[] into = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()]; + int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(into); + + int lastVisibleItemPosition = lastVisibleItemPositions[1] + 1; + + if (mChannelAnchors.size() != 0 && newPage < mPage && !isNodata && lastVisibleItemPosition > mChannelAnchors.size() - 2) { + getChannelData(mPage, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + } + return super.canScrollVertically(); + } + }); + + mAdapter = new MainChannelAdapter(getActivity(), mImage_bg); + mAdapter.setAnchorListBeans(mChannelAnchors); + mRvMainChannel.setAdapter(mAdapter); + +// mPageView = v.findViewById(R.id.pager_view); +// +// WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE); +// DisplayMetrics dm = new DisplayMetrics(); +// wm.getDefaultDisplay().getMetrics(dm); +// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( +// ViewGroup.LayoutParams.MATCH_PARENT, dm.widthPixels / 3); +// +// mPageView.setLayoutParams(params); +// +// mViewPager = (ViewPager) v.findViewById(R.id.ad_pager); +// mGroup = (ViewGroup) v.findViewById(R.id.view_group); +// mManager = new AdPagesManager(mViewPager, mGroup, getContext()); +// mManager.setOnImageClickListener(new AdPagesManager.ImageClickListener() { +// @Override +// public void onClick(View v, int position) { +// if (null != mBanners) { +// int size = mBanners.size(); +// if (size != 0) { +// int i = position % size; +// JumpUtils.jump(mBanners.get(i).getLink_type(), +// mBanners.get(i).getLink_url(), getActivity()); +// } +// } +// +// } +// }); + + mChannelRefresh = v.findViewById(R.id.channel_refresh); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getChannelData(mPage, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + } + }); + + AppBarLayout appBarLayout = v.findViewById(R.id.channel_app_bar); + appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if (verticalOffset == 0) { + mChannelRefresh.setEnabled(true); + + } else { + mChannelRefresh.setEnabled(false); + } + } + }); + + mBanners.clear(); + mImageBanner = v.findViewById(R.id.image_banner); + + } + + public void setChannelRefresh() { + mChannelRefresh.post(new Runnable() { + + @Override + public void run() { + mChannelRefresh.setRefreshing(true); + } + }); + } + + List images = new ArrayList<>(); + + private void addBanner() { +// Iterator bannerBeanIterator = mBanners.iterator(); +// mManager.clear(); +// while (bannerBeanIterator.hasNext()) { +// BannerBean bannerBean = bannerBeanIterator.next(); +// mManager.addImageViewByUrl(ConstUrl.IMAGE_URL + bannerBean.getImage()); +// } +// +// mManager.manage(); + images.clear(); + if (null != mBanners) { + if (mBanners.size() != 0) { + for (int i = 0; i < mBanners.size(); i++) { + images.add(StrU.getResourcePath(mBanners.get(i).getImage(), getActivity())); + } + } + } + //简单使用 + BaseUtils.setBannerLayoutParams(mImageBanner).setImages(images) + .setImageLoader(new GlideImageLoader()) + .setOnBannerListener(new OnBannerListener() { + @Override + public void OnBannerClick(int position) { + if (null != mBanners) { + int size = mBanners.size(); + if (size != 0) { + int i = position % size; + JumpUtils.jump(mBanners.get(i).getLink_type(), + mBanners.get(i).getLink_url(), getActivity()); + } + } + } + }) + .setDelayTime(3000) + .start() + .setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == 1) { + mChannelRefresh.setEnabled(false);//设置不可触发 + } else if (state == 2) { + mChannelRefresh.setEnabled(true);//设置可触发 + } + + } + }); + + } + + private int mPage = 1; + private int newPage = 1; + private boolean isNodata; + + public void setCityChoose(String cityId) { + mPage = 1; + getChannelData(1, cityId); + } + + private void getChannelData(final int page, String cityId) { + newPage = page; + MainManager.getCityAnchors((BaseActivity) getActivity(), cityId, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() == 0) { + isNodata = true; + } else { + isNodata = false; + } + + if (page == 1) { + mChannelAnchors.clear(); + mChannelAnchors.addAll(result.getList().getList()); + mAdapter.notifyDataSetChanged(); + } else { + List list = result.getList().getList(); + // 创建一个临时列表存储去重后的数据 + List filteredList = new ArrayList<>(); + for (AnchorBean newAnchor : list) { + boolean duplicate = false; + // 检查是否在mChannelAnchors中已存在 + for (AnchorBean existingAnchor : mChannelAnchors) { + if (newAnchor.getUserid() == existingAnchor.getUserid()) { + duplicate = true; + break; + } + } + // 如果不是重复数据,则添加到过滤列表 + if (!duplicate) { + filteredList.add(newAnchor); + } + } + int startPosition = mChannelAnchors.size(); + // 添加去重后的数据 + mChannelAnchors.addAll(filteredList); + mAdapter.notifyItemRangeInserted(startPosition, filteredList.size()); + } + } + } + } + + if (page == 1) { + if (null != mBanners && mBanners.size() == 0) { + mBanners = result.getBanner(); +// addBanner(); + } + } + mPage++; + + mChannelRefresh.setRefreshing(false); + } + + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + public void refresh() { + mPage = 1; + if (getActivity() != null) { + getChannelData(mPage, SPUtils.getString(getActivity(), ConsUser.PICKER_CITY_ID + "")); + } + if (null != mRvMainChannel) { + mRvMainChannel.scrollToPosition(0); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendFragment.java new file mode 100644 index 0000000..ca4b0dd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendFragment.java @@ -0,0 +1,554 @@ +package com.fengliyan.tianlesue.view.main; + +import static android.app.Activity.RESULT_OK; +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.eventBus.TurntableEvent; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.LuckWheelDialog; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.rank.ZhiRankActivity; +import com.fengliyan.tianlesue.view.settings.InvitationActivity; +import com.fengliyan.tianlesue.view.settings.dialog.GirlAuthDialog; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/1/11. + */ + +public class MainRecommendFragment extends Fragment implements View.OnClickListener { + + private RelativeLayout mRecommend_recommend; + private RelativeLayout mRecommend_active; + private RelativeLayout mRecommend_people; + private LinearLayout mRecommend_city; + private TextView mRecommend_title_name_1; + private TextView mRecommend_title_name_2; + private TextView mRecommend_title_name_3; + private TextView mRecommend_title_name_4; + private ImageView iv_location; + private View mRecommend_title_bottom_line_1; + private View mRecommend_title_bottom_line_2; + private View mRecommend_title_bottom_line_3; + private View mRecommend_title_bottom_line_4; + private boolean isReClick = false; + private MainRecommendCityFragment mMainRecommendCityFragment; + private RecommendFragment1 mRecommendFragment1; + private MainRecommendActiveFragment mMainRecommendActiveFragment; + private MainRecommendPeopleFragment mMainRecommendPeopleFragment; + private ImageView mIvMoreCity; + private ImageView mIvTitleSearch; + private View mVyaoqingLayout; + private LinearLayout main_turntable; + private ImageView main_turntable_end, iv_main_turntable; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_main_recommend, container, false); + + initTitle(); + initView(v); + EventBus.getDefault().register(this); +// getIndexStuff(); + return v; + } + + private View mSearchView; + private ImageView mGenderView; + private ImageView iv_title_rank; + + private void initTitle() { + Title title = ((BaseActivity) getActivity()).getCustomTitle(); + title.setVisibility(View.VISIBLE); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mSearchView = View.inflate(getActivity(), R.layout.item_main_home_page_layout, null); + mIvTitleSearch = mSearchView.findViewById(R.id.iv_title_search); + mGenderView = mSearchView.findViewById(R.id.iv_title_gender); + iv_title_rank = mSearchView.findViewById(R.id.iv_title_rank); + + mRecommend_recommend = mSearchView.findViewById(R.id.title_view_1); + mRecommend_active = mSearchView.findViewById(R.id.title_view_2); + mRecommend_people = mSearchView.findViewById(R.id.title_view_3); + mRecommend_city = mSearchView.findViewById(R.id.title_view_4); + + mRecommend_title_name_1 = mSearchView.findViewById(R.id.title_name_1); + String market = DeviceManager.getInstance().getApplicationMarket(); + if (market != null && market.equals("huawei")) { + mRecommend_title_name_1.setText("热门"); + } else { + mRecommend_title_name_1.setText("推荐"); + } + iv_location = mSearchView.findViewById(R.id.iv_location); + mRecommend_title_name_2 = mSearchView.findViewById(R.id.title_name_2); + mRecommend_title_name_3 = mSearchView.findViewById(R.id.title_name_3); + mRecommend_title_name_4 = mSearchView.findViewById(R.id.title_name_4); + + mRecommend_title_bottom_line_1 = mSearchView.findViewById(R.id.title_bottom_line_1); + mRecommend_title_bottom_line_2 = mSearchView.findViewById(R.id.title_bottom_line_2); + mRecommend_title_bottom_line_3 = mSearchView.findViewById(R.id.title_bottom_line_3); + mRecommend_title_bottom_line_4 = mSearchView.findViewById(R.id.title_bottom_line_4); + + mIvMoreCity = mSearchView.findViewById(R.id.iv_more_city); + + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + mRecommend_city.setVisibility(View.INVISIBLE); + iv_location.setVisibility(View.INVISIBLE); + } else { + mRecommend_city.setVisibility(View.VISIBLE); + iv_location.setVisibility(View.VISIBLE); + mRecommend_city.setOnClickListener(this); + } + mRecommend_recommend.setOnClickListener(this); + mRecommend_active.setOnClickListener(this); + mRecommend_people.setOnClickListener(this); + + +// if (SPUtils.getInt(getActivity(), ConsUser.GENDER) == 2) { +// mGenderView.setText("女生"); +// } else { +// mGenderView.setText("男生"); +// } + + title.addViewTo(mSearchView, POSTION_CENTER); + + iv_title_rank.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getActivity(), ZhiRankActivity.class); + startActivity(intent); + } + }); + + mIvTitleSearch.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), SearchActivity.class); + startActivity(intent); + } + }); + + + mGenderView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (UserManager.getUserInfo().getGender() == 1) { + if (UserManager.getUserInfo().getIs_anchor() == 1 && UserManager.getUserInfo().getIs_face_status() == 1) { + groupHello(); +// Intent intent = new Intent(getActivity(), GroupCallActivity.class); +// startActivity(intent); + } else { + GirlAuthDialog dialog = new GirlAuthDialog(getActivity()); + dialog.show(); + MaleToast.showMessage(getActivity(), "通过真人认证才能使用该功能"); + } + } else { + Intent intent = new Intent(getActivity(), GenderUserAndMibiRankActivity.class); + startActivity(intent); + } + } + }); + + } + + void groupHello() { + CustomAlertDialog dialog = new CustomAlertDialog(getActivity()); + dialog.hideTitle(true); + dialog.setContent("确定一键给" + NoClearSPUtils.getInt(getContext(), ConsUser.SEND_USER_TOTAL) + "人打招呼吗?\n每天可群发" + NoClearSPUtils.getInt(getContext(), ConsUser.GREET_DAY_TOTAL) + "次,每次需间隔" + NoClearSPUtils.getInt(getContext(), ConsUser.GREET_GAP_HOUR) + "分钟"); + dialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + MainManager.sendGroupCall((BaseActivity) getActivity(), -1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + MaleToast.showMessage(activity, "发送成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "发送失败"); + } + }); + } + }); + dialog.show(); + } + + private ViewPager mMainViewPager; + private MainViewPagerAdapter mViewPagerAdapter; + private List mChannelFragments = new ArrayList<>(); + private ImageView mIvAd; + + private void initView(View v) { + mVyaoqingLayout = v.findViewById(R.id.main_yaoqing_layout); +// mVyaoqingLayout.setVisibility(View.VISIBLE); + mIvAd = v.findViewById(R.id.main_yaoqing); + mIvAd.setOnClickListener(this); + v.findViewById(R.id.main_yaoqing_end).setOnClickListener(this); + + mMainViewPager = v.findViewById(R.id.main_view_pager); + + main_turntable = v.findViewById(R.id.main_turntable); + main_turntable_end = v.findViewById(R.id.main_turntable_end); + iv_main_turntable = v.findViewById(R.id.iv_main_turntable); + main_turntable.setOnClickListener(this); + main_turntable_end.setOnClickListener(this); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + main_turntable.setVisibility(View.GONE); + } else { + main_turntable.setVisibility(View.VISIBLE); + } + + mRecommendFragment1 = new RecommendFragment1(); + mMainRecommendActiveFragment = new MainRecommendActiveFragment(); + mMainRecommendPeopleFragment = new MainRecommendPeopleFragment(); + mMainRecommendCityFragment = new MainRecommendCityFragment(); + + mChannelFragments.add(mRecommendFragment1); + mChannelFragments.add(mMainRecommendActiveFragment); + mChannelFragments.add(mMainRecommendPeopleFragment); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) != 0 && SPUtils.getInt(getContext(), ConsUser.TYPE) != 2) { + mChannelFragments.add(mMainRecommendCityFragment); + } + + mViewPagerAdapter = new MainViewPagerAdapter(getChildFragmentManager(), + mChannelFragments); + + mMainViewPager.setAdapter(mViewPagerAdapter); + mMainViewPager.setOffscreenPageLimit(3); + viewPagerChange(1); + + mMainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if (position == 3) { + isReClick = true; + } else { + isReClick = false; + } + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPagerAdapter.notifyDataSetChanged(); + mMainViewPager.setCurrentItem(1); + } + + @Override + public void onHiddenChanged(boolean hidden) { + if (!hidden) { + initTitle(); + viewPagerChange(mIndex); +// if (UserManager.getUserInfo().getGender() == 2) { +// getRechargeInfo(); +// } + } + } + + // 审核模式隐藏邀请好友 + public void setMarketStatus(int marketStatus) { + if (marketStatus == 0) { + mVyaoqingLayout.setVisibility(View.GONE); + } else { + if (UserManager.getUserInfo().getGender() == 2) { + mVyaoqingLayout.setVisibility(View.VISIBLE); + } else { + mVyaoqingLayout.setVisibility(View.GONE); + } + } + } + + private int mIndex; + + private void viewPagerChange(int index) { + String city = SPUtils.getString(getActivity(), ConsUser.PICKER_CITY); + if (!TextUtils.isEmpty(city)) { + mRecommend_title_name_4.setText(city); + } + mIndex = index; + switch (index) { + case 0: + mRecommend_title_name_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mRecommend_title_name_1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mRecommend_title_name_1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mRecommend_title_bottom_line_1.setVisibility(View.VISIBLE); + + mRecommend_title_name_2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_2.setVisibility(View.GONE); + + mRecommend_title_name_3.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_3.setVisibility(View.GONE); + + mRecommend_title_name_4.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_4.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + break; + case 1: + mRecommend_title_name_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_1.setVisibility(View.GONE); + + mRecommend_title_name_2.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mRecommend_title_name_2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mRecommend_title_name_2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mRecommend_title_bottom_line_2.setVisibility(View.VISIBLE); + + mRecommend_title_name_3.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_3.setVisibility(View.GONE); + + mRecommend_title_name_4.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_4.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + break; + case 2: + mRecommend_title_name_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_1.setVisibility(View.GONE); + + mRecommend_title_name_2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_2.setVisibility(View.GONE); + + mRecommend_title_name_3.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mRecommend_title_name_3.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mRecommend_title_name_3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mRecommend_title_bottom_line_3.setVisibility(View.VISIBLE); + + mRecommend_title_name_4.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_4.setVisibility(View.GONE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + break; + case 3: + mRecommend_title_name_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_1.setVisibility(View.GONE); + + mRecommend_title_name_2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_2.setVisibility(View.GONE); + + mRecommend_title_name_3.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mRecommend_title_name_3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mRecommend_title_name_3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mRecommend_title_bottom_line_3.setVisibility(View.GONE); + + mRecommend_title_name_4.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mRecommend_title_name_4.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mRecommend_title_name_4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mRecommend_title_bottom_line_4.setVisibility(View.VISIBLE); + + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo2); + break; + } + } + + public void onEventMainThread(TurntableEvent event) { + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + main_turntable.setVisibility(View.GONE); + } else { + if (event.getType() == 1) { + main_turntable.setVisibility(View.VISIBLE); + } else { + main_turntable.setVisibility(View.GONE); + } + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onClick(View view) { + if (view == mRecommend_recommend) { + mMainViewPager.setCurrentItem(0); + } else if (view == mRecommend_active) { + mMainViewPager.setCurrentItem(1); + } else if (view == mRecommend_people) { + mMainViewPager.setCurrentItem(2); + } else if (view == mRecommend_city) { + if (isReClick) { + Intent intent = new Intent(getActivity(), CityPickerActivity.class); +// startActivity(intent); + startActivityForResult(intent, 1001); + } else { + mMainViewPager.setCurrentItem(3); + } + } else if (view.getId() == R.id.main_yaoqing) { + if (is_first_recharge) { + if (mRechargeListBean != null && mRechargeListBean.size() > 2) { +// FirstChargeGiftDialog dialog = new FirstChargeGiftDialog(getActivity(), mRechargeListBean); +// dialog.setCanceledOnTouchOutside(false); +// dialog.show(); + } + } else { + Intent intent = new Intent(getContext(), InvitationActivity.class); + startActivity(intent); + } + } else if (view.getId() == R.id.main_yaoqing_end) { + mVyaoqingLayout.setVisibility(View.GONE); + } else if (view.getId() == R.id.main_turntable) { + LuckWheelDialog dialog = new LuckWheelDialog(getActivity()); + dialog.show(); + } else if (view.getId() == R.id.main_turntable_end) { + main_turntable.setVisibility(View.GONE); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 1001 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(getActivity(), ConsUser.PICKER_CITY + "", city); + mRecommend_title_name_4.setText(city); + + if (!TextUtils.isEmpty(city)) { + String cityId = GlobalManager.getCityMap().get(city); + SPUtils.saveString(getActivity(), ConsUser.PICKER_CITY_ID + "", cityId); + if (null != mMainRecommendCityFragment) { + mMainRecommendCityFragment.setCityChoose(cityId); + } + } + } + } + } + + public void clickRefresh() { + + if (mIndex == 0) { + if (null != mRecommendFragment1) { + mRecommendFragment1.refresh(); + } + } else if (mIndex == 1) { + if (null != mMainRecommendActiveFragment) { + mMainRecommendActiveFragment.refresh(); + } + } else if (mIndex == 2) { + if (null != mMainRecommendPeopleFragment) { + mMainRecommendPeopleFragment.refresh(); + } + } else if (mIndex == 3) { + if (null != mMainRecommendCityFragment) { + mMainRecommendCityFragment.refresh(); + } + } + + } + + private boolean is_first_recharge; + private List mRechargeListBean; + + //男生未充值过显示首充图标 + private void getRechargeInfo() { + SettingManager.getRechargeInfo((BaseActivity) getActivity(), 2, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RechargeListBean result, String message) { + if (result != null) { + mRechargeListBean = result.getGift_bag_list(); + StorageManager.getInstance(activity).putInt(Constans.IS_FIRST_RECHARGE, result.getIs_first_recharge()); + // 1=已经首充过、0=没有首充过 + if (UserManager.getUserInfo().getGender() == 2 && result.getIs_first_recharge() == 0) { + mIvAd.setImageResource(R.drawable.ic_lqhl); + is_first_recharge = true; + mVyaoqingLayout.setVisibility(View.VISIBLE); + } else { + mIvAd.setImageResource(R.drawable.yqzq_ic); + is_first_recharge = false; + mVyaoqingLayout.setVisibility(View.GONE); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendPeopleFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendPeopleFragment.java new file mode 100644 index 0000000..7ba9e82 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/MainRecommendPeopleFragment.java @@ -0,0 +1,305 @@ +package com.fengliyan.tianlesue.view.main; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.MainChannelAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.utils.BaseUtils; +import com.fengliyan.tianlesue.utils.GlideImageLoader; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.uikit.adboard.AdPagesManager; +import com.youth.banner.Banner; +import com.youth.banner.listener.OnBannerListener; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/11. + */ + +public class MainRecommendPeopleFragment extends Fragment { + + private RecyclerView mRvMainChannel; + private MainChannelAdapter mAdapter; + + private List mChannelAnchors = new ArrayList<>(); + private int[] mImage_bg; + private SwipeRefreshLayout mChannelRefresh; + private Banner mImageBanner; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_main_recommend_recommend, container, false); + mImage_bg = new int[]{getColor("#e5c9c9"), getColor("#c9d8e5"), getColor("#c9d3c1"), getColor("#cbcbc8"), getColor("#d3cbe4"), getColor("#cdd1d6")}; + initView(v); + mPage = 1; + getChannelData(mPage); + return v; + } + + private int getColor(String color) { + return Color.parseColor(color); + } + + private View mPageView; + private ViewPager mViewPager; + private ViewGroup mGroup; + private AdPagesManager mManager; + private List mBanners = new ArrayList<>(); + + private void initView(View v) { + mRvMainChannel = v.findViewById(R.id.rv_main_channel); + mRvMainChannel.setLayoutManager(new WrapStaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + + RecyclerView.LayoutManager mLayoutManager = mRvMainChannel.getLayoutManager(); + int[] into = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()]; + int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(into); + + int lastVisibleItemPosition = lastVisibleItemPositions[1] + 1; + + if (mChannelAnchors.size() != 0 && newPage < mPage && !isNodata && lastVisibleItemPosition > mChannelAnchors.size() - 2) { + getChannelData(mPage); + } + return super.canScrollVertically(); + } + }); + + mAdapter = new MainChannelAdapter(getActivity(), mImage_bg); + mAdapter.setAnchorListBeans(mChannelAnchors); + mRvMainChannel.setAdapter(mAdapter); + +// mPageView = v.findViewById(R.id.pager_view); +// +// WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE); +// DisplayMetrics dm = new DisplayMetrics(); +// wm.getDefaultDisplay().getMetrics(dm); +// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( +// ViewGroup.LayoutParams.MATCH_PARENT, dm.widthPixels / 3); +// +// mPageView.setLayoutParams(params); +// +// mViewPager = (ViewPager) v.findViewById(R.id.ad_pager); +// mGroup = (ViewGroup) v.findViewById(R.id.view_group); +// mManager = new AdPagesManager(mViewPager, mGroup, getContext()); +// mManager.setOnImageClickListener(new AdPagesManager.ImageClickListener() { +// @Override +// public void onClick(View v, int position) { +// if (null != mBanners) { +// int size = mBanners.size(); +// if (size != 0) { +// int i = position % size; +// JumpUtils.jump(mBanners.get(i).getLink_type(), +// mBanners.get(i).getLink_url(), getActivity()); +// } +// } +// +// } +// }); + + mChannelRefresh = v.findViewById(R.id.channel_refresh); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getChannelData(mPage); + } + }); + + AppBarLayout appBarLayout = v.findViewById(R.id.channel_app_bar); + appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if (verticalOffset == 0) { + mChannelRefresh.setEnabled(true); + + } else { + mChannelRefresh.setEnabled(false); + } + } + }); + + mBanners.clear(); + mImageBanner = v.findViewById(R.id.image_banner); + + } + + public void setChannelRefresh() { + mChannelRefresh.post(new Runnable() { + + @Override + public void run() { + mChannelRefresh.setRefreshing(true); + } + }); + } + + + List images = new ArrayList<>(); + + + private void addBanner() { +// Iterator bannerBeanIterator = mBanners.iterator(); +// mManager.clear(); +// while (bannerBeanIterator.hasNext()) { +// BannerBean bannerBean = bannerBeanIterator.next(); +// mManager.addImageViewByUrl(ConstUrl.IMAGE_URL + bannerBean.getImage()); +// } +// +// mManager.manage(); + images.clear(); + if (null != mBanners) { + if (mBanners.size() != 0) { + for (int i = 0; i < mBanners.size(); i++) { + images.add(StrU.getResourcePath(mBanners.get(i).getImage(), getActivity())); + } + } + } + //简单使用 + BaseUtils.setBannerLayoutParams(mImageBanner).setImages(images) + .setImageLoader(new GlideImageLoader()) + .setOnBannerListener(new OnBannerListener() { + @Override + public void OnBannerClick(int position) { + if (null != mBanners) { + int size = mBanners.size(); + if (size != 0) { + int i = position % size; + JumpUtils.jump(mBanners.get(i).getLink_type(), + mBanners.get(i).getLink_url(), getActivity()); + } + } + } + }) + .setDelayTime(3000) + .start() + .setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == 1) { + mChannelRefresh.setEnabled(false);//设置不可触发 + } else if (state == 2) { + mChannelRefresh.setEnabled(true);//设置可触发 + } + + } + }); + + } + + private int mPage = 1; + private int newPage = 1; + private boolean isNodata; + + private void getChannelData(int page) { + newPage = page; + MainManager.getNewAnchors((BaseActivity) getActivity(), mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() == 0) { + isNodata = true; + } else { + isNodata = false; + if (mPage == 1) { + mChannelAnchors.clear(); + mChannelAnchors.addAll(result.getList().getList()); + mAdapter.notifyDataSetChanged(); + } else { + List list = result.getList().getList(); + // 创建一个临时列表存储去重后的数据 + List filteredList = new ArrayList<>(); + for (AnchorBean newAnchor : list) { + boolean duplicate = false; + // 检查是否在mChannelAnchors中已存在 + for (AnchorBean existingAnchor : mChannelAnchors) { + if (newAnchor.getUserid() == existingAnchor.getUserid()) { + duplicate = true; + break; + } + } + // 如果不是重复数据,则添加到过滤列表 + if (!duplicate) { + filteredList.add(newAnchor); + } + } + int startPosition = mChannelAnchors.size(); + // 添加去重后的数据 + mChannelAnchors.addAll(filteredList); + mAdapter.notifyItemRangeInserted(startPosition, filteredList.size()); + } + } + } + } + } + + if (mPage == 1) { + if (null != mBanners && mBanners.size() == 0) { + mBanners = result.getBanner(); +// addBanner(); + } + } + mPage++; + + mChannelRefresh.setRefreshing(false); + } + + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + public void refresh() { + mPage = 1; + if (getActivity() != null) { + getChannelData(mPage); + } + if (null != mRvMainChannel) { + mRvMainChannel.scrollToPosition(0); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/ManVideoFinishActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/main/ManVideoFinishActivity.kt new file mode 100644 index 0000000..a8ace72 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/ManVideoFinishActivity.kt @@ -0,0 +1,271 @@ +package com.fengliyan.tianlesue.view.main + +import android.content.Intent +import android.graphics.Rect +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.facebook.drawee.view.SimpleDraweeView +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.ConsUser +import com.fengliyan.tianlesue.controller.constant.Constant +import com.fengliyan.tianlesue.controller.main.manager.MainManager +import com.fengliyan.tianlesue.databinding.ActivityManvideofinishBinding +import com.fengliyan.tianlesue.databinding.HolderFooterBinding +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit +import com.fengliyan.tianlesue.im.uikit.common.Constans +import com.fengliyan.tianlesue.model.main.* +import com.fengliyan.tianlesue.utils.SPUtils +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.diooto.tools.Utils +import com.fengliyan.tianlesue.view.settings.MemberActivity +import com.fengliyan.uikit.toast.MaleToast + +class ManVideoFinishActivity : BaseActivity() { + + lateinit var binding: ActivityManvideofinishBinding + val datas = mutableListOf() + var roomId: String = "" + var nickName: String? = "" + var uid: Int = 0 + var avatar: String? = "" + var callType: Int = 0 + lateinit var adapter: BaseQuickAdapter + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + try { + roomId = "${intent.getIntExtra("roomId", 0)}" + nickName = intent.getStringExtra("nickName") + avatar = intent.getStringExtra("avatar") + uid = intent.getIntExtra("uid", 0) + callType = intent.getIntExtra("callType", 0) + } catch (e: Exception) { + + } + binding = ActivityManvideofinishBinding.inflate(layoutInflater) + setContentView(binding.root) +// avatar = "images/banner/054eda04c80661a61319c21285e05e9c.png" + binding.avatarImageView.setImageURI(Constans.IMAGE_URL + avatar) + binding.coverImageView.setImageURI(Constans.IMAGE_URL + avatar) + + binding.avatarImageView.setOnClickListener { + val intent = Intent(this@ManVideoFinishActivity, MainPageActivity::class.java) + intent.putExtra("userId", uid) + startActivity(intent) + } + binding.clVip.setOnClickListener { + val intent = Intent( + this, + MemberActivity::class.java + ) + intent.putExtra("index", 0) + startActivity(intent) + } + + binding.nameLabel.text = nickName + binding.backBtn.setOnClickListener { + finish() + } + adapter = object : + BaseQuickAdapter(R.layout.item_fnishcall_recommand, datas) { + init { + addChildClickViewIds(R.id.videoBtn) + } + + override fun convert(helper: BaseViewHolder, item: AnchorBean) { + var imageView = helper.getView(R.id.avatarImageView) + imageView.setImageURI(Constans.IMAGE_URL + item.cover) + helper.setText(R.id.nameLabel, item.city + "·" + item.nickname) + helper.setText(R.id.priceLabel, "${item.price}金币/分钟") +// if (callType == 0) { + helper.setImageResource(R.id.videoBtn, R.mipmap.video_v3) +// } else { +// helper.setImageResource(R.id.videoBtn, R.mipmap.ic_voiec_v3) +// } + } + } + setDefaultTitle() + setTitleName("") + hideTitleBar() + var manager = GridLayoutManager(this, 2) + binding.recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + val position: Int = parent?.getChildAdapterPosition(view)!! + outRect?.top = Utils.dip2px(this@ManVideoFinishActivity, 12f) + if (position % 2 == 0) { + outRect?.right = Utils.dip2px(this@ManVideoFinishActivity, 6f) + } else { + outRect?.left = Utils.dip2px(this@ManVideoFinishActivity, 6f) + } +// super.getItemOffsets(outRect, view, parent, state) + } + }) + binding.recyclerView.layoutManager = manager + adapter.setOnItemClickListener { adapter, view, position -> + val intent = Intent(this@ManVideoFinishActivity, MainPageActivity::class.java) + val bean = datas[position] + intent.putExtra("userId", bean.getUserid()) + startActivity(intent) + } + + adapter.setOnItemChildClickListener { adapter, view, position -> + val bean = datas[position] + getCallInfo(bean.userid) + } +// binding.recyclerView.addOnItemTouchListener(object : OnItemClickListener() { +// override fun onItemClick( +// adapter: BaseQuickAdapter<*, *>?, +// view: View?, +// position: Int +// ) { +// +// } +// }) +// binding.recyclerView.addOnItemTouchListener(object : OnItemChildClickListener() { +// override fun onSimpleItemChildClick( +// adapter: BaseQuickAdapter<*, *>?, +// view: View?, +// position: Int +// ) { +// val bean = datas[position] +// getCallInfo(bean.userid) +// } +// }) + val footer = HolderFooterBinding.inflate(layoutInflater) + adapter.addFooterView(footer.root) + binding.recyclerView.adapter = adapter; + + if (callType == 0) { + binding.recallBtn.setImageResource(R.mipmap.recall) + } else { + binding.recallBtn.setImageResource(R.mipmap.ic_recall_voice) + } + binding.recallBtn.setOnClickListener { + getCallInfo(uid) + } + binding.msgBtn.setOnClickListener { + NimUIKit.startChat("${uid}", ManVideoFinishActivity@ this); + } + refresh() + } + + override fun onResume() { + super.onResume() + if (SPUtils.getBoolean(this, ConsUser.USER_VIP, false)) { + binding.clVip.visibility = View.GONE + } else { + binding.clVip.visibility = View.VISIBLE + } + } + + private fun getCallInfo(uid: Int) { + MainManager.getCallInfo(this, uid, 1, callType, object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: CallBean?, message: String?) { + val intent = + Intent(this@ManVideoFinishActivity, AgoraWithFUVideoActivity::class.java) + intent.putExtra(Constant.SOCKET_URL, result!!.socket_url) + intent.putExtra("isCaller", true) + intent.putExtra("callType", callType) + intent.putExtra("roomId", Integer.valueOf(result.room_id)) + intent.putExtra("avatar", result.to_avatar) + intent.putExtra("nickName", result.to_nickname) + intent.putExtra("price", result.skill.price) + intent.putExtra("toUid", result.to_uid) + intent.putExtra("porn_check_bean_v2", result.porn_checkV2) + intent.putExtra("diff_num", result.guard.diff_num) + intent.putExtra("guard_price", result.guard.guard_price) + intent.putExtra("free_num", result.free_num) + intent.putExtra( + "isRisk", + result.from_risk_status == 1 || result.to_risk_status == 1 + ) + startActivity(intent) + } + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(activity, "请重试") + } + }) + } + + fun refresh() { + getVideoFee() + MainManager.getCallEndRecommend(this, object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: AnchorListBean?, + message: String? + ) { + if (null != result) { + if (null != result.list) { + datas.clear() + datas.addAll(result.list) + adapter.notifyDataSetChanged() + } + } + } + + override fun onFailure(activity: BaseActivity, tip: String) { + + } + + override fun onException(activity: BaseActivity, e: Throwable) { + + } + }) + } + + private fun getVideoFee() { + MainManager.getVideoFee(this, roomId, object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: VideoFeeBean?, + message: String? + ) { + val pay_money = result!!.pay_money +// if (mIsCaller) { +// if (!TextUtils.isEmpty(pay_money)) { +// val d = pay_money.toDouble() +// val money = d.toInt() +// mTv_cost.setText("本次花费" + money + "金币") +// } +// } + binding.durationLabel.setText(secondToTime(result.call_time)) + + } + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(this@ManVideoFinishActivity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(this@ManVideoFinishActivity, "请重试") + } + }) + } + + private fun secondToTime(second: Long): String? { + var second = second + val days = second / 86400 + second = second % 86400 + val hours = second / 3600 + second = second % 3600 + val minutes = second / 60 + second = second % 60 + return String.format("%02d:%02d:%02d", hours + days * 24, minutes, second) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/PlayVideoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/PlayVideoActivity.java new file mode 100644 index 0000000..ddf70c7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/PlayVideoActivity.java @@ -0,0 +1,496 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.activity.result.ActivityResult; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.airbnb.lottie.LottieAnimationView; +import com.facebook.drawee.view.SimpleDraweeView; +import com.google.android.exoplayer2.DefaultRenderersFactory; +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; +import com.google.android.exoplayer2.ui.PlayerView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.utils.ToastUtil; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.utils.GlideUtils; +import com.fengliyan.tianlesue.utils.ProgressView; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.ui.VerticalViewPager; +import com.fengliyan.tianlesue.view.main.utils.DefaultExoConfig; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + + +public class PlayVideoActivity extends BaseActivity { + private static final String TAG = "PlayVideoActivity"; + private ImageView iv_back; + private VerticalViewPager mVerticalViewpager; + private PlayerView videoView; + private ExoPlayer player; + private List mList = new ArrayList<>();// + private ImageView img_thumb; + private ImageView img_play; + private RelativeLayout rootView; + private SimpleDraweeView iv_user_avatar; + private TextView tv_nick_name; + private TextView tv_age; + private ImageView iv_follow; + private LottieAnimationView iv_call; + private ProgressView mProgress; + private List mViews = new ArrayList<>(); + private DouYinAdapter mDouYinAdapter; + private int position; + private int mCurrentItem; + private int mPlayingPosition; + private ActivityResultLauncher launcher; + private int mPage = 1; + private CountDownTimer mCallCountDownTimer; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback() { + @Override + public void onActivityResult(ActivityResult result) { + Log.i(TAG, "onActivityResult: ------->" + result); + } + }); + setContentView(R.layout.activity_vertical_video); + initTitle(); + initView(); + } + + public void initTitle() { + hideTitleBar(); + } + + public void initView() { + mList = (List) getIntent().getSerializableExtra("videoUrlList"); + position = getIntent().getIntExtra("position", 0); + mPage = getIntent().getIntExtra("page", 1); + mCurrentItem = position; + iv_back = findViewById(R.id.iv_back); + iv_user_avatar = findViewById(R.id.iv_user_avatar); + tv_nick_name = findViewById(R.id.tv_nick_name); + tv_age = findViewById(R.id.tv_age); + iv_follow = findViewById(R.id.iv_follow); + + mVerticalViewpager = findViewById(R.id.verticalviewpager); + videoView = new PlayerView(this); + videoView.setUseController(false); + videoView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM); + mProgress = findViewById(R.id.progress); + mProgress.setRadius(36f); + mProgress.post(new Runnable() { + @Override + public void run() { + //设置进度条长度 默认px + mProgress.setProgress(mProgress.getMeasuredWidth()); + //设置动画时间 + mProgress.setDuration(15000); + mProgress.startAnim(); + } + }); + iv_back.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + finish(); + } + }); + + iv_user_avatar.setImageURI(StrU.getResourcePath(mList.get(mCurrentItem).getCover(), this)); + iv_user_avatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(PlayVideoActivity.this, MainPageActivity.class); + intent.putExtra("userId", mList.get(mCurrentItem).getUserid()); + launcher.launch(intent); + } + }); + if (!TextUtils.isEmpty(mList.get(mCurrentItem).getNickname())) { + tv_nick_name.setText(mList.get(mCurrentItem).getNickname()); + } + tv_age.setText(mList.get(mCurrentItem).getAge() + ""); + if (mList.get(mCurrentItem).isIs_follow()) { + iv_follow.setImageResource(R.drawable.ic_play_follow); + } else { + iv_follow.setImageResource(R.drawable.ic_play_unfollow); + } + iv_follow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + focus(mList.get(mCurrentItem).getUserid() + "", iv_follow); + } + }); + getImageData(); + } + + public void getImageData() { + initVideoView(this); + mDouYinAdapter = new DouYinAdapter(mViews); + mVerticalViewpager.setAdapter(mDouYinAdapter); + + if (position != -1) { + mVerticalViewpager.setCurrentItem(position); + if (position == mList.size() - 1) { + getServerLuckList(); + } + } + + mVerticalViewpager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + mCurrentItem = position; + player.pause(); + mProgress.stopAnim(); + if (mCallCountDownTimer != null) { + mCallCountDownTimer.cancel(); + } + if (mCurrentItem == mList.size() - 1) { + getServerLuckList(); + ToastUtil.showToast(PlayVideoActivity.this, "加载中,请稍后"); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + if (isEnd) { + if (mCurrentItem == mList.size() - 1 && isEmpty && state == VerticalViewPager.SCROLL_STATE_IDLE) { + mVerticalViewpager.setCurrentItem(0); + } + } + isEnd = mCurrentItem == mList.size() - 1; + if (mPlayingPosition == mCurrentItem) return; + if (state == VerticalViewPager.SCROLL_STATE_IDLE) { + player.release(); + player = null; + mProgress.stopAnim(); + if (mCallCountDownTimer != null) { + mCallCountDownTimer.cancel(); + } + ViewParent parent = videoView.getParent(); + if (parent instanceof FrameLayout) { + ((FrameLayout) parent).removeView(videoView); + } + startPlay(); + } + } + }); + + mVerticalViewpager.post(new Runnable() { + @Override + public void run() { + startPlay(); + } + }); + } + + private void initVideoView(BaseActivity playVideoActivity) { + for (AnchorBean item : mList) { + View view = LayoutInflater.from(playVideoActivity).inflate(R.layout.item_play_video_view, null); + img_thumb = view.findViewById(R.id.img_thumb); + img_play = view.findViewById(R.id.img_play); + rootView = view.findViewById(R.id.root_view); + iv_call = view.findViewById(R.id.iv_call); + iv_call.setImageAssetsFolder("images/"); + iv_call.setAnimation("video_call_btn.json"); + iv_call.playAnimation(); + GlideUtils.showImage(playVideoActivity, img_thumb, item.getCover()); + + iv_call.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getCallInfo(item.getUserid(), 0); +// Intent intent = new Intent(PlayVideoActivity1.this, PushVideoActivity.class); +// CallBean callBean = new CallBean(); +// callBean.setUser_id(item.getUserid()); +// callBean.setAge(item.getAge()); +// callBean.setVideo_url(item.getCover_video()); +// callBean.setNickname(item.getNickname()); +// callBean.setAvatar_url(item.getCover()); +//// callBean.setIs_follow(bean.get()); +// intent.putExtra("result", callBean); +// startActivity(intent); + } + }); + mViews.add(view); + } + } + + private void startPlay() { + View view = mViews.get(mCurrentItem); + FrameLayout frameLayout = view.findViewById(R.id.container); + ViewGroup parent = (ViewGroup) videoView.getParent(); + if (parent != null) { + parent.removeAllViews(); + } + frameLayout.addView(videoView); + player = new SimpleExoPlayer.Builder(this, new DefaultRenderersFactory(this).setEnableDecoderFallback(true)).build(); + if (player.getAudioComponent() != null) { + player.getAudioComponent().setVolume(40); + } + player.setRepeatMode(Player.REPEAT_MODE_ONE); + videoView.setPlayer(player); + if (!StrU.isEmpty(mList.get(mCurrentItem).getCover_video())) { + player.setMediaSource(new DefaultExoConfig(this).createMediaSource(Uri.parse(StrU.getResourcePath(mList.get(mCurrentItem).getCover_video(), this)))); + player.prepare(); + player.setPlayWhenReady(true); + } + iv_user_avatar.setImageURI(StrU.getResourcePath(mList.get(mCurrentItem).getCover(), this)); + if (!TextUtils.isEmpty(mList.get(mCurrentItem).getNickname())) { + tv_nick_name.setText(mList.get(mCurrentItem).getNickname()); + } + tv_age.setText(mList.get(mCurrentItem).getAge() + ""); + if (mList.get(mCurrentItem).isIs_follow()) { + iv_follow.setImageResource(R.drawable.ic_play_follow); + } else { + iv_follow.setImageResource(R.drawable.ic_play_unfollow); + } + mProgress.startAnim(); + initCountDown(0); + mCallCountDownTimer.start(); + mPlayingPosition = mCurrentItem; + } + + @Override + public void onPause() { + super.onPause(); + if (player != null) { + player.pause(); + } + if (mCallCountDownTimer != null) { + mCallCountDownTimer.cancel(); + } + mProgress.getAnimator().pause(); + } + + @Override + public void onResume() { + super.onResume(); + if (player != null) { + player.play(); + } + initCountDown(mProgress.currentPlayTime()); + mCallCountDownTimer.start(); + mProgress.getAnimator().resume(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (player != null) { + player.release(); + player = null; + } + if (mCallCountDownTimer != null) { + mCallCountDownTimer.cancel(); + } + } + + public class DouYinAdapter extends PagerAdapter { + + private static final String TAG = "DouYinAdapter"; + + private List mViews; + + public DouYinAdapter(List views) { + this.mViews = views; + } + + + public void setmViews(List mViews) { + this.mViews = mViews; + } + + @Override + public int getCount() { + return mViews.size(); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Log.d(TAG, "instantiateItem: called"); + container.addView(mViews.get(position)); + return mViews.get(position); + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + Log.d(TAG, "destroyItem: "); + container.removeView(mViews.get(position)); + } + } + + private void initCountDown(long currentPlayTime) { + if (mCallCountDownTimer == null) { + mCallCountDownTimer = new CountDownTimer(15000 - currentPlayTime, 1000) { + @Override + public void onFinish() { + if (mCurrentItem < mList.size() - 1) { + mVerticalViewpager.setCurrentItem(mCurrentItem + 1); + } else { + if (mCurrentItem == mList.size() - 1) { + if (isEmpty) { + mVerticalViewpager.setCurrentItem(0); + } else { + mVerticalViewpager.setCurrentItem(mCurrentItem + 1); + } + } + } + } + + @Override + public void onTick(long millisUntilFinished) { + } + }; + } + } + + private void focus(String userId, ImageView iv_follow) { + DynamicsManager.follow(this, + userId, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + if (result != null) { + if (StrU.equals("add", result.getAction())) { + iv_follow.setImageResource(R.drawable.ic_play_follow); + MaleToast.showMessage(activity, "关注成功"); + mList.get(mCurrentItem).setIs_follow(true); + } else { + iv_follow.setImageResource(R.drawable.ic_play_unfollow); + MaleToast.showMessage(activity, message); + mList.get(mCurrentItem).setIs_follow(false); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "关注失败"); + } + }); + } + + private void getCallInfo(int mUid, int callType) { + MainManager.getCallInfo(this, mUid, 1, callType, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(activity, AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", true); + intent.putExtra("callType", callType); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + CallBean callBean = new CallBean(); + callBean.setUser_id(mList.get(mCurrentItem).getUserid() + ""); + callBean.setAge(mList.get(mCurrentItem).getAge()); + callBean.setVideo_url(mList.get(mCurrentItem).getCover_video()); + callBean.setNickname(mList.get(mCurrentItem).getNickname()); + callBean.setAvatar_url(mList.get(mCurrentItem).getCover()); +// callBean.setIs_follow(bean.get()); + intent.putExtra("bean", callBean); + launcher.launch(intent); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private boolean isEmpty; + private boolean isEnd; + + private void getServerLuckList() { + MainManager.getCoverVideo(this, mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() > 0) { + isEmpty = false; + mPage++; + mList.addAll(result.getList().getList()); + mViews.clear();//加载更多需要先清空原来的view + initVideoView(activity); + + mDouYinAdapter.setmViews(mViews); + mDouYinAdapter.notifyDataSetChanged(); + } else { + isEmpty = true; + } + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/PushVideoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/PushVideoActivity.java new file mode 100644 index 0000000..94044e4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/PushVideoActivity.java @@ -0,0 +1,235 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.flyco.roundview.RoundTextView; +import com.google.android.exoplayer2.DefaultRenderersFactory; +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.ui.PlayerView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.utils.GlideUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.HangUpDialog; +import com.fengliyan.tianlesue.view.main.utils.DefaultExoConfig; +import com.fengliyan.uikit.toast.MaleToast; + +public class PushVideoActivity extends BaseActivity implements View.OnClickListener { + private PlayerView video_view; + private SimpleDraweeView iv_user_avatar; + private ImageView iv_avatar; + private TextView tv_nick_name; + private TextView tv_age; + private ImageView iv_follow; + private TextView tv_hangup; + private TextView tv_call; + private RoundTextView tv_call1; + private CallBean bean; + private ExoPlayer player; + private MediaPlayer mMediaPlayer; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_push_video_view); + hideTitleBar(); + bean = (CallBean) getIntent().getSerializableExtra("result"); + initView(); + initData(); + mMediaPlayer = MediaPlayer.create(this, R.raw.call_bg); + mMediaPlayer.setLooping(true); + if (null != mMediaPlayer) { + mMediaPlayer.start(); + } + } + + private void initView() { + video_view = findViewById(R.id.video_view); + iv_avatar = findViewById(R.id.iv_avatar); + iv_user_avatar = findViewById(R.id.iv_user_avatar); + tv_nick_name = findViewById(R.id.tv_nick_name); + tv_age = findViewById(R.id.tv_age); + iv_follow = findViewById(R.id.iv_follow); + tv_hangup = findViewById(R.id.tv_hangup); + tv_call = findViewById(R.id.tv_call); + tv_call1 = findViewById(R.id.tv_call1); + iv_follow.setOnClickListener(this); + tv_hangup.setOnClickListener(this); + tv_call.setOnClickListener(this); + tv_call1.setOnClickListener(this); + } + + private void initData() { + +// player.prepare(new DefaultExoConfig(this).createMediaSource(Uri.parse(StrU.getResourcePath(bean.getVideo_url(), this)))); +//// player.prepare(new DefaultExoConfig(this).createMediaSource(Uri.parse(StrU.getResourcePath("uploads/cover_video/202405/14/17ab062d311ee4cb418a6bb5432f9bf8_.pic.mp4", this)))); +// if (player.getAudioComponent() != null) { +// player.getAudioComponent().setVolume(40); +// } +// player.setRepeatMode(Player.REPEAT_MODE_ONE); +// player.setPlayWhenReady(true); + if (bean != null) { + if (!StrU.isEmpty(bean.getAvatar_url())) { + iv_user_avatar.setImageURI(StrU.getResourcePath(bean.getAvatar_url(), this)); + } + tv_nick_name.setText(bean.getNickname()); + tv_age.setText(bean.getAge() + ""); + if (bean.isIs_follow()) { + iv_follow.setImageResource(R.drawable.ic_play_follow); + } else { + iv_follow.setImageResource(R.drawable.ic_play_unfollow); + } + if (!StrU.isEmpty(bean.getVideo_url())) { + iv_avatar.setVisibility(View.GONE); + iv_avatar.setImageResource(0); + video_view.setVisibility(View.VISIBLE); + player = new SimpleExoPlayer.Builder(this, new DefaultRenderersFactory(this).setEnableDecoderFallback(true)).build(); + video_view.setPlayer(player); + player.setMediaSource(new DefaultExoConfig(this).createMediaSource(Uri.parse(StrU.getResourcePath(bean.getVideo_url(), this)))); +// player.setMediaSource(new DefaultExoConfig(this).createMediaSource(Uri.parse(StrU.getResourcePath("uploads/cover_video/202405/14/17ab062d311ee4cb418a6bb5432f9bf8_.pic.mp4", this)))); + player.prepare(); + if (player.getAudioComponent() != null) { + player.getAudioComponent().setVolume(0); + } + player.setRepeatMode(Player.REPEAT_MODE_ONE); + player.setPlayWhenReady(true); + } else { + video_view.setVisibility(View.GONE); + iv_avatar.setVisibility(View.VISIBLE); + GlideUtils.showImage(this, iv_avatar, bean.getAvatar_url()); + } + } + } + + private void focus() { + DynamicsManager.follow(this, + bean.getUser_id(), + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + if (result != null) { + if (StrU.equals("add", result.getAction())) { + iv_follow.setImageResource(R.drawable.ic_play_follow); + MaleToast.showMessage(PushVideoActivity.this, "关注成功"); + } else { + iv_follow.setImageResource(R.drawable.ic_play_unfollow); + MaleToast.showMessage(PushVideoActivity.this, message); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(PushVideoActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(PushVideoActivity.this, "关注失败"); + } + }); + } + + private void getCallInfo() { + MainManager.getCallInfo(this, Integer.parseInt(bean.getUser_id()), 0, 0, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(activity, AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", true); + intent.putExtra("callType", 0); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + intent.putExtra("bean", bean); + startActivity(intent); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_follow: + focus(); + break; + case R.id.tv_hangup: + HangUpDialog hangUpDialog = new HangUpDialog(this, new HangUpDialog.OnHangUpListener() { + @Override + public void onHangUp() { + finish(); + } + }); + hangUpDialog.show(); + break; + case R.id.tv_call: + case R.id.tv_call1: + getCallInfo(); + break; + } + } + + @Override + public void onPause() { + super.onPause(); + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + } + if (player != null) { + player.pause(); + } + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + } + if (player != null) { + player.release(); + player = null; + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/RecommendFragment1.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/RecommendFragment1.java new file mode 100644 index 0000000..cebb1c8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/RecommendFragment1.java @@ -0,0 +1,483 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import androidx.viewpager.widget.ViewPager; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.google.android.material.appbar.AppBarLayout; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.adapter.MainChannelAdapter1; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.utils.BaseUtils; +import com.fengliyan.tianlesue.utils.GlideImageLoader; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.tianlesue.view.rank.ZhiRankActivity; +import com.fengliyan.uikit.adboard.AdPagesManager; +import com.youth.banner.Banner; +import com.youth.banner.listener.OnBannerListener; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/11. + */ + +public class RecommendFragment1 extends Fragment implements View.OnClickListener { + + private RecyclerView mRvMainChannel; + // private MainChannelAdapter mAdapter; + private MainChannelAdapter1 mAdapter; + + private List mChannelAnchors = new ArrayList<>(); + private int[] mImage_bg; + private SwipeRefreshLayout mChannelRefresh; + private Banner mImageBanner; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_recommend1, container, false); + mImage_bg = new int[]{getColor("#e5c9c9"), getColor("#c9d8e5"), getColor("#c9d3c1"), getColor("#cbcbc8"), getColor("#d3cbe4"), getColor("#cdd1d6")}; +// mImage_bg = new int[]{R.drawable.shape_bg_1, R.drawable.shape_bg_2, R.drawable.shape_bg_3, R.drawable.shape_bg_4, R.drawable.shape_bg_5, R.drawable.shape_bg_6}; + initView(v); + mPage = 1; + getChannelData(mPage); + return v; + } + + private int getColor(String color) { + return Color.parseColor(color); + } + + private View mPageView; + private ViewPager mViewPager; + private ViewGroup mGroup; + private AdPagesManager mManager; + private List mBanners = new ArrayList<>(); + private SimpleDraweeView mLoveRank1; + private SimpleDraweeView mLoveRank2; + private SimpleDraweeView mLoveRank3; + private View mLoveRankLayout; + private SimpleDraweeView mWealthRank1; + private SimpleDraweeView mWealthRank2; + private SimpleDraweeView mWealthRank3; + private View mWealthRankLayout; + + private void initView(View v) { + + + mLoveRank1 = v.findViewById(R.id.recommend_love_1); + mLoveRank2 = v.findViewById(R.id.recommend_love_2); + mLoveRank3 = v.findViewById(R.id.recommend_love_3); + mLoveRankLayout = v.findViewById(R.id.recommend_love_rank); + mWealthRank1 = v.findViewById(R.id.recommend_wealth_1); + mWealthRank2 = v.findViewById(R.id.recommend_wealth_2); + mWealthRank3 = v.findViewById(R.id.recommend_wealth_3); + mWealthRankLayout = v.findViewById(R.id.recommend_wealth_rank); + + mLoveRankLayout.setOnClickListener(this); + mWealthRankLayout.setOnClickListener(this); + + mRvMainChannel = v.findViewById(R.id.rv_recommend_channel); + mRvMainChannel.setLayoutManager(new WrapStaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + + RecyclerView.LayoutManager mLayoutManager = mRvMainChannel.getLayoutManager(); + int[] into = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()]; + int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(into); + + int lastVisibleItemPosition = lastVisibleItemPositions[1] + 1; + if (mChannelAnchors.size() != 0 && newPage < mPage && !isNodata && lastVisibleItemPosition > mChannelAnchors.size() - 2) { + getChannelData(mPage); + } + return super.canScrollVertically(); + } + }); + +// mAdapter = new MainChannelAdapter(getActivity(), mImage_bg); + mAdapter = new MainChannelAdapter1(getActivity(), "recommend"); + mAdapter.setShowNewPeople(true); + mAdapter.setOnPlay(new MainChannelAdapter1.OnPlay() { + @Override + public void goPlayVideoList() { + if (beanList != null && beanList.size() > 0) { + Intent intent = new Intent(getContext(), PlayVideoActivity.class); + intent.putExtra("videoUrlList", (Serializable) beanList); + intent.putExtra("position", videoPosition - 1); + intent.putExtra("page", page); + startActivity(intent); + } + } + + @Override + public void getVideo(@NonNull AnchorBean data) { + isPlay = true; + if (isResume) { + setVideoBean(); + } + } + }); +// mAdapter.setAnchorListBeans(mChannelAnchors); + mRvMainChannel.setAdapter(mAdapter); + + mChannelRefresh = v.findViewById(R.id.channel_refresh); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + page = 1; + videoPosition = 0; + beanList.clear(); + mAdapter.setPlay(false); + getChannelData(mPage); + } + }); + + AppBarLayout appBarLayout = v.findViewById(R.id.channel_app_bar); + appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if (verticalOffset == 0) { + mChannelRefresh.setEnabled(true); + + } else { + mChannelRefresh.setEnabled(false); + } + } + }); + + mBanners.clear(); + mImageBanner = v.findViewById(R.id.image_banner); + + } + + public void setChannelRefresh() { + mChannelRefresh.post(new Runnable() { + + @Override + public void run() { + mChannelRefresh.setRefreshing(true); + } + }); + } + + List images = new ArrayList<>(); + + private void addBanner() { +// Iterator bannerBeanIterator = mBanners.iterator(); +// mManager.clear(); +// while (bannerBeanIterator.hasNext()) { +// BannerBean bannerBean = bannerBeanIterator.next(); +// mManager.addImageViewByUrl(ConstUrl.IMAGE_URL + bannerBean.getImage()); +// } +// +// mManager.manage(); + images.clear(); + if (null != mBanners) { + if (mBanners.size() != 0) { + for (int i = 0; i < mBanners.size(); i++) { + images.add(StrU.getResourcePath(mBanners.get(i).getImage(), getActivity())); + } + } + } + + //简单使用 + BaseUtils.setBannerLayoutParams(mImageBanner).setImages(images) + .setImageLoader(new GlideImageLoader()) + .setOnBannerListener(new OnBannerListener() { + @Override + public void OnBannerClick(int position) { + if (null != mBanners) { + int size = mBanners.size(); + if (size != 0) { + int i = position % size; + JumpUtils.jump(mBanners.get(i).getLink_type(), + mBanners.get(i).getLink_url(), getActivity()); + } + } + } + }) + .setDelayTime(3000) + .start() + .setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == 1) { + mChannelRefresh.setEnabled(false);//设置不可触发 + } else if (state == 2) { + mChannelRefresh.setEnabled(true);//设置可触发 + } + + } + }); + } + + @Override + public void onResume() { + super.onResume(); + isResume = true; + if (isPlay) { +// setVideoBean(); + } + } + + @Override + public void onPause() { + super.onPause(); + isResume = false; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + isResume = false; + } + + private boolean isPlay; + private boolean isResume; + private int mPage = 1; + private int newPage = 1; + private boolean isNodata; + + private void getChannelData(int page) { + newPage = page; + MainManager.getRecommendAnchors((BaseActivity) getActivity(), mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() == 0) { + isNodata = true; + } else { + isNodata = false; + if (mPage == 1) { + mChannelAnchors.clear(); + mChannelAnchors.addAll(result.getList().getList()); + mAdapter.setList(result.getList().getList()); + } else { + List list = result.getList().getList(); + // 创建一个临时列表存储去重后的数据 + List filteredList = new ArrayList<>(); + for (AnchorBean newAnchor : list) { + boolean duplicate = false; + // 检查是否在mChannelAnchors中已存在 + for (AnchorBean existingAnchor : mChannelAnchors) { + if (newAnchor.getUserid() == existingAnchor.getUserid()) { + duplicate = true; + break; + } + } + // 如果不是重复数据,则添加到过滤列表 + if (!duplicate) { + filteredList.add(newAnchor); + } + } + // 添加去重后的数据 + mChannelAnchors.addAll(filteredList); + mAdapter.addData(filteredList); + } +// if (mPage == 1 && result.getVideo_list() != null) { +// getCoverVideo(); +//// result.getVideo_list().setVideo(true); +//// beanList.add(result.getVideo_list()); +//// mChannelAnchors.add(3, result.getVideo_list()); +// } + } + } + } + if (mPage == 1) { + if (null != mBanners && mBanners.size() == 0) { + mBanners = result.getBanner(); +// addBanner(); + } + + if (null != result.getRank()) { + if (null != result.getRank().getLove_rank()) { + int size = result.getRank().getLove_rank().size(); + if (size == 1) { + mLoveRank1.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getLove_rank().get(0).getAvatar()); + } else if (size == 2) { + mLoveRank1.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getLove_rank().get(0).getAvatar()); + mLoveRank2.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getLove_rank().get(1).getAvatar()); + } else if (size == 3) { + mLoveRank1.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getLove_rank().get(0).getAvatar()); + mLoveRank2.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getLove_rank().get(1).getAvatar()); + mLoveRank3.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getLove_rank().get(2).getAvatar()); + } + } + + if (null != result.getRank().getWealth_rank()) { + int size = result.getRank().getWealth_rank().size(); + if (size == 1) { + mWealthRank1.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getWealth_rank().get(0).getAvatar()); + } else if (size == 2) { + mWealthRank1.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getWealth_rank().get(0).getAvatar()); + mWealthRank2.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getWealth_rank().get(1).getAvatar()); + } else if (size == 3) { + mWealthRank1.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getWealth_rank().get(0).getAvatar()); + mWealthRank2.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getWealth_rank().get(1).getAvatar()); + mWealthRank3.setImageURI(ConstUrl.IMAGE_URL + + result.getRank().getWealth_rank().get(2).getAvatar()); + } + } + + + } + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + private List beanList = new ArrayList<>(); + private int videoPosition = 0; + private int page = 1; + private boolean canRemove; + + private void setVideoBean() { + if (beanList.size() > videoPosition) { + AnchorBean bean = beanList.get(videoPosition); + bean.setVideo(true); + if (videoPosition == 0) { + mAdapter.addData(3, bean); + mChannelAnchors.add(3, bean); + } else { + mAdapter.setData(3, bean); + mChannelAnchors.set(3, bean); + } + canRemove = true; + isPlay = false; + videoPosition++; + } else { + getCoverVideo(); + } + } + + private void getCoverVideo() { + MainManager.getCoverVideo((BaseActivity) getActivity(), page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList() && result.getList().getList().size() > 0) { + if (mAdapter.getItemCount() > 3) { + beanList.addAll(result.getList().getList()); +// if (page == 1) { +// beanList.remove(0); +// } + setVideoBean(); +// AnchorBean bean = result.getList().getList().get(0); +// bean.setVideo(true); +// mAdapter.setData(3, bean); +// isPlay = false; + } + page++; + } else { + if (canRemove) { + mAdapter.removeAt(3); + canRemove = false; + } + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + @Override + public void onClick(View view) { + if (mLoveRankLayout == view) { + Intent intent = new Intent(getActivity(), ZhiRankActivity.class); + intent.putExtra("rankType", 0); + getActivity().startActivity(intent); + } else if (mWealthRankLayout == view) { + Intent intent = new Intent(getActivity(), ZhiRankActivity.class); + intent.putExtra("rankType", 1); + getActivity().startActivity(intent); + } + } + + public void refresh() { + mPage = 1; + page = 1; + videoPosition = 0; + beanList.clear(); + if (getActivity() != null) { + if (mAdapter != null) { + mAdapter.setPlay(false); + } + getChannelData(mPage); + } + if (null != mRvMainChannel) { + mRvMainChannel.scrollToPosition(0); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/RedEnvelopesActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/RedEnvelopesActivity.java new file mode 100644 index 0000000..29b7f8e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/RedEnvelopesActivity.java @@ -0,0 +1,80 @@ +package com.fengliyan.tianlesue.view.main; + +import android.os.Bundle; +import androidx.recyclerview.widget.RecyclerView; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.AbsoluteSizeSpan; +import android.text.style.StyleSpan; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.RedEnvelopesAdpater; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.model.main.RedEnvelopesBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; + + +/** + * ying 2021/1/25 + * Describe :抢红包页 + */ + +public class RedEnvelopesActivity extends BaseActivity { + + private TextView mNumber; + private TextView red_title2; + private TextView red_tips; + private RecyclerView mRecyclerView; + private LinearLayout mTitle1Layout; + private String mRp_id; + private int mStatus; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_red); + mRp_id = getIntent().getStringExtra("rp_id"); + mStatus = getIntent().getIntExtra("status", 0); + initTitle(); + initView(); + } + + private void initView() { + mNumber = findViewById(R.id.red_title1_number); + mTitle1Layout = findViewById(R.id.red_title1); + red_title2 = findViewById(R.id.red_title2); + red_tips = findViewById(R.id.red_tips); + + mRecyclerView = findViewById(R.id.red_rv); + mRecyclerView.setAdapter(new RedEnvelopesAdpater(this, mRp_id, mRecyclerView, new RedEnvelopesAdpater.onRedEnvelopesListener() { + @Override + public void oneListener(RedEnvelopesBean result) { + if (result.page != 1) { + return; + } + + if (mStatus != 1) { + mTitle1Layout.setVisibility(View.GONE); + red_title2.setVisibility(View.VISIBLE); + } else { + SpannableStringBuilder spannableString = new SpannableStringBuilder(result.meReward + " 金币"); + spannableString.setSpan(new AbsoluteSizeSpan(ScreenUtil.sp2px(53)), 0, result.meReward.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, result.meReward.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + mNumber.setText(spannableString); + mTitle1Layout.setVisibility(View.VISIBLE); + red_title2.setVisibility(View.GONE); + } + + red_tips.setText(result.tips); + } + + })); + } + + private void initTitle() { + hideTitleBar(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/SearchActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/SearchActivity.java new file mode 100644 index 0000000..a36826b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/SearchActivity.java @@ -0,0 +1,218 @@ +package com.fengliyan.tianlesue.view.main; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.SearchAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.SearchBean; +import com.fengliyan.tianlesue.model.main.SearchListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.title.Title; + +import java.util.ArrayList; +import java.util.List; + +public class SearchActivity extends BaseActivity implements View.OnClickListener { + + private View mSearchView; + private EditText mSearchEdit; + private LoadMoreListView mListView; + private View mOptionView; + private TextView mTypeAll; + private TextView mTypeNumber; + private TextView mNickName; + private TextView mGenderAll; + private TextView mMaleView; + private TextView mFemaleView; + private RelativeLayout mCancelView; + private SearchAdapter mSearchAdapter; + private List mSearchList = new ArrayList<>(); + private int mSelectedType; + private int mSelectedGender; + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + String searchText = mSearchEdit.getText().toString(); + if (TextUtils.isEmpty(searchText)) { + mListView.setVisibility(View.GONE); + mOptionView.setVisibility(View.VISIBLE); + } else { + search(); + } + } + }; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_search); + initTitle(); + initView(); + } + + + private void initView() { + mListView = findViewById(R.id.search_list); + mTypeAll = findViewById(R.id.search_type_all); + mTypeNumber = findViewById(R.id.search_type_number); + mNickName = findViewById(R.id.search_type_nickname); + mGenderAll = findViewById(R.id.search_gender_all); + mMaleView = findViewById(R.id.search_gender_male); + mFemaleView = findViewById(R.id.search_gender_female); + mCancelView = findViewById(R.id.search_cancel); + mOptionView = findViewById(R.id.search_option_layout); + mSearchAdapter = new SearchAdapter(this); + mSearchAdapter.setSearchList(mSearchList); + mListView.setAdapter(mSearchAdapter); + mListView.dimissEmptyView(); + mTypeAll.setOnClickListener(this); + mTypeNumber.setOnClickListener(this); + mNickName.setOnClickListener(this); + mGenderAll.setOnClickListener(this); + mMaleView.setOnClickListener(this); + mFemaleView.setOnClickListener(this); + mCancelView.setOnClickListener(this); + mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + SearchBean bean = mSearchList.get(i); + Intent intent = new Intent(SearchActivity.this, MainPageActivity.class); + intent.putExtra("userId", bean.getUserid()); + startActivity(intent); + } + }); + mSearchEdit.addTextChangedListener(mTextWatcher); + mSearchEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + search(); + InputMethodManager imm = (InputMethodManager) + getSystemService(Context.INPUT_METHOD_SERVICE); + + imm.hideSoftInputFromWindow(mSearchEdit.getWindowToken(), 0); + return true; + } + + return false; + } + }); + } + + private void initTitle() { + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(R.color.yellow_ffd33e); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mSearchView = View.inflate(this, R.layout.item_search_title, null); + mSearchEdit = mSearchView.findViewById(R.id.search_title_input); + + mSearchEdit.setFocusable(true); + mSearchEdit.setFocusableInTouchMode(true); + mSearchEdit.requestFocus(); + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + + title.addViewTo(mSearchView, POSTION_CENTER); + } + + private void search() { + String searchText = mSearchEdit.getText().toString(); + if (TextUtils.isEmpty(searchText)) { + return; + } + + MainManager.search(this, mSelectedType, searchText, mSelectedGender, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SearchListBean result, String message) { + mOptionView.setVisibility(View.GONE); + mListView.setVisibility(View.VISIBLE); + mSearchList.clear(); + mSearchList.addAll(result.getList()); + mSearchAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + if (view == mTypeAll) { + mTypeAll.setBackgroundResource(R.drawable.shape_button_enable); + mTypeNumber.setBackgroundResource(R.drawable.shape_button_disable); + mNickName.setBackgroundResource(R.drawable.shape_button_disable); + mSelectedType = 0; + } else if (view == mTypeNumber) { + mTypeAll.setBackgroundResource(R.drawable.shape_button_disable); + mTypeNumber.setBackgroundResource(R.drawable.shape_button_enable); + mNickName.setBackgroundResource(R.drawable.shape_button_disable); + mSelectedType = 1; + + } else if (view == mNickName) { + mTypeAll.setBackgroundResource(R.drawable.shape_button_disable); + mTypeNumber.setBackgroundResource(R.drawable.shape_button_disable); + mNickName.setBackgroundResource(R.drawable.shape_button_enable); + mSelectedType = 2; + + } else if (view == mGenderAll) { + mGenderAll.setBackgroundResource(R.drawable.shape_button_enable); + mMaleView.setBackgroundResource(R.drawable.shape_button_disable); + mFemaleView.setBackgroundResource(R.drawable.shape_button_disable); + mSelectedGender = 0; + + } else if (view == mMaleView) { + mGenderAll.setBackgroundResource(R.drawable.shape_button_disable); + mMaleView.setBackgroundResource(R.drawable.shape_button_enable); + mFemaleView.setBackgroundResource(R.drawable.shape_button_disable); + mSelectedGender = 1; + + } else if (view == mFemaleView) { + mGenderAll.setBackgroundResource(R.drawable.shape_button_disable); + mMaleView.setBackgroundResource(R.drawable.shape_button_disable); + mFemaleView.setBackgroundResource(R.drawable.shape_button_enable); + mSelectedGender = 2; + + } else if (view == mCancelView) { + finish(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/SkillActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/SkillActivity.java new file mode 100644 index 0000000..2c643c2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/SkillActivity.java @@ -0,0 +1,374 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.adapter.MainChannelAdapter; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.utils.BaseUtils; +import com.fengliyan.tianlesue.utils.GlideImageLoader; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.uikit.adboard.AdPagesManager; +import com.youth.banner.Banner; +import com.youth.banner.listener.OnBannerListener; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/14. + */ + +public class SkillActivity extends BaseActivity implements View.OnClickListener { + + private int mSkillId; + private ImageView mIvMoreCity; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_skill); + Intent intent = getIntent(); + String skillName = intent.getStringExtra("skillName"); + mSkillId = intent.getIntExtra("skillId", 0); + setTitleName(skillName); + + mImage_bg = new int[]{getColor("#e5c9c9"), getColor("#c9d8e5"), getColor("#c9d3c1"), getColor("#cbcbc8"), getColor("#d3cbe4"), getColor("#cdd1d6")}; + initView(); + changeChannel(1); + } + + private RecyclerView mRvMainChannel; + private MainChannelAdapter mAdapter; + + private List mChannelAnchors = new ArrayList<>(); + private int[] mImage_bg; + private SwipeRefreshLayout mChannelRefresh; + + + private int getColor(String color) { + return Color.parseColor(color); + } + + private View mSelector; + private View mChannelView1; + private View mChannelView2; + private View mChannelView3; + private TextView mChannelTextView1; + private TextView mChannelTextView2; + private TextView mChannelTextView3; + private View mChannelBottomLine1; + private View mChannelBottomLine2; + private View mChannelBottomLine3; + + private View mPageView; + private ViewPager mViewPager; + private ViewGroup mGroup; + private AdPagesManager mManager; + private List mBanners = new ArrayList<>(); + private Banner mImageBanner; + + private void initView() { + mRvMainChannel = findViewById(R.id.rv_main_channel); + mRvMainChannel.setLayoutManager(new WrapStaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + + RecyclerView.LayoutManager mLayoutManager = mRvMainChannel.getLayoutManager(); + int[] into = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()]; + int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(into); + + int lastVisibleItemPosition = lastVisibleItemPositions[1]; + + if (mChannelAnchors.size() != 0 && mChannelAnchors.size() % 10 == 0 && newPage < mPage && !isNodata && lastVisibleItemPosition > mChannelAnchors.size() - 2) { + getChannelData(mSelectedIndex - 1, mPage, SPUtils.getString(SkillActivity.this, mSkillId + ConsUser.SKILL_CITY_ID )); + } + return super.canScrollVertically(); + } + }); + + mAdapter = new MainChannelAdapter(this, mImage_bg); + mAdapter.setAnchorListBeans(mChannelAnchors); + mRvMainChannel.setAdapter(mAdapter); + +// mPageView = findViewById(R.id.pager_view); +// +// WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE); +// DisplayMetrics dm = new DisplayMetrics(); +// wm.getDefaultDisplay().getMetrics(dm); +// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( +// ViewGroup.LayoutParams.MATCH_PARENT, dm.widthPixels / 3); +// +// mPageView.setLayoutParams(params); +// +// mViewPager = (ViewPager) findViewById(R.id.ad_pager); +// mGroup = (ViewGroup) findViewById(R.id.view_group); +// mManager = new AdPagesManager(mViewPager, mGroup, this); +// mManager.setOnImageClickListener(new AdPagesManager.ImageClickListener() { +// @Override +// public void onClick(View v, int position) { +// if (null != mBanners) { +// int size = mBanners.size(); +// if (size != 0) { +// int i = position % size; +// JumpUtils.jump(mBanners.get(i).getLink_type(), +// mBanners.get(i).getLink_url(), SkillActivity.this); +// } +// } +// +// } +// }); + + mSelector = findViewById(R.id.channel_selector_2); + mChannelView1 = findViewById(R.id.channel_selector_view_1); + mChannelView2 = findViewById(R.id.channel_selector_view_2); + mChannelView3 = findViewById(R.id.channel_selector_view_3); + mChannelTextView1 = findViewById(R.id.channel_selector_name_1); + mChannelTextView2 = findViewById(R.id.channel_selector_name_2); + mChannelTextView3 = findViewById(R.id.channel_selector_name_3); + mChannelBottomLine1 = findViewById(R.id.channel_selector_bottom_line_1); + mChannelBottomLine2 = findViewById(R.id.channel_selector_bottom_line_2); + mChannelBottomLine3 = findViewById(R.id.channel_selector_bottom_line_3); + mIvMoreCity = findViewById(R.id.iv_more_city); + mChannelRefresh = findViewById(R.id.channel_refresh); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + changeChannel(mSelectedIndex); + } + }); + + AppBarLayout appBarLayout = findViewById(R.id.channel_app_bar); + appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if (verticalOffset == 0) { + mChannelRefresh.setEnabled(true); + + } else { + mChannelRefresh.setEnabled(false); + } + } + }); + + mChannelView1.setOnClickListener(this); + mChannelView2.setOnClickListener(this); + mChannelView3.setOnClickListener(this); + + mBanners.clear(); + mImageBanner = findViewById(R.id.image_banner); + + } + + public void setChannelRefresh() { + mChannelRefresh.post(new Runnable() { + + @Override + public void run() { + mChannelRefresh.setRefreshing(true); + } + }); + } + + + List images = new ArrayList<>(); + private void addBanner() { +// Iterator bannerBeanIterator = mBanners.iterator(); +// mManager.clear(); +// while (bannerBeanIterator.hasNext()) { +// BannerBean bannerBean = bannerBeanIterator.next(); +// mManager.addImageViewByUrl(ConstUrl.IMAGE_URL + bannerBean.getImage()); +// } +// +// mManager.manage(); + images.clear(); + if (null != mBanners) { + if (mBanners.size() != 0) { + for (int i = 0; i < mBanners.size(); i++) { + images.add(ConstUrl.IMAGE_URL + mBanners.get(i).getImage()); + } + } + } + //简单使用 + BaseUtils.setBannerLayoutParams(mImageBanner).setImages(images) + .setImageLoader(new GlideImageLoader()) + .setOnBannerListener(new OnBannerListener() { + @Override + public void OnBannerClick(int position) { + if (null != mBanners) { + int size = mBanners.size(); + if (size != 0) { + int i = position % size; + JumpUtils.jump(mBanners.get(i).getLink_type(), + mBanners.get(i).getLink_url(), SkillActivity.this); + } + } + } + }) + .setDelayTime(3000) + .start(); + } + + private int mPage = 1; + private int newPage = 1; + private int mSelectedIndex = 1; + private boolean isNodata; + + private void getChannelData(final int index, int page, String cityId) { + newPage = page; + MainManager.getChannelAnchors(this, mSkillId + "", + index + "", mPage, cityId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() == 0) { + isNodata = true; + } else { + isNodata = false; + } + if (mPage == 1) { + mChannelAnchors.clear(); + } + + mChannelAnchors.addAll(result.getList().getList()); + if (null != mChannelAnchors) { + mAdapter.notifyDataSetChanged(); + } + } + } + } + + if (mPage == 1) { + if (null != mBanners && mBanners.size() == 0) { + mBanners = result.getBanner(); + addBanner(); + } + } + mPage++; + + mChannelRefresh.setRefreshing(false); + } + + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + public void changeChannel(int index) { + if (null != mChannelTextView3) { + String city = SPUtils.getString(this, mSkillId + ConsUser.SKILL_CITY); + if (!TextUtils.isEmpty(city)) { + mChannelTextView3.setText(city); + } + } + mSelectedIndex = index; + mPage = 1; + switch (index) { + case 1: + mChannelTextView1.setTextColor(getResources().getColor(R.color.black)); + mChannelTextView2.setTextColor(getResources().getColor(R.color.nofocus)); + mChannelTextView3.setTextColor(getResources().getColor(R.color.nofocus)); + mChannelBottomLine1.setVisibility(View.VISIBLE); + mChannelBottomLine2.setVisibility(View.GONE); + mChannelBottomLine3.setVisibility(View.GONE); + getChannelData(0, mPage, SPUtils.getString(SkillActivity.this, mSkillId + ConsUser.SKILL_CITY_ID )); + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + isReClick = false; + break; + case 2: + mChannelTextView1.setTextColor(getResources().getColor(R.color.nofocus)); + mChannelTextView2.setTextColor(getResources().getColor(R.color.black)); + mChannelTextView3.setTextColor(getResources().getColor(R.color.nofocus)); + mChannelBottomLine1.setVisibility(View.GONE); + mChannelBottomLine2.setVisibility(View.VISIBLE); + mChannelBottomLine3.setVisibility(View.GONE); + getChannelData(1, mPage, SPUtils.getString(SkillActivity.this, mSkillId + ConsUser.SKILL_CITY_ID )); + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo1); + isReClick = false; + break; + case 3: + mChannelTextView1.setTextColor(getResources().getColor(R.color.nofocus)); + mChannelTextView2.setTextColor(getResources().getColor(R.color.nofocus)); + mChannelTextView3.setTextColor(getResources().getColor(R.color.black)); + mChannelBottomLine1.setVisibility(View.GONE); + mChannelBottomLine2.setVisibility(View.GONE); + mChannelBottomLine3.setVisibility(View.VISIBLE); + getChannelData(2, mPage, SPUtils.getString(SkillActivity.this, mSkillId + ConsUser.SKILL_CITY_ID )); + mIvMoreCity.setImageResource(R.drawable.ic_bou_mo2); + isReClick = true; + break; + } + } + + private boolean isReClick = false; + + @Override + public void onClick(View view) { + if (view == mChannelView1) { + changeChannel(1); + } else if (view == mChannelView2) { + changeChannel(2); + } else if (view == mChannelView3) { + if (isReClick) { + Intent intent = new Intent(this, CityPickerActivity.class); + startActivityForResult(intent, 1003); + }else { + changeChannel(3); + } + + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 1003 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(SkillActivity.this, mSkillId + ConsUser.SKILL_CITY, city); + mChannelTextView3.setText(city); + + if (!TextUtils.isEmpty(city)) { + String cityId = GlobalManager.getCityMap().get(city); + SPUtils.saveString(SkillActivity.this, mSkillId + ConsUser.SKILL_CITY_ID , cityId); + mPage = 1; + getChannelData(2, mPage, cityId); + } + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/SwipeCardFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/SwipeCardFragment.java new file mode 100644 index 0000000..6700c31 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/SwipeCardFragment.java @@ -0,0 +1,152 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.CardAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.tianlesue.model.main.ChannelAnchorBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.flingswipe.SwipeFlingAdapterView; + +import java.util.ArrayList; + + +public class SwipeCardFragment extends Fragment implements View.OnClickListener { + private ArrayList al = new ArrayList<>();// + private CardAdapter adapter; + private SwipeFlingAdapterView flingContainer; + private ImageView left, right, info; + private int mPage = 1; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.demo_layout1, container, false); + initTitle(); + initView(v); + return v; + } + + public void initTitle() { + ((BaseActivity) getActivity()).hideTitleBar(); + } + + public void initView(View view) { + left = view.findViewById(R.id.left); + right = view.findViewById(R.id.right); + info = view.findViewById(R.id.info); + flingContainer = view.findViewById(R.id.frame); + left.setOnClickListener(this); + right.setOnClickListener(this); + info.setOnClickListener(this); + adapter = new CardAdapter(getContext(), al); + flingContainer.setAdapter(adapter); + getServerLuckList(); + flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener() { + @Override + public void removeFirstObjectInAdapter() { + al.remove(0); + adapter.notifyDataSetChanged(); + } + + @Override + public void onLeftCardExit(Object dataObject) { +// makeToast(MainActivity.this, "不喜欢"); + } + + @Override + public void onRightCardExit(Object dataObject) { +// makeToast(MainActivity.this, "喜欢"); + } + + @Override + public void onAdapterAboutToEmpty(int itemsInAdapter) { + getServerLuckList(); +// mPage++; + } + + @Override + public void onScroll(float scrollProgressPercent) { + try { + View view = flingContainer.getSelectedView(); + view.findViewById(R.id.item_swipe_right_indicator).setAlpha(scrollProgressPercent < 0 ? -scrollProgressPercent : 0); + view.findViewById(R.id.item_swipe_left_indicator).setAlpha(scrollProgressPercent > 0 ? scrollProgressPercent : 0); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + flingContainer.setOnItemClickListener(new SwipeFlingAdapterView.OnItemClickListener() { + @Override + public void onItemClicked(int itemPosition, Object dataObject) { + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.left: + if (al != null && al.size() > 0) { + flingContainer.getTopCardListener().selectLeft(); + } + break; + case R.id.right: + if (al != null && al.size() > 0) { + flingContainer.getTopCardListener().selectRight(); + } + break; + case R.id.info: + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", al.get(0).getUserid()); + startActivity(intent); + break; + } + } + + private void getServerLuckList() { + MainManager.getActiveAnchors((BaseActivity) getActivity(), mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChannelAnchorBean result, String message) { + if (null != result) { + if (null != result.getList()) { + if (null != result.getList().getList()) { + if (result.getList().getList().size() > 0) { + al.addAll(result.getList().getList()); + adapter.notifyDataSetChanged(); + } else { + mPage = 1; + } + } + } + } +// mPage++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + if (!hidden) { + initTitle(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/TransActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/TransActivity.java new file mode 100644 index 0000000..fdb124f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/TransActivity.java @@ -0,0 +1,65 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.DialogInterface; +import android.os.Bundle; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.user.bean.UserLiteBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.ToastNoticeDialog; + +/** + * Created by zhangbin on 2019/3/18. + */ + +public class TransActivity extends BaseActivity { + + private ToastNoticeDialog mToastNoticeDialog; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// setContentView(R.layout.activity_trans); + hideTitleBar(); + String userId = getIntent().getStringExtra("userId"); + getData(userId); + mToastNoticeDialog = new ToastNoticeDialog(this); + mToastNoticeDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + + @Override + public void onDismiss(DialogInterface dialog) { + finish(); + + } + }); + } + + private void getData(String userId) { + MainManager.getUserLite(this, userId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, UserLiteBean result, String message) { + if (null != result) { + mToastNoticeDialog.setData(result); + mToastNoticeDialog.setCancelable(false); + mToastNoticeDialog.show(); + }else { + finish(); + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + finish(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + finish(); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoActivity.java new file mode 100644 index 0000000..4dc3552 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoActivity.java @@ -0,0 +1,139 @@ +package com.fengliyan.tianlesue.view.main; + +import android.graphics.Rect; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.DisplayMetrics; +import android.view.KeyEvent; +import android.view.ViewTreeObserver; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.news.fragment.EmotionFragment; +import com.fengliyan.uikit.bottomedit.BottomEdit; +import com.fengliyan.uikit.emoji.utils.MoonUtil; + +public class VideoActivity extends BaseActivity { + private BottomEdit mBottomEdit; + private VideoFragment mVideoFragment; + private EmotionFragment mEmotionFragment; + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_video); + hideTitleBar(); + initView(); + + BaseApplication.getInstance().setVideo(true); + } + + private void initView(){ + + mBottomEdit = findViewById(R.id.video_bottom_edit); + mVideoFragment = new VideoFragment(); + mEmotionFragment = new EmotionFragment(); + mEmotionFragment.setListener(new EmotionFragment.EmojiSelectListener() { + @Override + public void onSelected(String key) { + submitEmoji(key); + } + }); + + mBottomEdit.setFragment(mVideoFragment); + mBottomEdit.addBottomFragment(mEmotionFragment); + mBottomEdit.getEditText().setEms(200); + mBottomEdit.dimissBottomFunction(); + mBottomEdit.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + Rect r = new Rect(); + getWindow().getDecorView().getWindowVisibleDisplayFrame(r); +// int screenHeight = getWindow().getDecorView().getRootView().getHeight(); + DisplayMetrics dm = getResources().getDisplayMetrics(); + int screenHeight = dm.heightPixels; + int heightDifference = screenHeight - r.bottom; + mBottomEdit.setBottomFragmentHeight(heightDifference); + } + }); + + mBottomEdit.setSubmitButtonClickedListener(new BottomEdit.SubmitButtonClickListener() { + @Override + public void onSubmitButtonClicked(String message) { + if(!TextUtils.isEmpty(mBottomEdit.getEditText().getText().toString())) { + mVideoFragment.submitMessage(mBottomEdit.getEditText().getText().toString()); + mBottomEdit.getEditText().setText(""); + } + } + }); + + mBottomEdit.getEditText().addTextChangedListener(new TextWatcher() { + + private int start; + private int count; + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + this.start = start; + this.count = count; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void afterTextChanged(Editable s) { + MoonUtil.replaceEmoticons(VideoActivity.this, s, start, count); + } + }); + + mBottomEdit.dismissInput(); + } + + public void showInput(){ + mBottomEdit.showInput(); + } + + public void dismissInput(){ + mBottomEdit.dismissInput(); + } + + public void submitEmoji(String key){ + Editable mEditable = mBottomEdit.getEditText().getText(); + if (key.equals("/DEL")) { + mBottomEdit.getEditText().dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + } else { + int start = mBottomEdit.getEditText().getSelectionStart(); + int end = mBottomEdit.getEditText().getSelectionEnd(); + start = (start < 0 ? 0 : start); + end = (start < 0 ? 0 : end); + mEditable.replace(start, end, key); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + + if (keyCode == KeyEvent.KEYCODE_BACK) { + if(mVideoFragment.isStarted() && !mVideoFragment.isHangup()) { + mVideoFragment.showLeaveMessage(); + }else if(mVideoFragment.isStarted() && mVideoFragment.isHangup()){ + finish(); + }else{ + mVideoFragment.refuseMessage(); + } + + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void onDestroy() { + super.onDestroy(); + BaseApplication.getInstance().setVideo(false); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoFinishActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoFinishActivity.java new file mode 100644 index 0000000..eabf8f3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoFinishActivity.java @@ -0,0 +1,242 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.VideoFeeBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +/** + * Created by zhangbin on 2018/12/15. + */ + +public class VideoFinishActivity extends BaseActivity implements View.OnClickListener { + + private LinearLayout mEvaluateView; + private TextView mTv_cost; + private TextView mTv_duration; + private TextView mTv_skill; + private ImageView[] mStartViews = new ImageView[5]; + private int mRoomId; + private boolean mIsCaller; + private SwipeRefreshLayout mRefresh; + private TextView tv_remake; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_video_finish); + setTitleName("通话结束"); + Intent intent = getIntent(); + mRoomId = intent.getIntExtra("roomId", 0); + mIsCaller = intent.getBooleanExtra("isCaller", false); + initView(); + getVideoFee(); + } + + private void initView() { + mTv_cost = findViewById(R.id.tv_cost); + mTv_duration = findViewById(R.id.tv_duration); + mTv_skill = findViewById(R.id.tv_skill); + mEvaluateView = findViewById(R.id.video_evaluate_layout); + mRefresh = findViewById(R.id.sr_refresh); + + mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + getVideoFee(); + } + }); + + mStartViews[0] = findViewById(R.id.video_evaluate_star_1); + mStartViews[1] = findViewById(R.id.video_evaluate_star_2); + mStartViews[2] = findViewById(R.id.video_evaluate_star_3); + mStartViews[3] = findViewById(R.id.video_evaluate_star_4); + mStartViews[4] = findViewById(R.id.video_evaluate_star_5); + tv_remake = findViewById(R.id.tv_remake); + + mStartViews[0].setOnClickListener(this); + mStartViews[1].setOnClickListener(this); + mStartViews[2].setOnClickListener(this); + mStartViews[3].setOnClickListener(this); + mStartViews[4].setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (mStartViews[0] == view) { + doStar(1); + } else if (mStartViews[1] == view) { + doStar(2); + } else if (mStartViews[2] == view) { + doStar(3); + } else if (mStartViews[3] == view) { + doStar(4); + } else if (mStartViews[4] == view) { + doStar(5); + } + } + + private int mStars = 5; + + private void doStar(int stars) { + mStars = stars; + switch (stars) { + case 1: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star1); + mStartViews[2].setImageResource(R.drawable.ic_video_star1); + mStartViews[3].setImageResource(R.drawable.ic_video_star1); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 2: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star1); + mStartViews[3].setImageResource(R.drawable.ic_video_star1); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 3: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star2); + mStartViews[3].setImageResource(R.drawable.ic_video_star1); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 4: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star2); + mStartViews[3].setImageResource(R.drawable.ic_video_star2); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 5: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star2); + mStartViews[3].setImageResource(R.drawable.ic_video_star2); + mStartViews[4].setImageResource(R.drawable.ic_video_star2); + break; + } + +// evaluate(); + } + + private void evaluate() { + MainManager.evaluateVideo(this, + mRoomId + "", mStars, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { +// MaleToast.showMessage(VideoFinishActivity.this, tip); + finish(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { +// MaleToast.showMessage(VideoFinishActivity.this, "未知异常"); + finish(); + } + }); + } + + private boolean isMax; + + private void getVideoFee() { + MainManager.getVideoFee(this, mRoomId + "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, VideoFeeBean result, String message) { + String pay_money = result.getPay_money(); + if (mIsCaller) { + if (!TextUtils.isEmpty(pay_money)) { + double d = Double.parseDouble(pay_money); + int money = (int) d; + mTv_cost.setText("本次花费" + money + "金币"); + + } + } else { + int income_money = (int) result.getIncome_money(); + mTv_cost.setText("本次收入" + income_money + "金币"); + } + tv_remake.setText(result.getRemark()); + mTv_duration.setText(secondToTime(result.getCall_time())); +// mTv_skill.setText(result.getSkill().getName()); + if (result.getCall_time() > 3 * 60) { + isMax = true; + mEvaluateView.setVisibility(View.VISIBLE); + } else { + isMax = false; + mEvaluateView.setVisibility(View.GONE); + } + + mRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(VideoFinishActivity.this, tip); + mRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(VideoFinishActivity.this, "请重试"); + mRefresh.setRefreshing(false); + } + }); + } + + private String secondToTime(long second) { + long days = second / 86400; + second = second % 86400; + long hours = second / 3600; + second = second % 3600; + long minutes = second / 60; + second = second % 60; + if (days > 0) { + return days + "天" + hours + "小时" + minutes + "分" + second + "秒"; + } else { + return hours + "小时" + minutes + "分" + second + "秒"; + } + } + + @Override + public void finishActivity() { +// super.finishActivity(); + if (isMax) { + evaluate(); + } else { + finish(); + } + + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (isMax) { + evaluate(); + } else { + finish(); + } +// return true; + } + return super.onKeyDown(keyCode, event); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoFragment.java new file mode 100644 index 0000000..6087369 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/VideoFragment.java @@ -0,0 +1,1059 @@ +package com.fengliyan.tianlesue.view.main; + +import android.Manifest; +import android.content.DialogInterface; +import android.content.Intent; +import android.media.MediaPlayer; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.appcompat.widget.AppCompatEditText; +import androidx.fragment.app.Fragment; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.fengliyan.base.base.permission.AbsPermissionResultCallBack; +import com.fengliyan.base.base.permission.PermissionHelper; +import com.fengliyan.http.httprequest.OkHttp.CaiWebSocket; +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.adapter.VideoAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.video.manager.VideoManager; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.VideoFeeBean; +import com.fengliyan.tianlesue.model.main.VideoRequestBean; +import com.fengliyan.tianlesue.model.main.VideoRequestDataBean; +import com.fengliyan.tianlesue.model.main.websocket.GiftBean; +import com.fengliyan.tianlesue.model.main.websocket.HangUpBean; +import com.fengliyan.tianlesue.model.main.websocket.NoticeBean; +import com.fengliyan.tianlesue.model.main.websocket.RoomIdBean; +import com.fengliyan.tianlesue.model.main.websocket.TextBean; +import com.fengliyan.tianlesue.model.main.websocket.TipBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketChatBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketRequestBean; +import com.fengliyan.tianlesue.model.main.websocket.WebSocketResultBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.settings.CaibeiRechargeActivity; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.dialog.BottomGiftDialog; +import com.fengliyan.uikit.dialog.DialogGiftBean; +import com.fengliyan.uikit.dialog.GiftListBean; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import io.agora.rtc.IRtcEngineEventHandler; + +public class VideoFragment extends Fragment implements View.OnClickListener{ + private SimpleDraweeView mStartPhoto; + private TextView mStartName; + private TextView mStartCost; + private TextView mStartHint; + private Button mCalleeAnswerButton; + private Button mCalleeCancelButton; + private Button mCallerCancelButton; + private TextView mStartCountDownTimeText; + private SimpleDraweeView mEndPhoto; + private SimpleDraweeView mBackground; + private TextView mEndName; + private TextView mEndDuration; + private TextView mEndCost; + private Button mEndFinishButton; + private SimpleDraweeView mVideoPhoto; + private TextView mVideoCost; + private TextView mVideoDuration; + private View mVideoEnd; + private FrameLayout mLocalVideoView; + private FrameLayout mRemoteVidoView; + private ImageView mVideoSwitcher; + private ImageView mVideoMuteSwitcher; + private ImageView mVideoCameraSwitcher; + private View mVideoGift; + private View mVideoChat; + private LoadMoreListView mVideoChatList; + private View mStartView; + private View mEndView; + private BaseMessageDialog mMessageDialog; + private int mToUid; + private int mSkillId; + private String mRoomId; + private long mBaseTime; + private long mDuration; + private boolean isMute; + private boolean enableVideo = true; + private boolean isCaller; //false为被叫 true为主叫 + private boolean isLeave; + private BottomGiftDialog mGiftDialog; + private List mChatBeanList = new ArrayList<>(); + private VideoAdapter mVideoChatAdapter; + private SurfaceView mLocalSurfaceView; + private SurfaceView mRemoteSuraceView; + private MediaPlayer mMediaPlayer; +// private BaseMessageDialog mConfirmDialog; + private View mEvaluateView; + private ImageView[] mStartViews = new ImageView[5]; + private boolean isLocalMain; + private boolean isStarted; + private boolean isHangup; + private boolean isCameraSwitch; + private int mUid; + private int mStars = 0; + + public boolean isStarted() { + return isStarted; + } + + public boolean isHangup() { + return isHangup; + } + + private Handler mVideoStatusHandler = new Handler(){ + public void handleMessage(Message message){ + if(message.what == 0){ + Bundle bundle = message.getData(); + mUid = bundle.getInt("uid"); + mRemoteSuraceView = + VideoManager.getInstance().setupRemoteVideo(mUid); + mRemoteVidoView.addView(mRemoteSuraceView); + + }else if(message.what == 1){ + + }else if(message.what == 2){ + if(null == mRemoteSuraceView || null == mLocalSurfaceView){ + return; + } + + if(isLocalMain){ + changeLocalView(); + } + + Bundle bundle = message.getData(); + boolean muted = bundle.getBoolean("muted"); + if(muted){ + mRemoteVidoView.removeAllViews(); + mLocalVideoView.removeAllViews(); + mLocalVideoView.setVisibility(View.GONE); + mLocalVideoView.addView(mRemoteSuraceView); + mRemoteVidoView.addView(mLocalSurfaceView); + }else{ + mRemoteVidoView.removeAllViews(); + mLocalVideoView.removeAllViews(); + mLocalVideoView.setVisibility(View.VISIBLE); + //mRemoteVidoView.addView(mRemoteSuraceView); + mLocalVideoView.addView(mLocalSurfaceView); + mRemoteSuraceView = + VideoManager.getInstance().setupRemoteVideo(mUid); + + mRemoteVidoView.addView(mRemoteSuraceView); + } + } + } + }; + + private void changeLocalView(){ + mLocalSurfaceView.setZOrderOnTop(true); + mLocalSurfaceView.setZOrderMediaOverlay(true); + mRemoteSuraceView.setZOrderMediaOverlay(false); + mRemoteSuraceView.setZOrderOnTop(false); + mLocalVideoView.removeAllViews(); + mRemoteVidoView.removeAllViews(); + mRemoteVidoView.addView(mRemoteSuraceView); + mLocalVideoView.addView(mLocalSurfaceView); + isLocalMain = !isLocalMain; + } + + private Handler mHeartBeatHandler = new Handler(){ + public void handleMessage(Message message){ + WebSocketRequestBean bean = new WebSocketRequestBean<>(); + bean.setMethod("heartbeat"); + bean.setData(new RoomIdBean()); + bean.getData().setRoom_id(Integer.parseInt(mRoomId)); + MainManager.sendWebSocketMessage(bean); + } + }; + + private Handler mTimerHandler = new Handler(){ + public void handleMessage(Message message){ + mVideoDuration.setText((String)message.obj); + } + }; + + private Timer mCallingTimer; + private TimerTask mCallingTimerTask; + + private CountDownTimer mStartCountDownTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + mStartCountDownTimeText.setText((l / 1000) + ""); + } + + @Override + public void onFinish() { + mStartCountDownTimeText.setVisibility(View.GONE); + mMessageDialog = new BaseMessageDialog.Builder(getActivity()).setMessage("对方未接听,是否挂断?") + .setCancelable(true) + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + showRefuseMessage(); + mMessageDialog.dismiss(); + } + }).setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mMessageDialog.dismiss(); + } + }).build(); + + mMessageDialog.show(); + } + }; + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_video, container, false); + mToUid = getActivity().getIntent().getIntExtra("toUid", 0); + mSkillId = getActivity().getIntent().getIntExtra("skillId", 0); + isCaller = getActivity().getIntent().getBooleanExtra("isCaller", false); + mRoomId = getActivity().getIntent().getStringExtra("roomId"); + initView(v); + + if(isCaller){ + showCallerView(); + }else{ + showCalleeView(); + } + + PermissionHelper.request(new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, + new AbsPermissionResultCallBack() { + @Override + public void onPermissionGranted() { + if(isCaller){ + getCallInfo(); + }else{ + if(null == mRoomId){ + getActivity().finish(); + MaleToast.showMessage(getActivity(), + "视频打开错误,请重试"); + } + + getCallInfoFromRoom(Integer.parseInt(mRoomId)); + } + } + }); + + return v; + } + + private void initView(View v){ + mStartPhoto = v.findViewById(R.id.video_start_photo); + mStartName = v.findViewById(R.id.video_start_name); + mStartHint = v.findViewById(R.id.video_start_hint); + mStartCountDownTimeText = v.findViewById(R.id.video_start_count_down); + mBackground = v.findViewById(R.id.video_background); + mStartCost = v.findViewById(R.id.video_start_cost); + mCallerCancelButton = v.findViewById(R.id.video_caller_cancel); + mCalleeAnswerButton = v.findViewById(R.id.video_callee_answer); + mCalleeCancelButton = v.findViewById(R.id.video_callee_cancel); + mEndPhoto = v.findViewById(R.id.video_end_photo); + mEndName = v.findViewById(R.id.video_end_name); + mEndDuration = v.findViewById(R.id.video_end_duration); + mEndCost = v.findViewById(R.id.video_end_cost); + mEndFinishButton = v.findViewById(R.id.video_end_button); + mVideoPhoto = v.findViewById(R.id.video_remote_photo); + mVideoCost = v.findViewById(R.id.video_remote_cost); + mVideoDuration = v.findViewById(R.id.video_remote_duration); + mVideoEnd = v.findViewById(R.id.video_end); + mLocalVideoView = v.findViewById(R.id.video_recent_view); + mRemoteVidoView = v.findViewById(R.id.video_remote_view); + mVideoChatList = v.findViewById(R.id.video_social_list); + mVideoSwitcher = v.findViewById(R.id.video_open_camera); + mVideoMuteSwitcher = v.findViewById(R.id.video_mute); + mVideoCameraSwitcher = v.findViewById(R.id.video_shoot); + mVideoGift = v.findViewById(R.id.video_gift); + mVideoChat = v.findViewById(R.id.video_chat); + mStartView = v.findViewById(R.id.video_start_layout); + mEndView = v.findViewById(R.id.video_end_layout); + mEvaluateView = v.findViewById(R.id.video_evaluate_layout); + mStartViews[0] = v.findViewById(R.id.video_evaluate_star_1); + mStartViews[1] = v.findViewById(R.id.video_evaluate_star_2); + mStartViews[2] = v.findViewById(R.id.video_evaluate_star_3); + mStartViews[3] = v.findViewById(R.id.video_evaluate_star_4); + mStartViews[4] = v.findViewById(R.id.video_evaluate_star_5); + mStartViews[0].setOnClickListener(this); + mStartViews[1].setOnClickListener(this); + mStartViews[2].setOnClickListener(this); + mStartViews[3].setOnClickListener(this); + mStartViews[4].setOnClickListener(this); + + mStartView.setVisibility(View.VISIBLE); + mEndView.setVisibility(View.GONE); + mBackground.setVisibility(View.VISIBLE); + if(!isCaller){ + mVideoSwitcher.setVisibility(View.INVISIBLE); + } + + mCallerCancelButton.setOnClickListener(this); + mCalleeAnswerButton.setOnClickListener(this); + mCalleeCancelButton.setOnClickListener(this); + mEndFinishButton.setOnClickListener(this); + mVideoEnd.setOnClickListener(this); + mVideoChat.setOnClickListener(this); + mVideoGift.setOnClickListener(this); + mVideoSwitcher.setOnClickListener(this); + mVideoMuteSwitcher.setOnClickListener(this); + mVideoCameraSwitcher.setOnClickListener(this); + mRemoteVidoView.setOnClickListener(this); + mLocalVideoView.setOnClickListener(this); + mVideoChatAdapter = new VideoAdapter(getActivity()); + mVideoChatAdapter.setChatBeanList(mChatBeanList); + mVideoChatList.setAdapter(mVideoChatAdapter); + mVideoChatList.dimissEmptyView(); + mMediaPlayer = MediaPlayer.create(getActivity(), R.raw.call_bg); + mMediaPlayer.setLooping(true); + mStartCountDownTimer.start(); + mVideoChatList.removeFooterView(mVideoChatList.getLoadMoreView()); + VideoManager.getInstance().init(getActivity(), new IRtcEngineEventHandler() { + @Override + public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) { + Message message = mVideoStatusHandler.obtainMessage(); + message.what = 0; + Bundle bundle = new Bundle(); + bundle.putInt("uid", uid); + message.setData(bundle); + message.sendToTarget(); + } + + @Override + public void onUserOffline(int uid, int reason) { + + } + + @Override + public void onUserMuteVideo(final int uid, final boolean muted) { + Message message = mVideoStatusHandler.obtainMessage(); + message.what = 2; + Bundle bundle = new Bundle(); + bundle.putBoolean("muted", muted); + message.setData(bundle); + message.sendToTarget(); + } + }); + + mVideoChatList.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { + View v = getActivity().getCurrentFocus(); + if (v!=null&&(!(v instanceof EditText)||!(v instanceof AppCompatEditText))){ + ((VideoActivity)getActivity()).dismissInput(); + + } + } + + return false; + } + }); + + mRemoteVidoView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { + View v = getActivity().getCurrentFocus(); + if (v!=null&&(!(v instanceof EditText)||!(v instanceof AppCompatEditText))){ + ((VideoActivity)getActivity()).dismissInput(); + + } + } + + return false; + } + }); + +// if(2 == UserManager.getUserInfo().getType()){ +// mVideoCost.setVisibility(View.GONE); +// mStartCost.setVisibility(View.GONE); +// } + } + + private void startCallingTimer(){ + mBaseTime = SystemClock.elapsedRealtime(); + mCallingTimer = new Timer(); + mCallingTimerTask = new TimerTask() { + @Override + public void run() { + int time = (int)((SystemClock.elapsedRealtime() - mBaseTime) / 1000); + String hh = new DecimalFormat("00").format(time / 3600); + String mm = new DecimalFormat("00").format(time % 3600 / 60); + String ss = new DecimalFormat("00").format(time % 60); + String timeFormat = new String(hh + ":" + mm + ":" + ss); + Message msg = new Message(); + msg.obj = timeFormat; + mTimerHandler.sendMessage(msg); + mDuration = (time - mBaseTime) / 1000; + } + }; + + mCallingTimer.scheduleAtFixedRate(mCallingTimerTask,0, 1000); + } + + private void stopCallingTimer(){ + if(null != mCallingTimer) { + mCallingTimer.cancel(); + mCallingTimer = null; + } + + if(null != mCallingTimerTask){ + mCallingTimerTask.cancel(); + mCallingTimerTask = null; + } + } + + private void calling(){ + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mLocalSurfaceView = VideoManager.getInstance().setupLocalVideo(); + mLocalVideoView.addView(mLocalSurfaceView); + } + }); + } + + private void getCallInfo(){ + MainManager.getCallInfo((BaseActivity) getActivity(), mToUid, mSkillId, 0, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + handleCallInfo(result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + getActivity().finish(); + if(null != mMediaPlayer && mMediaPlayer.isPlaying()){ + mMediaPlayer.stop(); + } + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "请重试"); + getActivity().finish(); + if(null != mMediaPlayer && mMediaPlayer.isPlaying()){ + mMediaPlayer.stop(); + } + } + }); + } + + private void getCallInfoFromRoom(int roomId){ + MainManager.getCallInfoFromRoom((BaseActivity) getActivity(), roomId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, CallBean result, String message) { + mToUid = result.getFrom_uid(); + mSkillId = result.getSkill().getId(); + handleCallInfo(result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(getActivity(), tip); + getActivity().finish(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(getActivity(), "请重试"); + getActivity().finish(); + } + }); + } + + private void getVideoFee(String roomId){ + MainManager.getVideoFee((BaseActivity) getActivity(), roomId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, VideoFeeBean result, String message) { + if(isCaller) { + mEndCost.setText("咨询花费:" + result.getPay_money() + "金币"); + }else{ + mEndCost.setText("咨询收入:" + result.getIncome_money() + "金币"); + } + + mEndDuration.setText("咨询时间:" + secondToTime(result.getCall_time())); + if(isCaller && result.getCall_time() > 3 * 60){ + mEvaluateView.setVisibility(View.VISIBLE); + } + + remoteLeave(); + + if(null != mStartCountDownTimer) { + mStartCountDownTimer.cancel(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private String secondToTime(long second){ + long days = second / 86400; + second = second % 86400; + long hours = second / 3600; + second = second % 3600; + long minutes = second /60; + second = second % 60; + if(days>0){ + return days + "天" + hours + "小时" + minutes + "分" + second + "秒"; + }else{ + return hours + "小时" + minutes + "分" + second + "秒"; + } + } + + private void handleCallInfo(final CallBean result){ + String avatar = null; + String nickname = null; + if(isCaller){ + avatar = result.getTo_avatar(); + nickname = result.getTo_nickname(); + }else{ + avatar = result.getFrom_avatar(); + nickname = result.getFrom_nickname(); + } + + mStartPhoto.setImageURI(ConstUrl.IMAGE_URL + avatar); + mStartName.setText(nickname); + mStartCost.setText(result.getSkill().getPrice() + "金币/分"); + mVideoPhoto.setImageURI(ConstUrl.IMAGE_URL + avatar); + mVideoCost.setText("价格:" + result.getSkill().getPrice() + "金币/分"); + mVideoDuration.setText("时长:00:00:00"); + mEndPhoto.setImageURI(ConstUrl.IMAGE_URL + avatar); + mEndName.setText(nickname); + mEndCost.setText("通话费用:"+ result.getSkill().getPrice() + "金币/分"); + mBackground.setImageURI(ConstUrl.IMAGE_URL + avatar); + mRoomId = result.getRoom_id(); + MainManager.createWebSocket(new CaiWebSocket.WebSocketListener() { + @Override + public void onOpen() { + if(isCaller) { + VideoRequestBean requestBean = new VideoRequestBean(); + requestBean.setId(11); + requestBean.setData(new VideoRequestDataBean()); + requestBean.getData().setCallTime((System.currentTimeMillis() / 1000) + ""); + requestBean.getData().setRoomid(result.getRoom_id()); + Gson gson = new Gson(); + String content = gson.toJson(requestBean); + ChatManager.getInstance().sendVideoRequest(content, mToUid + ""); + } + + mHeartBeatHandler.post(new Runnable() { + @Override + public void run() { + if(!isLeave) { + mHeartBeatHandler.sendEmptyMessage(0); + mHeartBeatHandler.postDelayed(this, 30000); + } + } + }); + } + + @Override + public void onMessage(String text) { + final Gson gson = new Gson(); + text = text.replaceAll("@@", ""); + final WebSocketResultBean bean = gson.fromJson(text, WebSocketResultBean.class); + if("request".equals(bean.getMethod())){ + calling(); + }else if ("response".equals(bean.getMethod())) { + calling(); + }else if("updatetip".equals(bean.getMethod())){ + final String finalText = text; + WebSocketResultBean tipBean = gson.fromJson(finalText, + new TypeToken>(){}.getType()); + mStartHint.setText(tipBean.getData().getTip()); + }else if("startvideo".equals(bean.getMethod())){ + isStarted = true; + VideoManager.getInstance().joinChannel(result.getRoom_id(), + SPUtils.getInt(getActivity(), ConsUser.USER_ID)); + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + VideoManager.getInstance().enableAudio(); + VideoManager.getInstance().speak(); + mStartView.setVisibility(View.GONE); + mEndView.setVisibility(View.GONE); + mBackground.setVisibility(View.GONE); + if(mMediaPlayer.isPlaying()) { + mMediaPlayer.stop(); + } + } + }); + + startCallingTimer(); + if(null != mStartCountDownTimer) { + mStartCountDownTimer.cancel(); + } + }else if("hangup".equals(bean.getMethod())){ + isHangup = true; + final String finalText = text; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + WebSocketResultBean hangUpBean = gson.fromJson(finalText, + new TypeToken>(){}.getType()); + int type = hangUpBean.getData().getType(); + switch (type){ + case 1: + MaleToast.showMessage(getActivity(), "你取消了本次通话"); + getActivity().finish(); + break; + case 2: + MaleToast.showMessage(getActivity(), "对方拒绝了本次通话"); + getActivity().finish(); + break; + case 3: + MaleToast.showMessage(getActivity(), "呼叫超时"); + getActivity().finish(); + break; + case 4: + MaleToast.showMessage(getActivity(), "已离线"); + getVideoFee(mRoomId); + break; + case 5: + MaleToast.showMessage(getActivity(), "已离线"); + getVideoFee(mRoomId); + break; + case 6: + MaleToast.showMessage(getActivity(), "费用不足"); + getVideoFee(mRoomId); + break; + case 7: + MaleToast.showMessage(getActivity(), "通话结束"); + getActivity().finish(); + break; + default: + remoteLeave(); + getActivity().finish(); + + } + } + }); + + }else if("notice".equals(bean.getMethod())){ + WebSocketResultBean noticeBean = gson.fromJson(text, + new TypeToken>(){}.getType()); + WebSocketChatBean chatBean = new WebSocketChatBean(); + chatBean.setData(noticeBean.getData()); + mChatBeanList.add(chatBean); + if(mChatBeanList.size() > 5){ + mChatBeanList.remove(0); + } + + mVideoChatAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onClosing() { + + } + + @Override + public void onClosed() { + + } + + @Override + public void onFailure(String reason) { + //MainManager.reconnectWebSocket(result.getSocket_url()); +// Log.d("nail","response===" + response); + } + + }, result.getSocket_url(), getActivity()); + } + + @Override + public void onClick(View view) { + if(view == mCallerCancelButton){ + //showRefuseMessage(); + refuseMessage(); + }else if(view == mEndFinishButton){ + BaseApplication.getInstance().setVideo(false); + getActivity().finish(); + ((VideoActivity)getActivity()).dismissInput(); + }else if(view == mVideoEnd){ + showLeaveMessage(); + ((VideoActivity)getActivity()).dismissInput(); + }else if(view == mVideoChat){ + ((VideoActivity)getActivity()).showInput(); + }else if(view == mVideoGift){ + getGiftData(); + ((VideoActivity)getActivity()).dismissInput(); + }else if(view == mVideoCameraSwitcher){ + ((VideoActivity)getActivity()).dismissInput(); + VideoManager.getInstance().switchCamera(); + if(isCameraSwitch){ + mVideoCameraSwitcher.setImageResource(R.drawable.ic_camera_switch_direction); + }else{ + mVideoCameraSwitcher.setImageResource(R.drawable.ic_video_photo); + } + + isCameraSwitch = !isCameraSwitch; + }else if(view == mVideoMuteSwitcher){ + ((VideoActivity)getActivity()).dismissInput(); +// VideoManager.getInstance().mute(isMute); + if(isMute){ + mVideoMuteSwitcher.setImageResource(R.drawable.ic_video_sound1); + VideoManager.getInstance().enableAudio(); + }else { + mVideoMuteSwitcher.setImageResource(R.drawable.ic_video_sound0); + VideoManager.getInstance().disableAudio(); + } + isMute = !isMute; + }else if(view == mVideoSwitcher){ + ((VideoActivity)getActivity()).dismissInput(); + VideoManager.getInstance().enableVideo(enableVideo); + if(null == mRemoteSuraceView || null == mLocalSurfaceView){ + return; + } + + if(isLocalMain){ + changeLocalView(); + } + + if(!enableVideo){ + mLocalSurfaceView.setZOrderOnTop(true); + mLocalSurfaceView.setZOrderMediaOverlay(true); + mRemoteSuraceView.setZOrderMediaOverlay(false); + mRemoteSuraceView.setZOrderOnTop(false); + mLocalVideoView.setVisibility(View.VISIBLE); + mLocalVideoView.removeAllViews(); + mRemoteVidoView.removeAllViews(); + mLocalVideoView.addView(mLocalSurfaceView); + mRemoteVidoView.addView(mRemoteSuraceView); + mVideoSwitcher.setImageResource(R.drawable.ic_video_video); + }else{ + mLocalVideoView.setVisibility(View.GONE); + mLocalVideoView.removeAllViews(); + mVideoSwitcher.setImageResource(R.drawable.ic_camera_switch_off); + } + + enableVideo = !enableVideo; + }else if(view == mCalleeAnswerButton){ + sendAgreeMessage(); + }else if(view == mCalleeCancelButton){ + //showRefuseMessage(); + refuseMessage(); + }else if(view == mLocalVideoView){ + if(isLocalMain){ + mLocalSurfaceView.setZOrderOnTop(true); + mLocalSurfaceView.setZOrderMediaOverlay(true); + mRemoteSuraceView.setZOrderMediaOverlay(false); + mRemoteSuraceView.setZOrderOnTop(false); + mLocalVideoView.removeAllViews(); + mRemoteVidoView.removeAllViews(); + mRemoteVidoView.addView(mRemoteSuraceView); + mLocalVideoView.addView(mLocalSurfaceView); + //mLocalSurfaceView.setZOrderOnTop(true); + //mLocalSurfaceView.setZOrderMediaOverlay(true); + }else{ + mRemoteSuraceView.setZOrderOnTop(true); + mRemoteSuraceView.setZOrderMediaOverlay(true); + mLocalSurfaceView.setZOrderMediaOverlay(false); + mLocalSurfaceView.setZOrderOnTop(false); + mLocalVideoView.removeAllViews(); + mRemoteVidoView.removeAllViews(); + mRemoteVidoView.addView(mLocalSurfaceView); + mLocalVideoView.addView(mRemoteSuraceView); + } + + isLocalMain = !isLocalMain; + }else if(mStartViews[0] == view){ + doStar(1); + }else if(mStartViews[1] == view){ + doStar(2); + }else if(mStartViews[2] == view){ + doStar(3); + }else if(mStartViews[3] == view){ + doStar(4); + }else if(mStartViews[4] == view){ + doStar(5); + } + } + + private void doStar(int stars){ + mStars = stars; + switch (stars){ + case 1: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star1); + mStartViews[2].setImageResource(R.drawable.ic_video_star1); + mStartViews[3].setImageResource(R.drawable.ic_video_star1); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 2: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star1); + mStartViews[3].setImageResource(R.drawable.ic_video_star1); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 3: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star2); + mStartViews[3].setImageResource(R.drawable.ic_video_star1); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 4: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star2); + mStartViews[3].setImageResource(R.drawable.ic_video_star2); + mStartViews[4].setImageResource(R.drawable.ic_video_star1); + break; + case 5: + mStartViews[0].setImageResource(R.drawable.ic_video_star2); + mStartViews[1].setImageResource(R.drawable.ic_video_star2); + mStartViews[2].setImageResource(R.drawable.ic_video_star2); + mStartViews[3].setImageResource(R.drawable.ic_video_star2); + mStartViews[4].setImageResource(R.drawable.ic_video_star2); + break; + } + + evaluate(); + } + + private void evaluate(){ + MainManager.evaluateVideo((BaseActivity) getActivity(), + mRoomId, mStars, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onDestroy(){ + super.onDestroy(); + if(null != mMessageDialog && mMessageDialog.isShowing()){ + mMessageDialog.dismiss(); + } + + if(null != mStartCountDownTimer){ + mStartCountDownTimer.cancel(); + mStartCountDownTimer = null; + } + + if(null != mMediaPlayer && mMediaPlayer.isPlaying()) { + mMediaPlayer.stop(); + mMediaPlayer = null; + } + } + + public void showLeaveMessage(){ + mMessageDialog = new BaseMessageDialog.Builder(getActivity()).setMessage("是否挂断?") + .setCancelable(true) + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sendLeaveMessage(); + mMessageDialog.dismiss(); + } + }).setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mMessageDialog.dismiss(); + } + }).build(); + + mMessageDialog.show(); + } + + public void showRefuseMessage(){ + mMessageDialog = new BaseMessageDialog.Builder(getActivity()).setMessage("拒绝通话?") + .setCancelable(true) + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + refuseMessage(); + mMessageDialog.dismiss(); + } + }).setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mMessageDialog.dismiss(); + } + }).build(); + + mMessageDialog.show(); + } + + public void showCallerView(){ + mCalleeCancelButton.setVisibility(View.GONE); + mCalleeAnswerButton.setVisibility(View.GONE); + mCallerCancelButton.setVisibility(View.VISIBLE); + mMediaPlayer.start(); + } + + public void showCalleeView(){ + mCalleeCancelButton.setVisibility(View.VISIBLE); + mCalleeAnswerButton.setVisibility(View.VISIBLE); + mCallerCancelButton.setVisibility(View.GONE); + mMediaPlayer.start(); + } + + + + private void remoteLeave(){ + ((VideoActivity)getActivity()).dismissInput(); + mRemoteVidoView.removeAllViews(); + mStartView.setVisibility(View.GONE); + mEndView.setVisibility(View.VISIBLE); + mBackground.setVisibility(View.VISIBLE); + stopCallingTimer(); + VideoManager.getInstance().leaveChannel(); + MainManager.closeWebSocket(); + isLeave = true; + if(mMediaPlayer.isPlaying()) { + mMediaPlayer.stop(); + } + //mEndDuration.setText("通话时长:" + mVideoDuration.getText()); + } + + public void refuseMessage(){ + if (!TextUtils.isEmpty(mRoomId)) { + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(Integer.parseInt(mRoomId)); + if(isCaller){ + requestBean.setMethod("cancel"); + }else{ + requestBean.setMethod("refuse"); + } + + MainManager.sendWebSocketMessage(requestBean); + getVideoFee(mRoomId); + } + } + + private void sendLeaveMessage(){ + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(Integer.parseInt(mRoomId)); + requestBean.setMethod("hangup"); + MainManager.sendWebSocketMessage(requestBean); + } + + + private void sendAgreeMessage(){ + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + requestBean.setData(new RoomIdBean()); + requestBean.getData().setRoom_id(Integer.parseInt(mRoomId)); + requestBean.setMethod("agree"); + MainManager.sendWebSocketMessage(requestBean); + } + + public void submitMessage(String message){ + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + TextBean bean = new TextBean(); + bean.setTxt(message); + requestBean.setMethod("message"); + requestBean.setData(bean); + MainManager.sendWebSocketMessage(requestBean); + } + + private void getGiftData(){ + MainManager.getGiftBeans((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + mGiftDialog = new BottomGiftDialog(getActivity(), + R.style.SelectiveDialog); + + mGiftDialog.setGiftListBean(result); + mGiftDialog.setOnGiftItemClickedListener(new BottomGiftDialog.OnGiftItemClickedListener() { + @Override + public void onGiftClicked(final DialogGiftBean bean) { + + if (null != bean) { + sendGift(bean.getId()); + } + } + + @Override + public void onWalletClicked() { + Intent intent = new Intent(getActivity(), CaibeiRechargeActivity.class); + startActivity(intent); + } + }); + + mGiftDialog.show(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void sendGift(int giftId){ + WebSocketRequestBean requestBean = new WebSocketRequestBean<>(); + GiftBean bean = new GiftBean(); + bean.setGift_count(1); + bean.setGift_id(giftId + ""); + requestBean.setMethod("gift"); + requestBean.setData(bean); + MainManager.sendWebSocketMessage(requestBean); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/WrapStaggeredGridLayoutManager.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/WrapStaggeredGridLayoutManager.java new file mode 100644 index 0000000..f2f3a41 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/WrapStaggeredGridLayoutManager.java @@ -0,0 +1,32 @@ +package com.fengliyan.tianlesue.view.main; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +/** + * Created by zhangbin on 2018/12/27. + */ + +public class WrapStaggeredGridLayoutManager extends StaggeredGridLayoutManager { + + + public WrapStaggeredGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public WrapStaggeredGridLayoutManager(int spanCount, int orientation) { + super(spanCount, orientation); + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + super.onLayoutChildren(recycler, state); + }catch (IndexOutOfBoundsException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/ConfirmWXAccountDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/ConfirmWXAccountDialog.java new file mode 100644 index 0000000..9146194 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/ConfirmWXAccountDialog.java @@ -0,0 +1,51 @@ +package com.fengliyan.tianlesue.view.main.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; + +import com.fengliyan.tianlesue.databinding.DialogConfirmwxaccountBinding; +import com.fengliyan.tianlesue.model.main.ContactBean; + +public class ConfirmWXAccountDialog extends Dialog { + private ContactBean.WechatBean bean; + + public ConfirmWXAccountDialog(@NonNull Context context, ContactBean.WechatBean bean) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.bean = bean; + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + DialogConfirmwxaccountBinding binding = DialogConfirmwxaccountBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + binding.priceLabel.setText("解锁微信"); + try { + int wechatPrice = Integer.parseInt(bean.getWechat_price()); + if (bean.getGiftCoin() < wechatPrice) { + binding.priceTiplabel.setText(String.format("再送%d金币礼物即可解锁微信", (wechatPrice - bean.getGiftCoin()))); + } + } catch (NumberFormatException e) { + } + binding.okBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); +// Window window = this.getWindow(); +//// window.setGravity(Gravity.CENTER); +//// window.setBackgroundDrawableResource(android.R.color.transparent); + WindowManager windowManager = getWindow().getWindowManager(); + Display display = windowManager.getDefaultDisplay(); + WindowManager.LayoutParams lp = getWindow().getAttributes(); + lp.width = (int) (display.getWidth() * 3 / 4); //设置宽度 + getWindow().setAttributes(lp); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/CustomAlertDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/CustomAlertDialog.java new file mode 100644 index 0000000..4ab24ef --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/CustomAlertDialog.java @@ -0,0 +1,174 @@ +package com.fengliyan.tianlesue.view.main.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Typeface; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.fengliyan.tianlesue.R; + + +public class CustomAlertDialog extends Dialog implements View.OnClickListener { + private TextView tvTitle; + private TextView tvContent; + private TextView leftBtn; + private TextView rightBtn; + + private String title; + private String content; + private String leftBtnText; + private String rightBtnText; + + private Context mContext; + private boolean isTitleBold = false; + private boolean hideTitle = false; + private boolean hideContent = false; + + private float add =0; + private float mult =0; + + private OnDialogLeftClickListener leftOnClickListener; + private OnDialogRightClickListener rightOnClickListener; + + public CustomAlertDialog(@NonNull Context context) { + super(context); + mContext = context; + } + + public CustomAlertDialog(Context context, boolean isBold) { + super(context); + mContext = context; + isTitleBold = isBold; + } + + public CustomAlertDialog(@NonNull Context context, int themeResId) { + super(context, themeResId); + mContext = context; + } + + protected CustomAlertDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.layout_custom_aletdialog); + initView(); + + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams lp = window.getAttributes(); + DisplayMetrics dm = new DisplayMetrics(); + dm = mContext.getResources().getDisplayMetrics(); + lp.width = (int) ((dm.widthPixels) * 0.8); + lp.height = LinearLayout.LayoutParams.WRAP_CONTENT; + window.setAttributes(lp); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + + private void initView() { + tvTitle = findViewById(R.id.tv_dialog_title); + tvContent = findViewById(R.id.tv_dialog_content); + leftBtn = findViewById(R.id.left_btn); + rightBtn = findViewById(R.id.right_btn); + if (title != null) { + tvTitle.setText(title); + if (isTitleBold){ + tvTitle.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); + } + } + if (hideTitle) { + tvTitle.setVisibility(View.GONE); + } + if (content != null) { + tvContent.setText(content); + if (add!=0&&mult!=0) { + tvContent.setLineSpacing(add,mult); + } + } + if (hideContent) { + tvContent.setVisibility(View.GONE); + } + if (leftBtnText != null) { + leftBtn.setText(leftBtnText); + } + if (rightBtnText!= null) { + rightBtn.setText(rightBtnText); + } + leftBtn.setOnClickListener(this); + rightBtn.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.left_btn: + if (leftOnClickListener != null) leftOnClickListener.leftClick(); + dismiss(); + break; + case R.id.right_btn: + if (rightOnClickListener != null) rightOnClickListener.rightClick(); + dismiss(); + break; + } + } + public void setTitle(String title) { + this.title = title; + } + + public void hideTitle(boolean hideTitle) { + this.hideTitle = hideTitle; + } + + public void setContent(String content) { + this.content = content; + } + + public void hideContent(boolean hideContent) { + this.hideContent = hideContent; + } + + public void setContentLineSpacing(float add, float mult) { + this.add = add; + this.mult = mult; + } + + public void setLeftBtnText(String leftBtnText) { + this.leftBtnText = leftBtnText; + } + + public void setRightBtnText(String rightBtnText) { + this.rightBtnText = rightBtnText; + } + + public void setOnDialogClickListener(OnDialogLeftClickListener leftOnClickListener,OnDialogRightClickListener rightOnClickListener) { + this.leftOnClickListener = leftOnClickListener; + this.rightOnClickListener = rightOnClickListener; + } + + public void setRightOnClickListener(OnDialogRightClickListener rightOnClickListener) { + this.rightOnClickListener = rightOnClickListener; + } + + public interface OnDialogLeftClickListener { + void leftClick(); + } + + public interface OnDialogRightClickListener { + void rightClick(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/FreeVideoDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/FreeVideoDialog.java new file mode 100644 index 0000000..41c8fe9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/FreeVideoDialog.java @@ -0,0 +1,126 @@ +package com.fengliyan.tianlesue.view.main.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; + +import androidx.annotation.NonNull; + +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.main.adapter.FreeVideoAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.FreeVideoBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.AgoraWithFUVideoActivity; + +import java.util.ArrayList; +import java.util.List; + +/** + * ying 2020/12/16 + * Describe :免费视频的弹窗 + */ + +public class FreeVideoDialog extends Dialog implements View.OnClickListener, FreeVideoAdapter.OnVideoClickListener { + private static final String TAG = "FreeVideoDialog"; + private final List mList; + private final Activity mActivity; + private int mIndex; + private FreeVideoAdapter mFreeVideoAdapter; + + + public FreeVideoDialog(@NonNull Activity activity, List list) { + super(activity, com.fengliyan.uikit.R.style.SelectiveDialog); + mActivity = activity; + mList = list; + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + setContentView(R.layout.dialog_free_video); + TextView title = findViewById(R.id.freeVideo_title); + SpannableStringBuilder style = new SpannableStringBuilder("限时免费视频一分钟"); + style.setSpan(new ForegroundColorSpan(Color.parseColor("#E14740")), 2, 4, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + title.setText(style); + mFreeVideoAdapter = new FreeVideoAdapter(findViewById(R.id.freeVideo_list)); + mFreeVideoAdapter.setOnClickListener(this); + notifyAdapter(); + findViewById(R.id.freeVideo_change).setOnClickListener(this); + + } + + private void notifyAdapter() { + ArrayList anchorListBeans = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + anchorListBeans.add(mList.get(mIndex)); + ++mIndex; + if (mIndex >= mList.size()) { + mIndex = 0; + } + } + mFreeVideoAdapter.setList(anchorListBeans); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.freeVideo_change: + notifyAdapter(); + break; + } + } + + @Override + public void onVideo(int id) { + MainManager.getCallInfo((BaseActivity) mActivity, id, 0, 0, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(mActivity, AgoraWithFUVideoActivity.class); + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + intent.putExtra("isCaller", true); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + mActivity.startActivity(intent); + dismiss(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/PermissionDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/PermissionDialog.java new file mode 100644 index 0000000..181b9f0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/PermissionDialog.java @@ -0,0 +1,91 @@ +package com.fengliyan.tianlesue.view.main.dialog; + +import android.Manifest; +import android.app.Dialog; +import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.Window; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + +import com.fengliyan.tianlesue.R; + +import java.util.HashMap; + +public class PermissionDialog extends Dialog { + private static final String TAG = "PermissionDialog"; + private Context mContext; + private String[] permissions; + + private TextView tv_permission; + + public PermissionDialog(@NonNull Context context, String[] permission) { + super(context); + mContext = context; + this.permissions = permission; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_permission); + Window window = this.getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + window.setGravity(Gravity.TOP); + } +// setCanceledOnTouchOutside(false); + initView(); + } + + private void initView() { + tv_permission = findViewById(R.id.tv_permission); + HashMap map = new HashMap<>(); + for (String s : permissions) { + switch (s) { + case Manifest.permission.ACCESS_COARSE_LOCATION: + case Manifest.permission.ACCESS_FINE_LOCATION: + map.put(1, "定位权限用于完善资料、编辑资料、推荐同城等场景;"); + break; + case Manifest.permission.CAMERA: + map.put(2, "相机权限用于拍照、录制、视频通话、认证等场景;"); + break; + case Manifest.permission.WRITE_EXTERNAL_STORAGE: + case Manifest.permission.READ_EXTERNAL_STORAGE: + map.put(3, "读写手机存储权限用于访问相册及储存图片、文件等场景;"); + break; + case Manifest.permission.RECORD_AUDIO: + map.put(4, "访问麦克风用于发送语音、语音通话等场景;"); + break; + } + } + + StringBuilder str = new StringBuilder(); + for (int key : map.keySet()) { + String value = map.get(key); + System.out.println("key=" + key + ", vlaue=" + value); + str.append(value); + } + tv_permission.setText(str); + } + + @Override + public void show() { + boolean isCheck = true; + for (String permission : permissions) { + if (ContextCompat.checkSelfPermission(mContext, permission) != PackageManager.PERMISSION_GRANTED) { + isCheck = false; + } + } + if (!isCheck) { + super.show(); + } + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/RedEnvelopesDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/RedEnvelopesDialog.java new file mode 100644 index 0000000..1972f54 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/RedEnvelopesDialog.java @@ -0,0 +1,106 @@ +package com.fengliyan.tianlesue.view.main.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.animation.Animation; +import android.view.animation.ScaleAnimation; +import android.widget.ImageView; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.main.RedEnvlopesRedwarsBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBackBase; +import com.fengliyan.tianlesue.view.main.RedEnvelopesActivity; + +/** + * ying 2021/1/25 + * Describe :红包弹窗 + */ + +public class RedEnvelopesDialog extends Dialog implements View.OnClickListener { + private Context mContext; + public ImageView mImage; + public ImageView mDialogclear; + public String mRedId; + private Animation mAnimation; + + public RedEnvelopesDialog(@NonNull Context context) { + super(context); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_redenvelopes); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + initView(); + } + + private void initView() { + mImage = findViewById(R.id.dialog_red_imageView); + mDialogclear = findViewById(R.id.dialog_red_clear); + mImage.setOnClickListener(this); + mDialogclear.setOnClickListener(this); + + mAnimation = new ScaleAnimation(0.8f, 1.0f, 0.8f, 1.0f, Animation.RELATIVE_TO_SELF, + 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + mAnimation.setDuration(300); + mAnimation.setRepeatCount(-1); + mAnimation.setRepeatMode(Animation.REVERSE); + mAnimation.setFillAfter(true); + mImage.startAnimation(mAnimation); + } + + + public void show(String redId) { + mRedId = redId; + if (!isShowing()) { + show(); + } + if (mAnimation != null) { + mImage.startAnimation(mAnimation); + } + } + + @Override + public void onClick(View v) { + if (v == mDialogclear) dismiss(); + else if (v == mImage) { + redwars(); + } + } + + public void redwars() { + MainManager.redwars((BaseActivity) mContext, mRedId, new HttpUiCallBackBase() { + @Override + public void onSuccessBase(BaseActivity activity, RedEnvlopesRedwarsBean result, String message) { + if (result.status==4){ //未抢成功 还能继续抢 + MaleToast.showMessage(activity,message); + return; + } + if (result.status==3){ //失效 + MaleToast.showMessage(activity,message); + dismiss(); + return; + } + + Intent intent = new Intent(mContext, RedEnvelopesActivity.class); + intent.putExtra("rp_id", mRedId); + intent.putExtra("status", result.status); //1 抢到 2 未抢到 + mContext.startActivity(intent); + dismiss(); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/SvgaDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/SvgaDialog.java new file mode 100644 index 0000000..a56b3d2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/SvgaDialog.java @@ -0,0 +1,126 @@ +package com.fengliyan.tianlesue.view.main.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.utils.StrU; +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.net.MalformedURLException; +import java.net.URL; + +public class SvgaDialog extends Dialog implements View.OnClickListener { + private static final String TAG = "SvgaDialog"; + private Context mContext; + private SVGAImageView mSVGA; + private SVGAParser mSVGAParser; + private String mGiftUrl; + + public SvgaDialog(@NonNull Context context) { + super(context); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_svga); + Window window = this.getWindow(); + window.setGravity(Gravity.BOTTOM); + window.setBackgroundDrawableResource(android.R.color.transparent); + window.setDimAmount(0f); //去掉遮罩层 + WindowManager.LayoutParams attributes = window.getAttributes(); + attributes.width = WindowManager.LayoutParams.MATCH_PARENT; + attributes.height = WindowManager.LayoutParams.MATCH_PARENT; + window.setAttributes(attributes); + setCancelable(false); + Log.i(TAG, "onCreate: "); + initView(); + } + + private void initView() { + mSVGA = findViewById(R.id.dialog_svga); + mSVGA.setScaleType(ImageView.ScaleType.CENTER_CROP); + mSVGAParser = SVGAParser.Companion.shareParser(); + mSVGAParser.init(mContext); + mSVGA.setLoops(1); + mSVGA.setCallback(new SVGACallback() { + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + dismiss(); + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } + }); + } + + @Override + public void onClick(View v) { + + } + + public void show(String giftUrl) { + mGiftUrl = giftUrl; + if (StrU.isEmpty(giftUrl)) return; + try { + super.show(); + parse(); + } catch (Exception e) { + Log.e(TAG, "弹窗显示 错误 show: "); + } + } + + private void parse() { + if (mSVGAParser != null) { + try { + mSVGAParser.decodeFromURL(new URL(ConstUrl.IMAGE_URL + mGiftUrl), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + Log.i(TAG, "onComplete: "); + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + mSVGA.setImageDrawable(drawable); + mSVGA.startAnimation(); + } + + @Override + public void onError() { + Log.i(TAG, "onError: "); + dismiss(); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/UpdateDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/UpdateDialog.java new file mode 100644 index 0000000..279b009 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/dialog/UpdateDialog.java @@ -0,0 +1,145 @@ +package com.fengliyan.tianlesue.view.main.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.SpeedWebSocket; +import com.fengliyan.storage.StorageManager; + + +public class UpdateDialog extends Dialog implements View.OnClickListener { + private Context mContext; + private TextView tv_update_title; + private TextView mDownloadInfo; + private LinearLayout lin_update_btn; + private Button mDownloadConfirmButton; + private TextView downloader_update_cancel; + private ProgressBar mDownloadProgress; + private DownloadConfirmListener mConfirmListener; + private String mContent; + private String versionName; + private int type = 0; + + public interface DownloadConfirmListener { + void onConfirm(); + + void onCancel(); + } + + public void setConfirmListener(DownloadConfirmListener listener) { + mConfirmListener = listener; + } + + public UpdateDialog(@NonNull Context context) { + super(context); + mContext = context; + } + + public UpdateDialog(@NonNull Context context, int themeResId) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + mContext = context; + } + + protected UpdateDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_downloader); + initView(); + + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + } + + private void initView() { + tv_update_title = findViewById(R.id.tv_update_title); + mDownloadInfo = findViewById(R.id.downloader_update_info); + lin_update_btn = findViewById(R.id.lin_update_btn); + mDownloadConfirmButton = findViewById(R.id.downloader_update_confirm); + downloader_update_cancel = findViewById(R.id.downloader_update_cancel); + mDownloadProgress = findViewById(R.id.downloader_update_progress); + mDownloadConfirmButton.setOnClickListener(this); + downloader_update_cancel.setOnClickListener(this); + mDownloadInfo.setText(mContent); + String s = "更新内容 V" + versionName; + StrU.setSpanTextColorSize(s, 5, s.length(), tv_update_title, R.color.verison_name_color, 14, mContext); + setOnDismissListener(new OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + lin_update_btn.setVisibility(View.VISIBLE); + mDownloadProgress.setVisibility(View.GONE); + } + }); + } + + @Override + public void onClick(View view) { + if (mDownloadConfirmButton == view) { + if (null != mConfirmListener) { + mConfirmListener.onConfirm(); + lin_update_btn.setVisibility(View.INVISIBLE); + mDownloadProgress.setVisibility(View.VISIBLE); + mDownloadProgress.setProgress(0); + } + } else if (view == downloader_update_cancel) { + if (type == 1) { + UserManager.getInstance().notifyUserInfoChanged(new BaseUserInfo()); + StorageManager.getInstance(mContext).clear(); + SpeedWebSocket.getInstance().close(); + ((BaseActivity) mContext).finish(); + } else { + if (null != mConfirmListener) { + mConfirmListener.onCancel(); + } + } + dismiss(); + } + } + + public void setProgress(int progress) { + mDownloadProgress.setProgress(progress); + } + + public void setInfo(String info) { + mContent = info; + } + + public void setVersionName(String versionName) { + this.versionName = versionName; + } + + public void setFinishHide() { + type = 1; + } + + @Override + public void show() { + super.show(); + if (type == 1) { + downloader_update_cancel.setText("退出登录"); + } else { + downloader_update_cancel.setText("暂不升级"); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/receiver/NotificationClickReceiver.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/receiver/NotificationClickReceiver.java new file mode 100644 index 0000000..720825b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/receiver/NotificationClickReceiver.java @@ -0,0 +1,23 @@ +package com.fengliyan.tianlesue.view.main.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.text.TextUtils; + +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; + +/** + * Created by zhangbin on 2018/12/26. + */ + +public class NotificationClickReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + int linkType = intent.getIntExtra("linkType", 0); + String linkUrl = intent.getStringExtra("linkUrl"); + if (!TextUtils.isEmpty(linkUrl) && linkType != 0) { + JumpUtils.jump(linkType, linkUrl, context); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/EmptyControlVideo.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/EmptyControlVideo.java new file mode 100644 index 0000000..8f11af4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/EmptyControlVideo.java @@ -0,0 +1,47 @@ +package com.fengliyan.tianlesue.view.main.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import com.fengliyan.tianlesue.R; +import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer; + +public class EmptyControlVideo extends StandardGSYVideoPlayer { + + public EmptyControlVideo(Context context, Boolean fullFlag) { + super(context, fullFlag); + } + + public EmptyControlVideo(Context context) { + super(context); + } + + public EmptyControlVideo(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public int getLayoutId() { + return R.layout.empty_control_video; + } + + @Override + protected void touchSurfaceMoveFullLogic(float absDeltaX, float absDeltaY) { + super.touchSurfaceMoveFullLogic(absDeltaX, absDeltaY); + //不给触摸快进,如果需要,屏蔽下方代码即可 + mChangePosition = false; + + //不给触摸音量,如果需要,屏蔽下方代码即可 + mChangeVolume = false; + + //不给触摸亮度,如果需要,屏蔽下方代码即可 + mBrightness = false; + } + + @Override + protected void touchDoubleUp(MotionEvent e) { + //super.touchDoubleUp(); + //不需要双击暂停 + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/VerticalViewPager.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/VerticalViewPager.java new file mode 100644 index 0000000..3c3c162 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/VerticalViewPager.java @@ -0,0 +1,2788 @@ +package com.fengliyan.tianlesue.view.main.ui; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.util.Log; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +import androidx.core.os.ParcelableCompat; +import androidx.core.os.ParcelableCompatCreatorCallbacks; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.MotionEventCompat; +import androidx.core.view.VelocityTrackerCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.ViewConfigurationCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; +import androidx.core.view.accessibility.AccessibilityRecordCompat; +import androidx.core.widget.EdgeEffectCompat; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +/** + * Created by castorflex on 12/29/13. + * Just a copy of the original ViewPager modified to support vertical Scrolling + */ +public class VerticalViewPager extends ViewGroup { + + private static final String TAG = "ViewPager"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int DEFAULT_OFFSCREEN_PAGES = 1; + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final int DEFAULT_GUTTER_SIZE = 16; // dips + + private static final int MIN_FLING_VELOCITY = 400; // dips + + private static final int[] LAYOUT_ATTRS = new int[]{ + android.R.attr.layout_gravity + }; + + /** + * Used to track what the expected number of items in the adapter should be. + * If the app changes this when we don't expect it, we'll throw a big obnoxious exception. + */ + private int mExpectedAdapterCount; + + static class ItemInfo { + Object object; + int position; + boolean scrolling; + float heightFactor; + float offset; + } + + private static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(ItemInfo lhs, ItemInfo rhs) { + return lhs.position - rhs.position; + } + }; + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private final ArrayList mItems = new ArrayList(); + private final ItemInfo mTempItem = new ItemInfo(); + + private final Rect mTempRect = new Rect(); + + private PagerAdapter mAdapter; + private int mCurItem; // Index of currently displayed page. + private int mRestoredCurItem = -1; + private Parcelable mRestoredAdapterState = null; + private ClassLoader mRestoredClassLoader = null; + private Scroller mScroller; + private PagerObserver mObserver; + + private int mPageMargin; + private Drawable mMarginDrawable; + private int mLeftPageBounds; + private int mRightPageBounds; + + // Offsets of the first and last items, if known. + // Set during population, used to determine if we are at the beginning + // or end of the pager data set during touch scrolling. + private float mFirstOffset = -Float.MAX_VALUE; + private float mLastOffset = Float.MAX_VALUE; + + private int mChildWidthMeasureSpec; + private int mChildHeightMeasureSpec; + private boolean mInLayout; + + private boolean mScrollingCacheEnabled; + + private boolean mPopulatePending; + private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES; + + private boolean mIsBeingDragged; + private boolean mIsUnableToDrag; + private boolean mIgnoreGutter; + private int mDefaultGutterSize; + private int mGutterSize; + private int mTouchSlop; + /** + * Position of the last motion event. + */ + private float mLastMotionX; + private float mLastMotionY; + private float mInitialMotionX; + private float mInitialMotionY; + /** + * ID of the active pointer. This is used to retain consistency during + * drags/flings if multiple pointers are used. + */ + private int mActivePointerId = INVALID_POINTER; + /** + * Sentinel value for no current active pointer. + * Used by {@link #mActivePointerId}. + */ + private static final int INVALID_POINTER = -1; + + /** + * Determines speed during touch scrolling + */ + private VelocityTracker mVelocityTracker; + private int mMinimumVelocity; + private int mMaximumVelocity; + private int mFlingDistance; + private int mCloseEnough; + + // If the pager is at least this close to its final position, complete the scroll + // on touch down and let the user interact with the content inside instead of + // "catching" the flinging pager. + private static final int CLOSE_ENOUGH = 2; // dp + + private boolean mFakeDragging; + private long mFakeDragBeginTime; + + private EdgeEffectCompat mTopEdge; + private EdgeEffectCompat mBottomEdge; + + private boolean mFirstLayout = true; + private boolean mNeedCalculatePageOffsets = false; + private boolean mCalledSuper; + private int mDecorChildCount; + + private ViewPager.OnPageChangeListener mOnPageChangeListener; + private ViewPager.OnPageChangeListener mInternalPageChangeListener; + private OnAdapterChangeListener mAdapterChangeListener; + private ViewPager.PageTransformer mPageTransformer; + private Method mSetChildrenDrawingOrderEnabled; + + private static final int DRAW_ORDER_DEFAULT = 0; + private static final int DRAW_ORDER_FORWARD = 1; + private static final int DRAW_ORDER_REVERSE = 2; + private int mDrawingOrder; + private ArrayList mDrawingOrderedChildren; + private static final ViewPositionComparator sPositionComparator = new ViewPositionComparator(); + + /** + * Indicates that the pager is in an idle, settled state. The current page + * is fully in view and no animation is in progress. + */ + public static final int SCROLL_STATE_IDLE = 0; + + /** + * Indicates that the pager is currently being dragged by the user. + */ + public static final int SCROLL_STATE_DRAGGING = 1; + + /** + * Indicates that the pager is in the process of settling to a final position. + */ + public static final int SCROLL_STATE_SETTLING = 2; + + private final Runnable mEndScrollRunnable = new Runnable() { + public void run() { + setScrollState(SCROLL_STATE_IDLE); + populate(); + } + }; + + private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Used internally to monitor when adapters are switched. + */ + interface OnAdapterChangeListener { + public void onAdapterChanged(PagerAdapter oldAdapter, PagerAdapter newAdapter); + } + + /** + * Used internally to tag special types of child views that should be added as + * pager decorations by default. + */ + interface Decor { + } + + public VerticalViewPager(Context context) { + super(context); + initViewPager(); + } + + public VerticalViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + initViewPager(); + } + + void initViewPager() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + final ViewConfiguration configuration = ViewConfiguration.get(context); + final float density = context.getResources().getDisplayMetrics().density; + + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + mTopEdge = new EdgeEffectCompat(context); + mBottomEdge = new EdgeEffectCompat(context); + + mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); + mCloseEnough = (int) (CLOSE_ENOUGH * density); + mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density); + + ViewCompat.setAccessibilityDelegate(this, new MyAccessibilityDelegate()); + + if (ViewCompat.getImportantForAccessibility(this) + == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + ViewCompat.setImportantForAccessibility(this, + ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); + } + } + + @Override + protected void onDetachedFromWindow() { + removeCallbacks(mEndScrollRunnable); + super.onDetachedFromWindow(); + } + + private void setScrollState(int newState) { + if (mScrollState == newState) { + return; + } + + mScrollState = newState; + if (mPageTransformer != null) { + // PageTransformers can do complex things that benefit from hardware layers. + enableLayers(newState != SCROLL_STATE_IDLE); + } + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrollStateChanged(newState); + } + } + + /** + * Set a PagerAdapter that will supply views for this pager as needed. + * + * @param adapter Adapter to use + */ + public void setAdapter(PagerAdapter adapter) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + mAdapter.startUpdate(this); + for (int i = 0; i < mItems.size(); i++) { + final ItemInfo ii = mItems.get(i); + mAdapter.destroyItem(this, ii.position, ii.object); + } + mAdapter.finishUpdate(this); + mItems.clear(); + removeNonDecorViews(); + mCurItem = 0; + scrollTo(0, 0); + } + + final PagerAdapter oldAdapter = mAdapter; + mAdapter = adapter; + mExpectedAdapterCount = 0; + + if (mAdapter != null) { + if (mObserver == null) { + mObserver = new PagerObserver(); + } + mAdapter.registerDataSetObserver(mObserver); + mPopulatePending = false; + final boolean wasFirstLayout = mFirstLayout; + mFirstLayout = true; + mExpectedAdapterCount = mAdapter.getCount(); + if (mRestoredCurItem >= 0) { + mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); + setCurrentItemInternal(mRestoredCurItem, false, true); + mRestoredCurItem = -1; + mRestoredAdapterState = null; + mRestoredClassLoader = null; + } else if (!wasFirstLayout) { + populate(); + } else { + requestLayout(); + } + } + + if (mAdapterChangeListener != null && oldAdapter != adapter) { + mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); + } + } + + private void removeNonDecorViews() { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + removeViewAt(i); + i--; + } + } + } + + /** + * Retrieve the current adapter supplying pages. + * + * @return The currently registered PagerAdapter + */ + public PagerAdapter getAdapter() { + return mAdapter; + } + + void setOnAdapterChangeListener(OnAdapterChangeListener listener) { + mAdapterChangeListener = listener; + } + +// private int getClientWidth() { +// return getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); +// } + + private int getClientHeight() { + return getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); + } + + + /** + * Set the currently selected page. If the ViewPager has already been through its first + * layout with its current adapter there will be a smooth animated transition between + * the current item and the specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + mPopulatePending = false; + setCurrentItemInternal(item, !mFirstLayout, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + mPopulatePending = false; + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (mAdapter == null || mAdapter.getCount() <= 0) { + setScrollingCacheEnabled(false); + return; + } + if (!always && mCurItem == item && mItems.size() != 0) { + setScrollingCacheEnabled(false); + return; + } + + if (item < 0) { + item = 0; + } else if (item >= mAdapter.getCount()) { + item = mAdapter.getCount() - 1; + } + final int pageLimit = mOffscreenPageLimit; + if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) { + // We are doing a jump by more than one page. To avoid + // glitches, we want to keep all current pages in the view + // until the scroll ends. + for (int i = 0; i < mItems.size(); i++) { + mItems.get(i).scrolling = true; + } + } + final boolean dispatchSelected = mCurItem != item; + + if (mFirstLayout) { + // We don't have any idea how big we are yet and shouldn't have any pages either. + // Just set things up and let the pending layout handle things. + mCurItem = item; + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + requestLayout(); + } else { + populate(item); + scrollToItem(item, smoothScroll, velocity, dispatchSelected); + } + } + + private void scrollToItem(int item, boolean smoothScroll, int velocity, + boolean dispatchSelected) { + final ItemInfo curInfo = infoForPosition(item); + int destY = 0; + if (curInfo != null) { + final int height = getClientHeight(); + destY = (int) (height * Math.max(mFirstOffset, + Math.min(curInfo.offset, mLastOffset))); + } + if (smoothScroll) { + smoothScrollTo(0, destY, velocity); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + } else { + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + completeScroll(false); + scrollTo(0, destY); + pageScrolled(destY); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + + /** + * Set a that will be called for each attached page whenever + * the scroll position is changed. This allows the application to apply custom property + * transformations to each page, overriding the default sliding look and feel. + *

+ *

Note: Prior to Android 3.0 the property animation APIs did not exist. + * As a result, setting a PageTransformer prior to Android 3.0 (API 11) will have no effect.

+ * + * @param reverseDrawingOrder true if the supplied PageTransformer requires page views + * to be drawn from last to first instead of first to last. + * @param transformer PageTransformer that will modify each page's animation properties + */ + public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) { + if (Build.VERSION.SDK_INT >= 11) { + final boolean hasTransformer = transformer != null; + final boolean needsPopulate = hasTransformer != (mPageTransformer != null); + mPageTransformer = transformer; + setChildrenDrawingOrderEnabledCompat(hasTransformer); + if (hasTransformer) { + mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD; + } else { + mDrawingOrder = DRAW_ORDER_DEFAULT; + } + if (needsPopulate) populate(); + } + } + + void setChildrenDrawingOrderEnabledCompat(boolean enable) { + if (Build.VERSION.SDK_INT >= 7) { + if (mSetChildrenDrawingOrderEnabled == null) { + try { + mSetChildrenDrawingOrderEnabled = ViewGroup.class.getDeclaredMethod( + "setChildrenDrawingOrderEnabled", new Class[]{Boolean.TYPE}); + } catch (NoSuchMethodException e) { + Log.e(TAG, "Can't find setChildrenDrawingOrderEnabled", e); + } + } + try { + mSetChildrenDrawingOrderEnabled.invoke(this, enable); + } catch (Exception e) { + Log.e(TAG, "Error changing children drawing order", e); + } + } + } + + @Override + protected int getChildDrawingOrder(int childCount, int i) { + final int index = mDrawingOrder == DRAW_ORDER_REVERSE ? childCount - 1 - i : i; + final int result = ((LayoutParams) mDrawingOrderedChildren.get(index).getLayoutParams()).childIndex; + return result; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + ViewPager.OnPageChangeListener setInternalPageChangeListener(ViewPager.OnPageChangeListener listener) { + ViewPager.OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + /** + * Returns the number of pages that will be retained to either side of the + * current page in the view hierarchy in an idle state. Defaults to 1. + * + * @return How many pages will be kept offscreen on either side + * @see #setOffscreenPageLimit(int) + */ + public int getOffscreenPageLimit() { + return mOffscreenPageLimit; + } + + /** + * Set the number of pages that should be retained to either side of the + * current page in the view hierarchy in an idle state. Pages beyond this + * limit will be recreated from the adapter when needed. + *

+ *

This is offered as an optimization. If you know in advance the number + * of pages you will need to support or have lazy-loading mechanisms in place + * on your pages, tweaking this setting can have benefits in perceived smoothness + * of paging animations and interaction. If you have a small number of pages (3-4) + * that you can keep active all at once, less time will be spent in layout for + * newly created view subtrees as the user pages back and forth.

+ *

+ *

You should keep this limit low, especially if your pages have complex layouts. + * This setting defaults to 1.

+ * + * @param limit How many pages will be kept offscreen in an idle state. + */ + public void setOffscreenPageLimit(int limit) { + if (limit < DEFAULT_OFFSCREEN_PAGES) { + Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + + DEFAULT_OFFSCREEN_PAGES); + limit = DEFAULT_OFFSCREEN_PAGES; + } + if (limit != mOffscreenPageLimit) { + mOffscreenPageLimit = limit; + populate(); + } + } + + /** + * Set the margin between pages. + * + * @param marginPixels Distance between adjacent pages in pixels + * @see #getPageMargin() + * @see #setPageMarginDrawable(Drawable) + * @see #setPageMarginDrawable(int) + */ + public void setPageMargin(int marginPixels) { + final int oldMargin = mPageMargin; + mPageMargin = marginPixels; + + final int height = getHeight(); + recomputeScrollPosition(height, height, marginPixels, oldMargin); + + requestLayout(); + } + + /** + * Return the margin between pages. + * + * @return The size of the margin in pixels + */ + public int getPageMargin() { + return mPageMargin; + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param d Drawable to display between pages + */ + public void setPageMarginDrawable(Drawable d) { + mMarginDrawable = d; + if (d != null) refreshDrawableState(); + setWillNotDraw(d == null); + invalidate(); + } + + /** + * Set a drawable that will be used to fill the margin between pages. + * + * @param resId Resource ID of a drawable to display between pages + */ + public void setPageMarginDrawable(int resId) { + setPageMarginDrawable(getContext().getResources().getDrawable(resId)); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mMarginDrawable; + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + final Drawable d = mMarginDrawable; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(false); + populate(); + setScrollState(SCROLL_STATE_IDLE); + return; + } + + setScrollingCacheEnabled(true); + setScrollState(SCROLL_STATE_SETTLING); + + final int height = getClientHeight(); + final int halfHeight = height / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / height); + final float distance = halfHeight + halfHeight * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageHeight = height * mAdapter.getPageWidth(mCurItem); + final float pageDelta = (float) Math.abs(dx) / (pageHeight + mPageMargin); + duration = (int) ((pageDelta + 1) * 100); + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + ViewCompat.postInvalidateOnAnimation(this); + } + + ItemInfo addNewItem(int position, int index) { + ItemInfo ii = new ItemInfo(); + ii.position = position; + ii.object = mAdapter.instantiateItem(this, position); + ii.heightFactor = mAdapter.getPageWidth(position); + if (index < 0 || index >= mItems.size()) { + mItems.add(ii); + } else { + mItems.add(index, ii); + } + return ii; + } + + void dataSetChanged() { + // This method only gets called if our observer is attached, so mAdapter is non-null. + + final int adapterCount = mAdapter.getCount(); + mExpectedAdapterCount = adapterCount; + boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 && + mItems.size() < adapterCount; + int newCurrItem = mCurItem; + + boolean isUpdating = false; + for (int i = 0; i < mItems.size(); i++) { + final ItemInfo ii = mItems.get(i); + final int newPos = mAdapter.getItemPosition(ii.object); + + if (newPos == PagerAdapter.POSITION_UNCHANGED) { + continue; + } + + if (newPos == PagerAdapter.POSITION_NONE) { + mItems.remove(i); + i--; + + if (!isUpdating) { + mAdapter.startUpdate(this); + isUpdating = true; + } + + mAdapter.destroyItem(this, ii.position, ii.object); + needPopulate = true; + + if (mCurItem == ii.position) { + // Keep the current item in the valid range + newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1)); + needPopulate = true; + } + continue; + } + + if (ii.position != newPos) { + if (ii.position == mCurItem) { + // Our current item changed position. Follow it. + newCurrItem = newPos; + } + + ii.position = newPos; + needPopulate = true; + } + } + + if (isUpdating) { + mAdapter.finishUpdate(this); + } + + Collections.sort(mItems, COMPARATOR); + + if (needPopulate) { + // Reset our known page widths; populate will recompute them. + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) { + lp.heightFactor = 0.f; + } + } + + setCurrentItemInternal(newCurrItem, false, true); + requestLayout(); + } + } + + void populate() { + populate(mCurItem); + } + + void populate(int newCurrentItem) { + ItemInfo oldCurInfo = null; + int focusDirection = View.FOCUS_FORWARD; + if (mCurItem != newCurrentItem) { + focusDirection = mCurItem < newCurrentItem ? View.FOCUS_DOWN : View.FOCUS_UP; + oldCurInfo = infoForPosition(mCurItem); + mCurItem = newCurrentItem; + } + + if (mAdapter == null) { + sortChildDrawingOrder(); + return; + } + + // Bail now if we are waiting to populate. This is to hold off + // on creating views from the time the user releases their finger to + // fling to a new position until we have finished the scroll to + // that position, avoiding glitches from happening at that point. + if (mPopulatePending) { + if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); + sortChildDrawingOrder(); + return; + } + + // Also, don't populate until we are attached to a window. This is to + // avoid trying to populate before we have restored our view hierarchy + // state and conflicting with what is restored. + if (getWindowToken() == null) { + return; + } + + mAdapter.startUpdate(this); + + final int pageLimit = mOffscreenPageLimit; + final int startPos = Math.max(0, mCurItem - pageLimit); + final int N = mAdapter.getCount(); + final int endPos = Math.min(N - 1, mCurItem + pageLimit); + + if (N != mExpectedAdapterCount) { + String resName; + try { + resName = getResources().getResourceName(getId()); + } catch (Resources.NotFoundException e) { + resName = Integer.toHexString(getId()); + } + throw new IllegalStateException("The application's PagerAdapter changed the adapter's" + + " contents without calling PagerAdapter#notifyDataSetChanged!" + + " Expected adapter item count: " + mExpectedAdapterCount + ", found: " + N + + " Pager id: " + resName + + " Pager class: " + getClass() + + " Problematic adapter: " + mAdapter.getClass()); + } + + // Locate the currently focused item or add it if needed. + int curIndex = -1; + ItemInfo curItem = null; + for (curIndex = 0; curIndex < mItems.size(); curIndex++) { + final ItemInfo ii = mItems.get(curIndex); + if (ii.position >= mCurItem) { + if (ii.position == mCurItem) curItem = ii; + break; + } + } + + if (curItem == null && N > 0) { + curItem = addNewItem(mCurItem, curIndex); + } + + // Fill 3x the available width or up to the number of offscreen + // pages requested to either side, whichever is larger. + // If we have no current item we have no work to do. + if (curItem != null) { + float extraHeightTop = 0.f; + int itemIndex = curIndex - 1; + ItemInfo ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; + final int clientHeight = getClientHeight(); + final float topHeightNeeded = clientHeight <= 0 ? 0 : + 2.f - curItem.heightFactor + (float) getPaddingLeft() / (float) clientHeight; + for (int pos = mCurItem - 1; pos >= 0; pos--) { + if (extraHeightTop >= topHeightNeeded && pos < startPos) { + if (ii == null) { + break; + } + if (pos == ii.position && !ii.scrolling) { + mItems.remove(itemIndex); + mAdapter.destroyItem(this, pos, ii.object); + if (DEBUG) { + Log.i(TAG, "populate() - destroyItem() with pos: " + pos + + " view: " + ((View) ii.object)); + } + itemIndex--; + curIndex--; + ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; + } + } else if (ii != null && pos == ii.position) { + extraHeightTop += ii.heightFactor; + itemIndex--; + ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; + } else { + ii = addNewItem(pos, itemIndex + 1); + extraHeightTop += ii.heightFactor; + curIndex++; + ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; + } + } + + float extraHeightBottom = curItem.heightFactor; + itemIndex = curIndex + 1; + if (extraHeightBottom < 2.f) { + ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; + final float bottomHeightNeeded = clientHeight <= 0 ? 0 : + (float) getPaddingRight() / (float) clientHeight + 2.f; + for (int pos = mCurItem + 1; pos < N; pos++) { + if (extraHeightBottom >= bottomHeightNeeded && pos > endPos) { + if (ii == null) { + break; + } + if (pos == ii.position && !ii.scrolling) { + mItems.remove(itemIndex); + mAdapter.destroyItem(this, pos, ii.object); + if (DEBUG) { + Log.i(TAG, "populate() - destroyItem() with pos: " + pos + + " view: " + ((View) ii.object)); + } + ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; + } + } else if (ii != null && pos == ii.position) { + extraHeightBottom += ii.heightFactor; + itemIndex++; + ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; + } else { + ii = addNewItem(pos, itemIndex); + itemIndex++; + extraHeightBottom += ii.heightFactor; + ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; + } + } + } + + calculatePageOffsets(curItem, curIndex, oldCurInfo); + } + + if (DEBUG) { + Log.i(TAG, "Current page list:"); + for (int i = 0; i < mItems.size(); i++) { + Log.i(TAG, "#" + i + ": page " + mItems.get(i).position); + } + } + + mAdapter.setPrimaryItem(this, mCurItem, curItem != null ? curItem.object : null); + + mAdapter.finishUpdate(this); + + // Check width measurement of current pages and drawing sort order. + // Update LayoutParams as needed. + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + lp.childIndex = i; + if (!lp.isDecor && lp.heightFactor == 0.f) { + // 0 means requery the adapter for this, it doesn't have a valid width. + final ItemInfo ii = infoForChild(child); + if (ii != null) { + lp.heightFactor = ii.heightFactor; + lp.position = ii.position; + } + } + } + sortChildDrawingOrder(); + + if (hasFocus()) { + View currentFocused = findFocus(); + ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null; + if (ii == null || ii.position != mCurItem) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(focusDirection)) { + break; + } + } + } + } + } + } + + private void sortChildDrawingOrder() { + if (mDrawingOrder != DRAW_ORDER_DEFAULT) { + if (mDrawingOrderedChildren == null) { + mDrawingOrderedChildren = new ArrayList(); + } else { + mDrawingOrderedChildren.clear(); + } + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + mDrawingOrderedChildren.add(child); + } + Collections.sort(mDrawingOrderedChildren, sPositionComparator); + } + } + + private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCurInfo) { + final int N = mAdapter.getCount(); + final int height = getClientHeight(); + final float marginOffset = height > 0 ? (float) mPageMargin / height : 0; + // Fix up offsets for later layout. + if (oldCurInfo != null) { + final int oldCurPosition = oldCurInfo.position; + // Base offsets off of oldCurInfo. + if (oldCurPosition < curItem.position) { + int itemIndex = 0; + ItemInfo ii = null; + float offset = oldCurInfo.offset + oldCurInfo.heightFactor + marginOffset; + for (int pos = oldCurPosition + 1; + pos <= curItem.position && itemIndex < mItems.size(); pos++) { + ii = mItems.get(itemIndex); + while (pos > ii.position && itemIndex < mItems.size() - 1) { + itemIndex++; + ii = mItems.get(itemIndex); + } + while (pos < ii.position) { + // We don't have an item populated for this, + // ask the adapter for an offset. + offset += mAdapter.getPageWidth(pos) + marginOffset; + pos++; + } + ii.offset = offset; + offset += ii.heightFactor + marginOffset; + } + } else if (oldCurPosition > curItem.position) { + int itemIndex = mItems.size() - 1; + ItemInfo ii = null; + float offset = oldCurInfo.offset; + for (int pos = oldCurPosition - 1; + pos >= curItem.position && itemIndex >= 0; pos--) { + ii = mItems.get(itemIndex); + while (pos < ii.position && itemIndex > 0) { + itemIndex--; + ii = mItems.get(itemIndex); + } + while (pos > ii.position) { + // We don't have an item populated for this, + // ask the adapter for an offset. + offset -= mAdapter.getPageWidth(pos) + marginOffset; + pos--; + } + offset -= ii.heightFactor + marginOffset; + ii.offset = offset; + } + } + } + + // Base all offsets off of curItem. + final int itemCount = mItems.size(); + float offset = curItem.offset; + int pos = curItem.position - 1; + mFirstOffset = curItem.position == 0 ? curItem.offset : -Float.MAX_VALUE; + mLastOffset = curItem.position == N - 1 ? + curItem.offset + curItem.heightFactor - 1 : Float.MAX_VALUE; + // Previous pages + for (int i = curIndex - 1; i >= 0; i--, pos--) { + final ItemInfo ii = mItems.get(i); + while (pos > ii.position) { + offset -= mAdapter.getPageWidth(pos--) + marginOffset; + } + offset -= ii.heightFactor + marginOffset; + ii.offset = offset; + if (ii.position == 0) mFirstOffset = offset; + } + offset = curItem.offset + curItem.heightFactor + marginOffset; + pos = curItem.position + 1; + // Next pages + for (int i = curIndex + 1; i < itemCount; i++, pos++) { + final ItemInfo ii = mItems.get(i); + while (pos < ii.position) { + offset += mAdapter.getPageWidth(pos++) + marginOffset; + } + if (ii.position == N - 1) { + mLastOffset = offset + ii.heightFactor - 1; + } + ii.offset = offset; + offset += ii.heightFactor + marginOffset; + } + + mNeedCalculatePageOffsets = false; + } + + /** + * This is the persistent state that is saved by ViewPager. Only needed + * if you are creating a sublass of ViewPager that must save its own + * state, in which case it should implement a subclass of this which + * contains that state. + */ + public static class SavedState extends BaseSavedState { + int position; + Parcelable adapterState; + ClassLoader loader; + + public SavedState(Parcelable superState) { + super(superState); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(position); + out.writeParcelable(adapterState, flags); + } + + @Override + public String toString() { + return "FragmentPager.SavedState{" + + Integer.toHexString(System.identityHashCode(this)) + + " position=" + position + "}"; + } + + public static final Creator CREATOR + = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks() { + @Override + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }); + + SavedState(Parcel in, ClassLoader loader) { + super(in); + if (loader == null) { + loader = getClass().getClassLoader(); + } + position = in.readInt(); + adapterState = in.readParcelable(loader); + this.loader = loader; + } + } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.position = mCurItem; + if (mAdapter != null) { + ss.adapterState = mAdapter.saveState(); + } + return ss; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (mAdapter != null) { + mAdapter.restoreState(ss.adapterState, ss.loader); + setCurrentItemInternal(ss.position, false, true); + } else { + mRestoredCurItem = ss.position; + mRestoredAdapterState = ss.adapterState; + mRestoredClassLoader = ss.loader; + } + } + + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + final LayoutParams lp = (LayoutParams) params; + lp.isDecor |= child instanceof Decor; + if (mInLayout) { + if (lp != null && lp.isDecor) { + throw new IllegalStateException("Cannot add pager decor view during layout"); + } + lp.needsMeasure = true; + addViewInLayout(child, index, params); + } else { + super.addView(child, index, params); + } + + if (USE_CACHE) { + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(mScrollingCacheEnabled); + } else { + child.setDrawingCacheEnabled(false); + } + } + } + + @Override + public void removeView(View view) { + if (mInLayout) { + removeViewInLayout(view); + } else { + super.removeView(view); + } + } + + ItemInfo infoForChild(View child) { + for (int i = 0; i < mItems.size(); i++) { + ItemInfo ii = mItems.get(i); + if (mAdapter.isViewFromObject(child, ii.object)) { + return ii; + } + } + return null; + } + + ItemInfo infoForAnyChild(View child) { + ViewParent parent; + while ((parent = child.getParent()) != this) { + if (parent == null || !(parent instanceof View)) { + return null; + } + child = (View) parent; + } + return infoForChild(child); + } + + ItemInfo infoForPosition(int position) { + for (int i = 0; i < mItems.size(); i++) { + ItemInfo ii = mItems.get(i); + if (ii.position == position) { + return ii; + } + } + return null; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // For simple implementation, our internal size is always 0. + // We depend on the container to specify the layout size of + // our view. We can't really know what it is since we will be + // adding and removing different arbitrary views and do not + // want the layout to change as this happens. + setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), + getDefaultSize(0, heightMeasureSpec)); + + final int measuredHeight = getMeasuredHeight(); + final int maxGutterSize = measuredHeight / 10; + mGutterSize = Math.min(maxGutterSize, mDefaultGutterSize); + + // Children are just made to fill our space. + int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + int childHeightSize = measuredHeight - getPaddingTop() - getPaddingBottom(); + + /* + * Make sure all children have been properly measured. Decor views first. + * Right now we cheat and make this less complicated by assuming decor + * views won't intersect. We will pin to edges based on gravity. + */ + int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp != null && lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + int widthMode = MeasureSpec.AT_MOST; + int heightMode = MeasureSpec.AT_MOST; + boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; + boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; + + if (consumeVertical) { + widthMode = MeasureSpec.EXACTLY; + } else if (consumeHorizontal) { + heightMode = MeasureSpec.EXACTLY; + } + + int widthSize = childWidthSize; + int heightSize = childHeightSize; + if (lp.width != LayoutParams.WRAP_CONTENT) { + widthMode = MeasureSpec.EXACTLY; + if (lp.width != LayoutParams.FILL_PARENT) { + widthSize = lp.width; + } + } + if (lp.height != LayoutParams.WRAP_CONTENT) { + heightMode = MeasureSpec.EXACTLY; + if (lp.height != LayoutParams.FILL_PARENT) { + heightSize = lp.height; + } + } + final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); + final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode); + child.measure(widthSpec, heightSpec); + + if (consumeVertical) { + childHeightSize -= child.getMeasuredHeight(); + } else if (consumeHorizontal) { + childWidthSize -= child.getMeasuredWidth(); + } + } + } + } + + mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); + + // Make sure we have created all fragments that we need to have shown. + mInLayout = true; + populate(); + mInLayout = false; + + // Page views next. + size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + + ": " + mChildWidthMeasureSpec); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp == null || !lp.isDecor) { + final int heightSpec = MeasureSpec.makeMeasureSpec( + (int) (childHeightSize * lp.heightFactor), MeasureSpec.EXACTLY); + child.measure(mChildWidthMeasureSpec, heightSpec); + } + } + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Make sure scroll position is set correctly. + if (h != oldh) { + recomputeScrollPosition(h, oldh, mPageMargin, mPageMargin); + } + } + + private void recomputeScrollPosition(int height, int oldHeight, int margin, int oldMargin) { + if (oldHeight > 0 && !mItems.isEmpty()) { + final int heightWithMargin = height - getPaddingTop() - getPaddingBottom() + margin; + final int oldHeightWithMargin = oldHeight - getPaddingTop() - getPaddingBottom() + + oldMargin; + final int ypos = getScrollY(); + final float pageOffset = (float) ypos / oldHeightWithMargin; + final int newOffsetPixels = (int) (pageOffset * heightWithMargin); + + scrollTo(getScrollX(), newOffsetPixels); + if (!mScroller.isFinished()) { + // We now return to your regularly scheduled scroll, already in progress. + final int newDuration = mScroller.getDuration() - mScroller.timePassed(); + ItemInfo targetInfo = infoForPosition(mCurItem); + mScroller.startScroll(0, newOffsetPixels, + 0, (int) (targetInfo.offset * height), newDuration); + } + } else { + final ItemInfo ii = infoForPosition(mCurItem); + final float scrollOffset = ii != null ? Math.min(ii.offset, mLastOffset) : 0; + final int scrollPos = (int) (scrollOffset * + (height - getPaddingTop() - getPaddingBottom())); + if (scrollPos != getScrollY()) { + completeScroll(false); + scrollTo(getScrollX(), scrollPos); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int count = getChildCount(); + int width = r - l; + int height = b - t; + int paddingLeft = getPaddingLeft(); + int paddingTop = getPaddingTop(); + int paddingRight = getPaddingRight(); + int paddingBottom = getPaddingBottom(); + final int scrollY = getScrollY(); + + int decorCount = 0; + + // First pass - decor views. We need to do this in two passes so that + // we have the proper offsets for non-decor views later. + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + int childLeft = 0; + int childTop = 0; + if (lp.isDecor) { + final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + switch (hgrav) { + default: + childLeft = paddingLeft; + break; + case Gravity.LEFT: + childLeft = paddingLeft; + paddingLeft += child.getMeasuredWidth(); + break; + case Gravity.CENTER_HORIZONTAL: + childLeft = Math.max((width - child.getMeasuredWidth()) / 2, + paddingLeft); + break; + case Gravity.RIGHT: + childLeft = width - paddingRight - child.getMeasuredWidth(); + paddingRight += child.getMeasuredWidth(); + break; + } + switch (vgrav) { + default: + childTop = paddingTop; + break; + case Gravity.TOP: + childTop = paddingTop; + paddingTop += child.getMeasuredHeight(); + break; + case Gravity.CENTER_VERTICAL: + childTop = Math.max((height - child.getMeasuredHeight()) / 2, + paddingTop); + break; + case Gravity.BOTTOM: + childTop = height - paddingBottom - child.getMeasuredHeight(); + paddingBottom += child.getMeasuredHeight(); + break; + } + childTop += scrollY; + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + decorCount++; + } + } + } + + final int childHeight = height - paddingTop - paddingBottom; + // Page views. Do this once we have the right padding offsets from above. + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + ItemInfo ii; + if (!lp.isDecor && (ii = infoForChild(child)) != null) { + int toff = (int) (childHeight * ii.offset); + int childLeft = paddingLeft; + int childTop = paddingTop + toff; + if (lp.needsMeasure) { + // This was added during layout and needs measurement. + // Do it now that we know what we're working with. + lp.needsMeasure = false; + final int widthSpec = MeasureSpec.makeMeasureSpec( + (int) (width - paddingLeft - paddingRight), + MeasureSpec.EXACTLY); + final int heightSpec = MeasureSpec.makeMeasureSpec( + (int) (childHeight * lp.heightFactor), + MeasureSpec.EXACTLY); + child.measure(widthSpec, heightSpec); + } + if (DEBUG) Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object + + ":" + childLeft + "," + childTop + " " + child.getMeasuredWidth() + + "x" + child.getMeasuredHeight()); + child.layout(childLeft, childTop, + childLeft + child.getMeasuredWidth(), + childTop + child.getMeasuredHeight()); + } + } + } + mLeftPageBounds = paddingLeft; + mRightPageBounds = width - paddingRight; + mDecorChildCount = decorCount; + + if (mFirstLayout) { + scrollToItem(mCurItem, false, 0, false); + } + mFirstLayout = false; + } + + @Override + public void computeScroll() { + if (!mScroller.isFinished() && mScroller.computeScrollOffset()) { + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + if (!pageScrolled(y)) { + mScroller.abortAnimation(); + scrollTo(x, 0); + } + } + + // Keep on drawing until the animation has finished. + ViewCompat.postInvalidateOnAnimation(this); + return; + } + + // Done with scroll, clean up state. + completeScroll(true); + } + + private boolean pageScrolled(int ypos) { + if (mItems.size() == 0) { + mCalledSuper = false; + onPageScrolled(0, 0, 0); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + return false; + } + final ItemInfo ii = infoForCurrentScrollPosition(); + final int height = getClientHeight(); + final int heightWithMargin = height + mPageMargin; + final float marginOffset = (float) mPageMargin / height; + final int currentPage = ii.position; + final float pageOffset = (((float) ypos / height) - ii.offset) / + (ii.heightFactor + marginOffset); + final int offsetPixels = (int) (pageOffset * heightWithMargin); + + mCalledSuper = false; + onPageScrolled(currentPage, pageOffset, offsetPixels); + if (!mCalledSuper) { + throw new IllegalStateException( + "onPageScrolled did not call superclass implementation"); + } + return true; + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + // Offset any decor views if needed - keep them on-screen at all times. + if (mDecorChildCount > 0) { + final int scrollY = getScrollY(); + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + final int height = getHeight(); + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isDecor) continue; + + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + int childTop = 0; + switch (vgrav) { + default: + childTop = paddingTop; + break; + case Gravity.TOP: + childTop = paddingTop; + paddingTop += child.getHeight(); + break; + case Gravity.CENTER_VERTICAL: + childTop = Math.max((height - child.getMeasuredHeight()) / 2, + paddingTop); + break; + case Gravity.BOTTOM: + childTop = height - paddingBottom - child.getMeasuredHeight(); + paddingBottom += child.getMeasuredHeight(); + break; + } + childTop += scrollY; + + final int childOffset = childTop - child.getTop(); + if (childOffset != 0) { + child.offsetTopAndBottom(childOffset); + } + } + } + + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + + if (mPageTransformer != null) { + final int scrollY = getScrollY(); + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + if (lp.isDecor) continue; + + final float transformPos = (float) (child.getTop() - scrollY) / getClientHeight(); + mPageTransformer.transformPage(child, transformPos); + } + } + + mCalledSuper = true; + } + + private void completeScroll(boolean postEvents) { + boolean needPopulate = mScrollState == SCROLL_STATE_SETTLING; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + } + mPopulatePending = false; + for (int i = 0; i < mItems.size(); i++) { + ItemInfo ii = mItems.get(i); + if (ii.scrolling) { + needPopulate = true; + ii.scrolling = false; + } + } + if (needPopulate) { + if (postEvents) { + ViewCompat.postOnAnimation(this, mEndScrollRunnable); + } else { + mEndScrollRunnable.run(); + } + } + } + + private boolean isGutterDrag(float y, float dy) { + return (y < mGutterSize && dy > 0) || (y > getHeight() - mGutterSize && dy < 0); + } + + private void enableLayers(boolean enable) { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final int layerType = enable ? + ViewCompat.LAYER_TYPE_HARDWARE : ViewCompat.LAYER_TYPE_NONE; + ViewCompat.setLayerType(getChildAt(i), layerType, null); + } + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + /* + * This method JUST determines whether we want to intercept the motion. + * If we return true, onMotionEvent will be called and we do the actual + * scrolling there. + */ + + final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; + + // Always take care of the touch gesture being complete. + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + // Release the drag. + if (DEBUG) Log.v(TAG, "Intercept done!"); + mIsBeingDragged = false; + mIsUnableToDrag = false; + mActivePointerId = INVALID_POINTER; + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + return false; + } + + // Nothing more to do here if we have decided whether or not we + // are dragging. + if (action != MotionEvent.ACTION_DOWN) { + if (mIsBeingDragged) { + if (DEBUG) Log.v(TAG, "Intercept returning true!"); + return true; + } + if (mIsUnableToDrag) { + if (DEBUG) Log.v(TAG, "Intercept returning false!"); + return false; + } + } + + switch (action) { + case MotionEvent.ACTION_MOVE: { + /* + * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check + * whether the user has moved far enough from his original down touch. + */ + + /* + * Locally do absolute value. mLastMotionY is set to the y value + * of the down event. + */ + final int activePointerId = mActivePointerId; + if (activePointerId == INVALID_POINTER) { + // If we don't have a valid id, the touch down wasn't on content. + break; + } + + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float dy = y - mLastMotionY; + final float yDiff = Math.abs(dy); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float xDiff = Math.abs(x - mInitialMotionX); + if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + + if (dy != 0 && !isGutterDrag(mLastMotionY, dy) && + canScroll(this, false, (int) dy, (int) x, (int) y)) { + // Nested view has scrollable area under this point. Let it be handled there. + mLastMotionX = x; + mLastMotionY = y; + mIsUnableToDrag = true; + return false; + } + if (yDiff > mTouchSlop && yDiff * 0.5f > xDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + requestParentDisallowInterceptTouchEvent(true); + setScrollState(SCROLL_STATE_DRAGGING); + mLastMotionY = dy > 0 ? mInitialMotionY + mTouchSlop : + mInitialMotionY - mTouchSlop; + mLastMotionX = x; + setScrollingCacheEnabled(true); + } else if (xDiff > mTouchSlop) { + // The finger has moved enough in the vertical + // direction to be counted as a drag... abort + // any attempt to drag horizontally, to work correctly + // with children that have scrolling containers. + if (DEBUG) Log.v(TAG, "Starting unable to drag!"); + mIsUnableToDrag = true; + } + if (mIsBeingDragged) { + // Scroll to follow the motion event + if (performDrag(y)) { + ViewCompat.postInvalidateOnAnimation(this); + } + } + break; + } + + case MotionEvent.ACTION_DOWN: { + /* + * Remember location of down touch. + * ACTION_DOWN always refers to pointer index 0. + */ + mLastMotionX = mInitialMotionX = ev.getX(); + mLastMotionY = mInitialMotionY = ev.getY(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + mIsUnableToDrag = false; + + mScroller.computeScrollOffset(); + if (mScrollState == SCROLL_STATE_SETTLING && + Math.abs(mScroller.getFinalY() - mScroller.getCurrY()) > mCloseEnough) { + // Let the user 'catch' the pager as it animates. + mScroller.abortAnimation(); + mPopulatePending = false; + populate(); + mIsBeingDragged = true; + requestParentDisallowInterceptTouchEvent(true); + setScrollState(SCROLL_STATE_DRAGGING); + } else { + completeScroll(false); + mIsBeingDragged = false; + } + + if (DEBUG) Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY + + " mIsBeingDragged=" + mIsBeingDragged + + "mIsUnableToDrag=" + mIsUnableToDrag); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + /* + * The only time we want to intercept motion events is if we are in the + * drag mode. + */ + return mIsBeingDragged; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (mFakeDragging) { + // A fake drag is in progress already, ignore this real one + // but still eat the touch events. + // (It is likely that the user is multi-touching the screen.) + return true; + } + + if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) { + // Don't handle edge touches immediately -- they may actually belong to one of our + // descendants. + return false; + } + + if (mAdapter == null || mAdapter.getCount() == 0) { + // Nothing to present or scroll; nothing to touch. + return false; + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + final int action = ev.getAction(); + boolean needsInvalidate = false; + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + mScroller.abortAnimation(); + mPopulatePending = false; + populate(); + + // Remember where the motion event started + mLastMotionX = mInitialMotionX = ev.getX(); + mLastMotionY = mInitialMotionY = ev.getY(); + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + break; + } + case MotionEvent.ACTION_MOVE: + if (!mIsBeingDragged) { + final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float yDiff = Math.abs(y - mLastMotionY); + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float xDiff = Math.abs(x - mLastMotionX); + if (DEBUG) + Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); + if (yDiff > mTouchSlop && yDiff > xDiff) { + if (DEBUG) Log.v(TAG, "Starting drag!"); + mIsBeingDragged = true; + requestParentDisallowInterceptTouchEvent(true); + mLastMotionY = y - mInitialMotionY > 0 ? mInitialMotionY + mTouchSlop : + mInitialMotionY - mTouchSlop; + mLastMotionX = x; + setScrollState(SCROLL_STATE_DRAGGING); + setScrollingCacheEnabled(true); + + // Disallow Parent Intercept, just in case + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } + } + // Not else! Note that mIsBeingDragged can be set above. + if (mIsBeingDragged) { + // Scroll to follow the motion event + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float y = MotionEventCompat.getY(ev, activePointerIndex); + needsInvalidate |= performDrag(y); + } + break; + case MotionEvent.ACTION_UP: + if (mIsBeingDragged) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getYVelocity( + velocityTracker, mActivePointerId); + mPopulatePending = true; + final int height = getClientHeight(); + final int scrollY = getScrollY(); + final ItemInfo ii = infoForCurrentScrollPosition(); + final int currentPage = ii.position; + final float pageOffset = (((float) scrollY / height) - ii.offset) / ii.heightFactor; + final int activePointerIndex = + MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float y = MotionEventCompat.getY(ev, activePointerIndex); + final int totalDelta = (int) (y - mInitialMotionY); + int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, + totalDelta); + setCurrentItemInternal(nextPage, true, true, initialVelocity); + + mActivePointerId = INVALID_POINTER; + endDrag(); + needsInvalidate = mTopEdge.onRelease() | mBottomEdge.onRelease(); + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsBeingDragged) { + scrollToItem(mCurItem, true, 0, false); + mActivePointerId = INVALID_POINTER; + endDrag(); + needsInvalidate = mTopEdge.onRelease() | mBottomEdge.onRelease(); + } + break; + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float y = MotionEventCompat.getY(ev, index); + mLastMotionY = y; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + mLastMotionY = MotionEventCompat.getY(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + if (needsInvalidate) { + ViewCompat.postInvalidateOnAnimation(this); + } + return true; + } + + private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) { + final ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(disallowIntercept); + } + } + + private boolean performDrag(float y) { + boolean needsInvalidate = false; + + final float deltaY = mLastMotionY - y; + mLastMotionY = y; + + float oldScrollY = getScrollY(); + float scrollY = oldScrollY + deltaY; + final int height = getClientHeight(); + + float topBound = height * mFirstOffset; + float bottomBound = height * mLastOffset; + boolean topAbsolute = true; + boolean bottomAbsolute = true; + + final ItemInfo firstItem = mItems.get(0); + final ItemInfo lastItem = mItems.get(mItems.size() - 1); + if (firstItem.position != 0) { + topAbsolute = false; + topBound = firstItem.offset * height; + } + if (lastItem.position != mAdapter.getCount() - 1) { + bottomAbsolute = false; + bottomBound = lastItem.offset * height; + } + + if (scrollY < topBound) { + if (topAbsolute) { + float over = topBound - scrollY; + needsInvalidate = mTopEdge.onPull(Math.abs(over) / height); + } + scrollY = topBound; + } else if (scrollY > bottomBound) { + if (bottomAbsolute) { + float over = scrollY - bottomBound; + needsInvalidate = mBottomEdge.onPull(Math.abs(over) / height); + } + scrollY = bottomBound; + } + // Don't lose the rounded component + mLastMotionX += scrollY - (int) scrollY; + scrollTo(getScrollX(), (int) scrollY); + pageScrolled((int) scrollY); + + return needsInvalidate; + } + + /** + * @return Info about the page at the current scroll position. + * This can be synthetic for a missing middle page; the 'object' field can be null. + */ + private ItemInfo infoForCurrentScrollPosition() { + final int height = getClientHeight(); + final float scrollOffset = height > 0 ? (float) getScrollY() / height : 0; + final float marginOffset = height > 0 ? (float) mPageMargin / height : 0; + int lastPos = -1; + float lastOffset = 0.f; + float lastHeight = 0.f; + boolean first = true; + + ItemInfo lastItem = null; + for (int i = 0; i < mItems.size(); i++) { + ItemInfo ii = mItems.get(i); + float offset; + if (!first && ii.position != lastPos + 1) { + // Create a synthetic item for a missing page. + ii = mTempItem; + ii.offset = lastOffset + lastHeight + marginOffset; + ii.position = lastPos + 1; + ii.heightFactor = mAdapter.getPageWidth(ii.position); + i--; + } + offset = ii.offset; + + final float topBound = offset; + final float bottomBound = offset + ii.heightFactor + marginOffset; + if (first || scrollOffset >= topBound) { + if (scrollOffset < bottomBound || i == mItems.size() - 1) { + return ii; + } + } else { + return lastItem; + } + first = false; + lastPos = ii.position; + lastOffset = offset; + lastHeight = ii.heightFactor; + lastItem = ii; + } + + return lastItem; + } + + private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaY) { + int targetPage; + if (Math.abs(deltaY) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { + targetPage = velocity > 0 ? currentPage : currentPage + 1; + } else { + final float truncator = currentPage >= mCurItem ? 0.4f : 0.6f; + targetPage = (int) (currentPage + pageOffset + truncator); + } + + if (mItems.size() > 0) { + final ItemInfo firstItem = mItems.get(0); + final ItemInfo lastItem = mItems.get(mItems.size() - 1); + + // Only let the user target pages we have items for + targetPage = Math.max(firstItem.position, Math.min(targetPage, lastItem.position)); + } + + return targetPage; + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + boolean needsInvalidate = false; + + final int overScrollMode = ViewCompat.getOverScrollMode(this); + if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS || + (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && + mAdapter != null && mAdapter.getCount() > 1)) { + if (!mTopEdge.isFinished()) { + final int restoreCount = canvas.save(); + final int height = getHeight(); + final int width = getWidth() - getPaddingLeft() - getPaddingRight(); + + canvas.translate(getPaddingLeft(), mFirstOffset * height); + mTopEdge.setSize(width, height); + needsInvalidate |= mTopEdge.draw(canvas); + canvas.restoreToCount(restoreCount); + } + if (!mBottomEdge.isFinished()) { + final int restoreCount = canvas.save(); + final int height = getHeight(); + final int width = getWidth() - getPaddingLeft() - getPaddingRight(); + + canvas.rotate(180); + canvas.translate(-width - getPaddingLeft(), -(mLastOffset + 1) * height); + mBottomEdge.setSize(width, height); + needsInvalidate |= mBottomEdge.draw(canvas); + canvas.restoreToCount(restoreCount); + } + } else { + mTopEdge.finish(); + mBottomEdge.finish(); + } + + if (needsInvalidate) { + // Keep animating + ViewCompat.postInvalidateOnAnimation(this); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Draw the margin drawable between pages if needed. + if (mPageMargin > 0 && mMarginDrawable != null && mItems.size() > 0 && mAdapter != null) { + final int scrollY = getScrollY(); + final int height = getHeight(); + + final float marginOffset = (float) mPageMargin / height; + int itemIndex = 0; + ItemInfo ii = mItems.get(0); + float offset = ii.offset; + final int itemCount = mItems.size(); + final int firstPos = ii.position; + final int lastPos = mItems.get(itemCount - 1).position; + for (int pos = firstPos; pos < lastPos; pos++) { + while (pos > ii.position && itemIndex < itemCount) { + ii = mItems.get(++itemIndex); + } + + float drawAt; + if (pos == ii.position) { + drawAt = (ii.offset + ii.heightFactor) * height; + offset = ii.offset + ii.heightFactor + marginOffset; + } else { + float heightFactor = mAdapter.getPageWidth(pos); + drawAt = (offset + heightFactor) * height; + offset += heightFactor + marginOffset; + } + + if (drawAt + mPageMargin > scrollY) { + mMarginDrawable.setBounds(mLeftPageBounds, (int) drawAt, + mRightPageBounds, (int) (drawAt + mPageMargin + 0.5f)); + mMarginDrawable.draw(canvas); + } + + if (drawAt > scrollY + height) { + break; // No more visible, no sense in continuing + } + } + } + } + + /** + * Start a fake drag of the pager. + *

+ *

A fake drag can be useful if you want to synchronize the motion of the ViewPager + * with the touch scrolling of another view, while still letting the ViewPager + * control the snapping motion and fling behavior. (e.g. parallax-scrolling tabs.) + * Call {@link #fakeDragBy(float)} to simulate the actual drag motion. Call + * {@link #endFakeDrag()} to complete the fake drag and fling as necessary. + *

+ *

During a fake drag the ViewPager will ignore all touch events. If a real drag + * is already in progress, this method will return false. + * + * @return true if the fake drag began successfully, false if it could not be started. + * @see #fakeDragBy(float) + * @see #endFakeDrag() + */ + public boolean beginFakeDrag() { + if (mIsBeingDragged) { + return false; + } + mFakeDragging = true; + setScrollState(SCROLL_STATE_DRAGGING); + mInitialMotionY = mLastMotionY = 0; + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } else { + mVelocityTracker.clear(); + } + final long time = SystemClock.uptimeMillis(); + final MotionEvent ev = MotionEvent.obtain(time, time, MotionEvent.ACTION_DOWN, 0, 0, 0); + mVelocityTracker.addMovement(ev); + ev.recycle(); + mFakeDragBeginTime = time; + return true; + } + + /** + * End a fake drag of the pager. + * + * @see #beginFakeDrag() + * @see #fakeDragBy(float) + */ + public void endFakeDrag() { + if (!mFakeDragging) { + throw new IllegalStateException("No fake drag in progress. Call beginFakeDrag first."); + } + + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getYVelocity( + velocityTracker, mActivePointerId); + mPopulatePending = true; + final int height = getClientHeight(); + final int scrollY = getScrollY(); + final ItemInfo ii = infoForCurrentScrollPosition(); + final int currentPage = ii.position; + final float pageOffset = (((float) scrollY / height) - ii.offset) / ii.heightFactor; + final int totalDelta = (int) (mLastMotionY - mInitialMotionY); + int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, + totalDelta); + setCurrentItemInternal(nextPage, true, true, initialVelocity); + endDrag(); + + mFakeDragging = false; + } + + /** + * Fake drag by an offset in pixels. You must have called {@link #beginFakeDrag()} first. + * + * @param yOffset Offset in pixels to drag by. + * @see #beginFakeDrag() + * @see #endFakeDrag() + */ + public void fakeDragBy(float yOffset) { + if (!mFakeDragging) { + throw new IllegalStateException("No fake drag in progress. Call beginFakeDrag first."); + } + + mLastMotionY += yOffset; + + float oldScrollY = getScrollY(); + float scrollY = oldScrollY - yOffset; + final int height = getClientHeight(); + + float topBound = height * mFirstOffset; + float bottomBound = height * mLastOffset; + + final ItemInfo firstItem = mItems.get(0); + final ItemInfo lastItem = mItems.get(mItems.size() - 1); + if (firstItem.position != 0) { + topBound = firstItem.offset * height; + } + if (lastItem.position != mAdapter.getCount() - 1) { + bottomBound = lastItem.offset * height; + } + + if (scrollY < topBound) { + scrollY = topBound; + } else if (scrollY > bottomBound) { + scrollY = bottomBound; + } + // Don't lose the rounded component + mLastMotionY += scrollY - (int) scrollY; + scrollTo(getScrollX(), (int) scrollY); + pageScrolled((int) scrollY); + + // Synthesize an event for the VelocityTracker. + final long time = SystemClock.uptimeMillis(); + final MotionEvent ev = MotionEvent.obtain(mFakeDragBeginTime, time, MotionEvent.ACTION_MOVE, + 0, mLastMotionY, 0); + mVelocityTracker.addMovement(ev); + ev.recycle(); + } + + /** + * Returns true if a fake drag is in progress. + * + * @return true if currently in a fake drag, false otherwise. + * @see #beginFakeDrag() + * @see #fakeDragBy(float) + * @see #endFakeDrag() + */ + public boolean isFakeDragging() { + return mFakeDragging; + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastMotionY = MotionEventCompat.getY(ev, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + } + } + } + + private void endDrag() { + mIsBeingDragged = false; + mIsUnableToDrag = false; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + public boolean internalCanScrollVertically(int direction) { + if (mAdapter == null) { + return false; + } + + final int height = getClientHeight(); + final int scrollY = getScrollY(); + if (direction < 0) { + return (scrollY > (int) (height * mFirstOffset)); + } else if (direction > 0) { + return (scrollY < (int) (height * mLastOffset)); + } else { + return false; + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dy Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dy, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + final View child = group.getChildAt(i); + if (y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + canScroll(child, true, dy, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollVertically(v, -dy); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (event.hasNoModifiers()) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) { + currentFocused = null; + } else if (currentFocused != null) { + boolean isChild = false; + for (ViewParent parent = currentFocused.getParent(); parent instanceof ViewGroup; + parent = parent.getParent()) { + if (parent == this) { + isChild = true; + break; + } + } + if (!isChild) { + // This would cause the focus search down below to fail in fun ways. + final StringBuilder sb = new StringBuilder(); + sb.append(currentFocused.getClass().getSimpleName()); + for (ViewParent parent = currentFocused.getParent(); parent instanceof ViewGroup; + parent = parent.getParent()) { + sb.append(" => ").append(parent.getClass().getSimpleName()); + } + Log.e(TAG, "arrowScroll tried to find focus based on non-child " + + "current focused view " + sb.toString()); + currentFocused = null; + } + } + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_UP) { + // If there is nothing to the left, or this is causing us to + // jump to the right, then what we really want to do is page left. + final int nextTop = getChildRectInPagerCoordinates(mTempRect, nextFocused).top; + final int currTop = getChildRectInPagerCoordinates(mTempRect, currentFocused).top; + if (currentFocused != null && nextTop >= currTop) { + handled = pageUp(); + } else { + handled = nextFocused.requestFocus(); + } + } else if (direction == View.FOCUS_DOWN) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + final int nextDown = getChildRectInPagerCoordinates(mTempRect, nextFocused).bottom; + final int currDown = getChildRectInPagerCoordinates(mTempRect, currentFocused).bottom; + if (currentFocused != null && nextDown <= currDown) { + handled = pageDown(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_UP || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageUp(); + } else if (direction == FOCUS_DOWN || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageDown(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + private Rect getChildRectInPagerCoordinates(Rect outRect, View child) { + if (outRect == null) { + outRect = new Rect(); + } + if (child == null) { + outRect.set(0, 0, 0, 0); + return outRect; + } + outRect.left = child.getLeft(); + outRect.right = child.getRight(); + outRect.top = child.getTop(); + outRect.bottom = child.getBottom(); + + ViewParent parent = child.getParent(); + while (parent instanceof ViewGroup && parent != this) { + final ViewGroup group = (ViewGroup) parent; + outRect.left += group.getLeft(); + outRect.right += group.getRight(); + outRect.top += group.getTop(); + outRect.bottom += group.getBottom(); + + parent = group.getParent(); + } + return outRect; + } + + boolean pageUp() { + if (mCurItem > 0) { + setCurrentItem(mCurItem - 1, true); + return true; + } + return false; + } + + boolean pageDown() { + if (mAdapter != null && mCurItem < (mAdapter.getCount() - 1)) { + setCurrentItem(mCurItem + 1, true); + return true; + } + return false; + } + + /** + * We only want the current page that is being shown to be focusable. + */ + @Override + public void addFocusables(ArrayList views, int direction, int focusableMode) { + final int focusableCount = views.size(); + + final int descendantFocusability = getDescendantFocusability(); + + if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addFocusables(views, direction, focusableMode); + } + } + } + } + + // we add ourselves (if focusable) in all cases except for when we are + // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // to avoid the focus search finding layouts when a more precise search + // among the focusable children would be more interesting. + if ( + descendantFocusability != FOCUS_AFTER_DESCENDANTS || + // No focusable descendants + (focusableCount == views.size())) { + // Note that we can't call the superclass here, because it will + // add all views in. So we need to do the same thing View does. + if (!isFocusable()) { + return; + } + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + if (views != null) { + views.add(this); + } + } + } + + /** + * We only want the current page that is being shown to be touchable. + */ + @Override + public void addTouchables(ArrayList views) { + // Note that we don't call super.addTouchables(), which means that + // we don't call View.addTouchables(). This is okay because a ViewPager + // is itself not touchable. + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + child.addTouchables(views); + } + } + } + } + + /** + * We only want the current page that is being shown to be focusable. + */ + @Override + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + int index; + int increment; + int end; + int count = getChildCount(); + if ((direction & FOCUS_FORWARD) != 0) { + index = 0; + increment = 1; + end = count; + } else { + index = count - 1; + increment = -1; + end = -1; + } + for (int i = index; i != end; i += increment) { + View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem) { + if (child.requestFocus(direction, previouslyFocusedRect)) { + return true; + } + } + } + } + return false; + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + // Dispatch scroll events from this ViewPager. + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { + return super.dispatchPopulateAccessibilityEvent(event); + } + + // Dispatch all other accessibility events from the current page. + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == VISIBLE) { + final ItemInfo ii = infoForChild(child); + if (ii != null && ii.position == mCurItem && + child.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + } + + return false; + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return generateDefaultLayoutParams(); + } + + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + class MyAccessibilityDelegate extends AccessibilityDelegateCompat { + + @Override + public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(host, event); + event.setClassName(ViewPager.class.getName()); + final AccessibilityRecordCompat recordCompat = AccessibilityRecordCompat.obtain(); + recordCompat.setScrollable(canScroll()); + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED + && mAdapter != null) { + recordCompat.setItemCount(mAdapter.getCount()); + recordCompat.setFromIndex(mCurItem); + recordCompat.setToIndex(mCurItem); + } + } + + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setClassName(ViewPager.class.getName()); + info.setScrollable(canScroll()); + if (internalCanScrollVertically(1)) { + info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD); + } + if (internalCanScrollVertically(-1)) { + info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD); + } + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (super.performAccessibilityAction(host, action, args)) { + return true; + } + switch (action) { + case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD: { + if (internalCanScrollVertically(1)) { + setCurrentItem(mCurItem + 1); + return true; + } + } + return false; + case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: { + if (internalCanScrollVertically(-1)) { + setCurrentItem(mCurItem - 1); + return true; + } + } + return false; + } + return false; + } + + private boolean canScroll() { + return (mAdapter != null) && (mAdapter.getCount() > 1); + } + } + + private class PagerObserver extends DataSetObserver { + @Override + public void onChanged() { + dataSetChanged(); + } + + @Override + public void onInvalidated() { + dataSetChanged(); + } + } + + /** + * Layout parameters that should be supplied for views added to a + * ViewPager. + */ + public static class LayoutParams extends ViewGroup.LayoutParams { + /** + * true if this view is a decoration on the pager itself and not + * a view supplied by the adapter. + */ + public boolean isDecor; + + /** + * Gravity setting for use on decor views only: + * Where to position the view page within the overall ViewPager + * container; constants are defined in {@link Gravity}. + */ + public int gravity; + + /** + * Width as a 0-1 multiplier of the measured pager width + */ + float heightFactor = 0.f; + + /** + * true if this view was added during layout and needs to be measured + * before being positioned. + */ + boolean needsMeasure; + + /** + * Adapter position this view is for if !isDecor + */ + int position; + + /** + * Current child index within the ViewPager that this view occupies + */ + int childIndex; + + public LayoutParams() { + super(FILL_PARENT, FILL_PARENT); + } + + public LayoutParams(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); + gravity = a.getInteger(0, Gravity.TOP); + a.recycle(); + } + } + + static class ViewPositionComparator implements Comparator { + @Override + public int compare(View lhs, View rhs) { + final LayoutParams llp = (LayoutParams) lhs.getLayoutParams(); + final LayoutParams rlp = (LayoutParams) rhs.getLayoutParams(); + if (llp.isDecor != rlp.isDecor) { + return llp.isDecor ? 1 : -1; + } + return llp.position - rlp.position; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/VpSwipeRefreshLayout.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/VpSwipeRefreshLayout.java new file mode 100644 index 0000000..07b7e6e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/ui/VpSwipeRefreshLayout.java @@ -0,0 +1,65 @@ +package com.fengliyan.tianlesue.view.main.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.ViewConfiguration; + +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +/** + * ying 2020/9/15 + * Describe :滑动冲突 + */ + +public class VpSwipeRefreshLayout extends SwipeRefreshLayout { + + private float startY; + private float startX; + // 记录viewPager是否拖拽的标记 + private boolean mIsVpDragger; + private final int mTouchSlop; + + public VpSwipeRefreshLayout(Context context, AttributeSet attrs) { + super(context, attrs); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + int action = ev.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + // 记录手指按下的位置 + startY = ev.getY(); + startX = ev.getX(); + // 初始化标记 + mIsVpDragger = false; + break; + case MotionEvent.ACTION_MOVE: + // 如果viewpager正在拖拽中,那么不拦截它的事件,直接return false; + if(mIsVpDragger) { + return false; + } + + // 获取当前手指位置 + float endY = ev.getY(); + float endX = ev.getX(); + float distanceX = Math.abs(endX - startX); + float distanceY = Math.abs(endY - startY); + // 如果X轴位移大于Y轴位移,那么将事件交给viewPager处理。 + if(distanceX > mTouchSlop && distanceX > distanceY) { + mIsVpDragger = true; + return false; + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + // 初始化标记 + mIsVpDragger = false; + break; + } + // 如果是Y轴位移大于X轴,事件交给swipeRefreshLayout处理。 + return super.onInterceptTouchEvent(ev); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/DefaultExoConfig.kt b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/DefaultExoConfig.kt new file mode 100644 index 0000000..c03738d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/DefaultExoConfig.kt @@ -0,0 +1,54 @@ +package com.fengliyan.tianlesue.view.main.utils + +import android.content.Context +import android.net.Uri +import com.google.android.exoplayer2.MediaItem +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory +import com.google.android.exoplayer2.source.MediaSource +import com.google.android.exoplayer2.source.ProgressiveMediaSource +import com.google.android.exoplayer2.source.dash.DashMediaSource +import com.google.android.exoplayer2.source.hls.HlsMediaSource +import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource +import com.google.android.exoplayer2.util.MimeTypes + +class DefaultExoConfig(val context: Context) { + val USER_AGENT = "android" + val dataSourceFactory: VideoCacheDataSourceFactory = VideoCacheDataSourceFactory(context) + val mediaSourceFactory: ProgressiveMediaSource.Factory = + ProgressiveMediaSource.Factory(dataSourceFactory, DefaultExtractorsFactory()) + + fun createMediaSource(uri: Uri?): MediaSource? { + if (uri != null) { + val url = uri.toString() + val mineType = getMineTypeForMediaUrl(url) + val mediaItem = MediaItem.fromUri(uri) + return when (mineType) { + MimeTypes.APPLICATION_M3U8 -> + HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem) + MimeTypes.APPLICATION_SS + -> SsMediaSource.Factory(dataSourceFactory) + .createMediaSource(mediaItem) + + MimeTypes.APPLICATION_MPD -> DashMediaSource.Factory(dataSourceFactory) + .createMediaSource(mediaItem) + + else -> mediaSourceFactory.createMediaSource(mediaItem) + } + } else { + return null + } + } + + fun getMineTypeForMediaUrl(url: String): String { + val list = url.split('.') + if (list.isNotEmpty()) { + return when (list[list.size - 1]) { + "m3u8" -> MimeTypes.APPLICATION_M3U8 + "ss" -> MimeTypes.APPLICATION_SS + "dash" -> MimeTypes.APPLICATION_MPD + else -> MimeTypes.APPLICATION_MP4 //TODO:识别不了统一当MP4处理 + } + } + return MimeTypes.APPLICATION_MP4 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/FastBlur.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/FastBlur.java new file mode 100644 index 0000000..996af1b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/FastBlur.java @@ -0,0 +1,254 @@ +package com.fengliyan.tianlesue.view.main.utils; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.drawable.BitmapDrawable; +import android.util.Log; +import android.view.View; +import android.view.ViewTreeObserver; + +public class FastBlur { + + public static void applyBlur(final View v) { + v.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + v.getViewTreeObserver().removeOnPreDrawListener(this); + v.buildDrawingCache(); + Bitmap bmp = v.getDrawingCache(); + blur(bmp, v); + return true; + } + }); + } + + public static void blur(Bitmap bkg, View view) { + long startMs = System.currentTimeMillis(); + float scaleFactor = 1; + float radius = 20; + scaleFactor = 8; + radius = 2; + + Log.e("blurView", view.getMeasuredWidth() + "vs" + view.getMeasuredHeight()); + Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth() / scaleFactor), + (int) (view.getMeasuredHeight() / scaleFactor), Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(overlay); + canvas.translate(-view.getLeft() / scaleFactor, -view.getTop() / scaleFactor); + canvas.scale(1 / scaleFactor, 1 / scaleFactor); + Paint paint = new Paint(); + paint.setFlags(Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(bkg, 0, 0, paint); + + overlay = FastBlur.doBlur(overlay, (int) radius, true); + view.setBackgroundDrawable(new BitmapDrawable(view.getResources(), overlay)); + } + + public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) { + + Bitmap bitmap; + if (canReuseInBitmap) { + bitmap = sentBitmap; + } else { + bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); + } + + if (radius < 1) { + return (null); + } + + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + + int[] pix = new int[w * h]; + bitmap.getPixels(pix, 0, w, 0, 0, w, h); + + int wm = w - 1; + int hm = h - 1; + int wh = w * h; + int div = radius + radius + 1; + + int r[] = new int[wh]; + int g[] = new int[wh]; + int b[] = new int[wh]; + int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; + int vmin[] = new int[Math.max(w, h)]; + + int divsum = (div + 1) >> 1; + divsum *= divsum; + int dv[] = new int[256 * divsum]; + for (i = 0; i < 256 * divsum; i++) { + dv[i] = (i / divsum); + } + + yw = yi = 0; + + int[][] stack = new int[div][3]; + int stackpointer; + int stackstart; + int[] sir; + int rbs; + int r1 = radius + 1; + int routsum, goutsum, boutsum; + int rinsum, ginsum, binsum; + + for (y = 0; y < h; y++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + for (i = -radius; i <= radius; i++) { + p = pix[yi + Math.min(wm, Math.max(i, 0))]; + sir = stack[i + radius]; + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + rbs = r1 - Math.abs(i); + rsum += sir[0] * rbs; + gsum += sir[1] * rbs; + bsum += sir[2] * rbs; + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + } + stackpointer = radius; + + for (x = 0; x < w; x++) { + + r[yi] = dv[rsum]; + g[yi] = dv[gsum]; + b[yi] = dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (y == 0) { + vmin[x] = Math.min(x + radius + 1, wm); + } + p = pix[yw + vmin[x]]; + + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[(stackpointer) % div]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi++; + } + yw += w; + } + for (x = 0; x < w; x++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + yp = -radius * w; + for (i = -radius; i <= radius; i++) { + yi = Math.max(0, yp) + x; + + sir = stack[i + radius]; + + sir[0] = r[yi]; + sir[1] = g[yi]; + sir[2] = b[yi]; + + rbs = r1 - Math.abs(i); + + rsum += r[yi] * rbs; + gsum += g[yi] * rbs; + bsum += b[yi] * rbs; + + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + + if (i < hm) { + yp += w; + } + } + yi = x; + stackpointer = radius; + for (y = 0; y < h; y++) { + // Preserve alpha channel: ( 0xff000000 & pix[yi] ) + pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (x == 0) { + vmin[y] = Math.min(y + r1, hm) * w; + } + p = x + vmin[y]; + + sir[0] = r[p]; + sir[1] = g[p]; + sir[2] = b[p]; + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[stackpointer]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi += w; + } + } + + bitmap.setPixels(pix, 0, w, 0, 0, w, h); + + return (bitmap); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/JumpUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/JumpUtils.java new file mode 100644 index 0000000..943de37 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/JumpUtils.java @@ -0,0 +1,135 @@ +package com.fengliyan.tianlesue.view.main.utils; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.news.AddQQGroupBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.view.WeChatAccountsDialog; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.settings.CaibeiRechargeActivity; +import com.fengliyan.tianlesue.view.settings.CertificationActivity; +import com.fengliyan.tianlesue.view.settings.InvitationActivity; +import com.fengliyan.tianlesue.view.settings.MemberActivity; +import com.fengliyan.tianlesue.view.settings.MissionActivity; +import com.fengliyan.tianlesue.view.settings.MyItemsActivity; +import com.fengliyan.uikit.toast.MaleToast; + +public class JumpUtils { + public static void jump(int linkType, String linkUrl, Context context) { + switch (linkType) { + case 0: + break; + case 1: + Intent intentH5 = new Intent(context, BaseWebViewActivity.class); + intentH5.putExtra("ClickUrl", linkUrl); + context.startActivity(intentH5); + break; + case 2: + if (!StrU.isEmpty(linkUrl)) { + if (linkUrl.contains("/")) { + String[] array = linkUrl.split("/"); + if (array.length < 2) { + return; + } + String action = array[0]; + String id = array[1]; + if (action.equals("userinfo")) { + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", Integer.parseInt(id)); + context.startActivity(intent); + } + return; + } + + if ("help".equals(linkUrl)) { + Intent intentHelp = new Intent(context, BaseWebViewActivity.class); +// if (UserManager.getUserInfo().getType() == 2) { +// intentHelp.putExtra("ClickUrl", ConstUrl.HELP_URL_SPECIAL); +// } else { + if (UserManager.getUserInfo().getGender() == 2) { + intentHelp.putExtra("ClickUrl", ConstUrl.HELP_URL_BOY); + } else { + intentHelp.putExtra("ClickUrl", ConstUrl.HELP_URL_GIRL); + } +// } + context.startActivity(intentHelp); + } else if ("invite".equals(linkUrl)) { + Intent intentInvite = new Intent(context, InvitationActivity.class); + context.startActivity(intentInvite); + } else if ("rechargeCoin".equals(linkUrl)) { //跳转到充值金币页面 + Intent intentRechargeCoin = new Intent(context, CaibeiRechargeActivity.class); + context.startActivity(intentRechargeCoin); + } else if ("applyBigCast".equals(linkUrl)) { //跳转到女神页面(如果没有成为女神,如果是女神了,就提示已经是女神) + if (SPUtils.getInt(context, ConsUser.IS_ANCHOR) == 1 && SPUtils.getInt(context, ConsUser.IS_FACE_STATUS) == 1) { + MaleToast.showMessage(context, "您已经是女神了"); + } else { + Intent intentApplyBigCast = new Intent(context, CertificationActivity.class); + context.startActivity(intentApplyBigCast); + } + } else if ("auditCamera".equals(linkUrl)) { //跳到申请自拍认证的界面 + Intent intentAuditCamera = new Intent(context, CertificationActivity.class); + context.startActivity(intentAuditCamera); + } else if ("member".equals(linkUrl) || "svip".equals(linkUrl)) { + int anInt = SPUtils.getInt(context, ConsUser.GENDER); +// if (anInt == 2) { //男生 + Intent intentMember = new Intent(context, MemberActivity.class); + intentMember.putExtra("index", 0); + context.startActivity(intentMember); +// } + } else if ("my_item".equals(linkUrl)) {//我的道具 + Intent intent = new Intent(context, MyItemsActivity.class); + context.startActivity(intent); + } else if ("sign".equals(linkUrl)) {//签到 + Intent intent = new Intent(context, MissionActivity.class); + context.startActivity(intent); + } else if ("customerService".equals(linkUrl)) { + NimUIKit.startP2PSession(context, "4"); + } + } + break; + case 3: + if (!TextUtils.isEmpty(linkUrl)) { + Gson gson = new Gson(); + AddQQGroupBean addQQGroupBean = gson.fromJson(linkUrl, AddQQGroupBean.class); + if (null != addQQGroupBean) { + String action = addQQGroupBean.getAction(); + if (!TextUtils.isEmpty(action)) { + if (action.equals("add_qq_group")) { + String androidKey = addQQGroupBean.getData().getAndroidKey(); + if (androidKey == null) return; + Intent intent = new Intent(); + intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + androidKey)); + // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + try { + context.startActivity(intent); + } catch (Exception e) { + // 未安装手Q或安装的版本不支持 + MaleToast.showMessage(context, "检查是否安装QQ或QQ为最新版本"); + } + } else if (action.equals("wexinPublic")) { + String weixinId = addQQGroupBean.getData().getWeixinId(); + WeChatAccountsDialog wechatAccounts = new WeChatAccountsDialog(context, weixinId); + wechatAccounts.show(); + } + } + + } + + } + break; + case 11: + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(linkUrl))); + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/UiUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/UiUtils.java new file mode 100644 index 0000000..805dcb8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/UiUtils.java @@ -0,0 +1,56 @@ +package com.fengliyan.tianlesue.view.main.utils; + +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.text.TextUtils; + +import java.util.List; + +public class UiUtils { + public static int dp2px(Context context, float dpValue){ + float scale=context.getResources().getDisplayMetrics().density; + return (int)(dpValue*scale+0.5f); + } + + /** + * px转换成dp + */ + public static int px2dp(Context context,float pxValue){ + float scale=context.getResources().getDisplayMetrics().density; + return (int)(pxValue/scale+0.5f); + } + + /** + * sp转换成px + */ + public static int sp2px(Context context,float spValue){ + float fontScale=context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue*fontScale+0.5f); + } + /** + * px转换成sp + */ + public static int px2sp(Context context,float pxValue){ + float fontScale=context.getResources().getDisplayMetrics().scaledDensity; + return (int) (pxValue/fontScale+0.5f); + } + + public static boolean isForeground(Context context, String className) { + if (context == null || TextUtils.isEmpty(className)) { + return false; + } + + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List list = am.getRunningTasks(1); + if (list != null && list.size() > 0) { + ComponentName cpn = list.get(0).topActivity; + if (className.equals(cpn.getClassName())) { + return true; + } + } + + return false; + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/VideoCacheDataSourceFactory.java b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/VideoCacheDataSourceFactory.java new file mode 100644 index 0000000..ccad2d6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/main/utils/VideoCacheDataSourceFactory.java @@ -0,0 +1,30 @@ +package com.fengliyan.tianlesue.view.main.utils; + +import android.content.Context; + +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.upstream.cache.CacheDataSource; +import com.fengliyan.tianlesue.view.base.BaseApplication; + +public class VideoCacheDataSourceFactory implements DataSource.Factory { + + private final Context context; + private final DefaultDataSourceFactory defaultDataSourceFactory; + + public VideoCacheDataSourceFactory(Context context) { + this.context = context; + // 创建默认数据源工厂 + this.defaultDataSourceFactory = new DefaultDataSourceFactory(context, "exoplayer-cache"); + } + + @Override + public DataSource createDataSource() { + return new CacheDataSource( + BaseApplication.getSimpleCache(), // 缓存实例 + defaultDataSourceFactory.createDataSource(), // 网络数据源工厂 + CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR // 缓存错误时忽略缓存 + ); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/ChatActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/ChatActivity.java new file mode 100644 index 0000000..f153251 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/ChatActivity.java @@ -0,0 +1,281 @@ +package com.fengliyan.tianlesue.view.news.activity; + +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.DisplayMetrics; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewTreeObserver; + +import com.fengliyan.uikit.bottomedit.BottomEdit; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.dialog.DialogGiftBean; +import com.fengliyan.uikit.dialog.GiftListBean; +import com.fengliyan.uikit.emoji.utils.MoonUtil; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.model.news.RecentContactBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.VideoActivity; +import com.fengliyan.tianlesue.view.news.fragment.ChatFragment; +import com.fengliyan.tianlesue.view.news.fragment.EmotionFragment; +import com.fengliyan.tianlesue.view.news.fragment.GiftFragment; +import com.fengliyan.tianlesue.view.settings.WalletActivity; +@Deprecated +public class ChatActivity extends BaseActivity { + private BottomEdit mBottomEdit; + private ChatFragment mChatFragment; + private GiftFragment mGiftFragment; + private EmotionFragment mEmotionFragment; + public static final int SINGLE_SELECTOR_REQUEST = 201; + private MultiImageSelector mSelector; + private BaseMessageDialog mConfirmDialog; + public RecentContactBean mRecentContactBean; + + @Override + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat); + setDefaultTitle(); + initView(); + mBottomEdit.setFragment(mChatFragment); + mBottomEdit.addBottomFragment(mEmotionFragment); + mBottomEdit.addBottomFragment(mGiftFragment); + mBottomEdit.getEditText().setEms(200); + mBottomEdit.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + Rect r = new Rect(); + ChatActivity.this.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); + + DisplayMetrics dm = getResources().getDisplayMetrics(); + int screenHeight = dm.heightPixels; +// int screenHeight = ChatActivity.this.getWindow().getDecorView().getRootView().getHeight(); + int heightDifference = screenHeight - r.bottom; + mBottomEdit.setBottomFragmentHeight(heightDifference); + } + }); + + mBottomEdit.setSubmitButtonClickedListener(new BottomEdit.SubmitButtonClickListener() { + @Override + public void onSubmitButtonClicked(String message) { + if(!TextUtils.isEmpty(mBottomEdit.getEditText().getText().toString())) { + mChatFragment.submitMessage(mBottomEdit.getEditText().getText().toString()); + mBottomEdit.getEditText().setText(""); + } + } + }); + } + +// private void parseNotifyIntent(Intent intent) { +// ArrayList messages = (ArrayList) intent.getSerializableExtra(NimIntent.EXTRA_NOTIFY_CONTENT); +// if (messages != null && messages.size() <= 1) { +// +// Intent intent1 = new Intent().putExtra(NimIntent.EXTRA_NOTIFY_CONTENT, messages.get(0)); +// } +// } + + private void initView(){ + mBottomEdit = findViewById(R.id.chat_bottom_edit); + mChatFragment = new ChatFragment(); + mEmotionFragment = new EmotionFragment(); + mGiftFragment = new GiftFragment(); + mEmotionFragment.setListener(new EmotionFragment.EmojiSelectListener() { + @Override + public void onSelected(String key) { + submitEmoji(key); + } + }); + + mChatFragment.setChatViewClickListener(new ChatFragment.ChatViewClickListener() { + @Override + public void onViewClicked(View v) { + mBottomEdit.dismissAllBottom(); + } + }); + + mBottomEdit.getEditText().addTextChangedListener(new TextWatcher() { + + private int start; + private int count; + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + this.start = start; + this.count = count; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void afterTextChanged(Editable s) { + MoonUtil.replaceEmoticons(ChatActivity.this, s, start, count); + } + }); + + mBottomEdit.setFunctionButtonClickListener(new BottomEdit.FunctionButtonClickListener() { + @Override + public void onClicked(int index) { + if(1 == index){ + startImageSelector(); + }else if(3 == index){ + + }else if(4 == index){ + Intent intent = new Intent(ChatActivity.this, + VideoActivity.class); + + intent.putExtra("toUid", Integer.parseInt(mChatFragment.getToAccount())); + intent.putExtra("skillId", 0); + intent.putExtra("isCaller", true); + startActivity(intent); + } + } + }); + + mSelector = MultiImageSelector.create().single(); + getGiftData(); + } + + public void startImageSelector(){ + mSelector.single(); + mSelector.start(this, SINGLE_SELECTOR_REQUEST); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if(requestCode == SINGLE_SELECTOR_REQUEST && resultCode == RESULT_OK){ + mChatFragment.submitImage(data. + getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT).get(0)); + } + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if(event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() != KeyEvent.ACTION_UP){ + mChatFragment.submitMessage(mBottomEdit.getEditText().getText().toString()); + mBottomEdit.getEditText().setText(""); + return true; + } + + return super.dispatchKeyEvent(event); + } + + public void submitEmoji(String key){ + Editable mEditable = mBottomEdit.getEditText().getText(); + if (key.equals("/DEL")) { + mBottomEdit.getEditText().dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + } else { + int start = mBottomEdit.getEditText().getSelectionStart(); + int end = mBottomEdit.getEditText().getSelectionEnd(); + start = (start < 0 ? 0 : start); + end = (start < 0 ? 0 : end); + mEditable.replace(start, end, key); + } + } + + private void getGiftData(){ + MainManager.getGiftBeans(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + mGiftFragment.setGiftListBean(result); + mGiftFragment.setOnGiftItemClickedListener(new GiftFragment.OnGiftItemClickedListener() { + @Override + public void onGiftClicked(final DialogGiftBean bean) { + mConfirmDialog = new BaseMessageDialog.Builder(ChatActivity.this) + .setMessage("确定赠送礼物?").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mConfirmDialog.dismiss(); + } + }).setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mConfirmDialog.dismiss(); + sendGift(Integer.parseInt(mChatFragment.getToAccount()), bean); + } + }).build(); + mConfirmDialog.show(); + } + + @Override + public void onWalletClicked() { + Intent intent = new Intent(ChatActivity.this, WalletActivity.class); + startActivity(intent); + } + }); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void sendGift(int toUid, final DialogGiftBean bean){ + MainManager.sendGift(this, 2, toUid, bean.getId(), 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, GiftListBean result, String message) { + mGiftFragment.setCoin(result.getCoin() + ""); + //mChatFragment.submitGift(bean); + + MaleToast.showMessage(ChatActivity.this, "赠送成功"); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(ChatActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(ChatActivity.this, "赠送失败"); + } + }); + } + + public void dismissInput(){ + mBottomEdit.dismissInput(); + } + + public void dismissVideo(){ + mBottomEdit.dimissVideo(); + } + + @Override + public void onDestroy(){ + super.onDestroy(); + if(null != mConfirmDialog && mConfirmDialog.isShowing()){ + mConfirmDialog.dismiss(); + } + } + /*@Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + View v = getCurrentFocus(); + if (v!=null&&(!(v instanceof EditText)||!(v instanceof AppCompatEditText))){ + mBottomEdit.dismissAllBottom(); + + } + } + + return super.onTouchEvent(event); + }*/ + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/ChatSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/ChatSettingActivity.java new file mode 100644 index 0000000..7efb4fa --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/ChatSettingActivity.java @@ -0,0 +1,288 @@ +package com.fengliyan.tianlesue.view.news.activity; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.Switch; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.news.manager.NewsManager; +import com.fengliyan.tianlesue.im.uikit.business.recent.RecentContactsFragment; +import com.fengliyan.tianlesue.im.uikit.business.session.helper.MessageListPanelHelper; +import com.fengliyan.tianlesue.im.uikit.business.uinfo.UserInfoHelper; +import com.fengliyan.tianlesue.im.uikit.common.CommonUtil; +import com.fengliyan.tianlesue.model.main.BlackBean; +import com.fengliyan.tianlesue.model.news.ChatSettingBean; +import com.fengliyan.tianlesue.model.news.ChatSettingInfoBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.ComplaintActivity; +import com.fengliyan.tianlesue.view.main.MainDynamicActivity; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; + +/** + * Created by zhangbin on 2019/2/19. + */ + +public class ChatSettingActivity extends BaseActivity implements View.OnClickListener { + + private int mUid; + private SimpleDraweeView mSetting_my_photo; + private TextView mPersonal_main_page_name; + private TextView mPersonal_main_page_age; + private TextView mPersonal_caicai_number; + private SimpleDraweeView[] mDynamicImages = new SimpleDraweeView[3]; + private RelativeLayout mDynamic_photo_layout; + private LinearLayout mLl_to_main_page; + private ChatSettingInfoBean mMainPageInfoBean; + private RelativeLayout mRl_complain; + private RelativeLayout mRl_clear_chat; + private BottomSelectiveDialog mSelectDialog; + private Switch mRl_top_switch; + private int mIs_black; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat_setting); + initTitle(); + mUid = getIntent().getIntExtra("userId", 0); + initView(); + getChatSettingData(mUid); + } + + private void initView() { + mSetting_my_photo = findViewById(R.id.setting_my_photo); + mPersonal_main_page_name = findViewById(R.id.personal_main_page_name); + mPersonal_main_page_age = findViewById(R.id.personal_main_page_age); + mPersonal_caicai_number = findViewById(R.id.personal_caicai_number); + mLl_to_main_page = findViewById(R.id.ll_to_main_page); + mDynamic_photo_layout = findViewById(R.id.personal_main_page_dynamic_photo_layout); + + mDynamicImages[0] = findViewById(R.id.personal_main_page_dynamic_photo_1); + mDynamicImages[1] = findViewById(R.id.personal_main_page_dynamic_photo_2); + mDynamicImages[2] = findViewById(R.id.personal_main_page_dynamic_photo_3); + + mRl_complain = findViewById(R.id.rl_complain); + mRl_clear_chat = findViewById(R.id.rl_clear_chat); + mRl_top_switch = findViewById(R.id.rl_top_switch); + + mRl_top_switch.setChecked(SPUtils.getBoolean(this, mUid + "", false)); + + mLl_to_main_page.setOnClickListener(this); + mDynamic_photo_layout.setOnClickListener(this); + mRl_complain.setOnClickListener(this); + mRl_clear_chat.setOnClickListener(this); + mRl_top_switch.setOnClickListener(this); + } + + private void getChatSettingData(int uid) { + NewsManager.getChatSetting(this, uid, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, ChatSettingBean result, String message) { + if (null != result) { + if (null != result.getInfo()) { + mMainPageInfoBean = result.getInfo(); + mSetting_my_photo.setImageURI(ConstUrl.IMAGE_URL + result.getInfo().getAvatar()); + mPersonal_main_page_name.setText(UserInfoHelper.getUserTitleName(mUid + "", SessionTypeEnum.P2P)); + mPersonal_main_page_age.setText(result.getInfo().getAge() + ""); + if (result.getInfo().getGender() == 1) { + mPersonal_main_page_age.setBackgroundResource(android.R.color.holo_red_light); + } + + mPersonal_caicai_number.setText("用户号:" + result.getInfo().getUsercode()); + } + + if (null != result.getDynamic()) { + if (result.getDynamic().size() == 0) { + mDynamic_photo_layout.setVisibility(View.GONE); + } else { + for (int i = 0; i < result.getDynamic().size(); i++) { + if (i < 3) { + String url = result.getDynamic().get(i); + mDynamicImages[i].setImageURI(ConstUrl.IMAGE_URL + url); + } + + } + } + } + + mIs_black = result.getIs_black(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private View mTitleView; + private View mBack; + private View mpPullBlack; + + private void initTitle() { + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(android.R.color.white); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.chat_setting_title, null); + mBack = mTitleView.findViewById(R.id.exchange_title_back); + mpPullBlack = mTitleView.findViewById(R.id.rl_chat_pull_black); + + mBack.setOnClickListener(this); + mpPullBlack.setOnClickListener(this); + + title.addViewTo(mTitleView, POSTION_CENTER); + } + + @Override + public void onClick(View view) { + if (view == mBack) { + finish(); + } else if (view == mpPullBlack) { + mSelectDialog = new BottomSelectiveDialog(this, R.style.SelectiveDialog); + String blackTitle = mIs_black != 1 ? "拉黑" : "取消拉黑"; + mSelectDialog.addSelectButton(blackTitle, + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectDialog.dismiss(); + pullBlack(); + } + }); + mSelectDialog.show(); + } else if (view == mLl_to_main_page) { + Intent intent = new Intent(this, MainPageActivity.class); + intent.putExtra("userId", mUid); + startActivity(intent); + } else if (view == mDynamic_photo_layout) { + if (mMainPageInfoBean != null) { + Intent intent = new Intent(this, MainDynamicActivity.class); + intent.putExtra("userId", mMainPageInfoBean.getUser_id()); + intent.putExtra("nickName", mMainPageInfoBean.getNickname()); + startActivity(intent); + } + } else if (view == mRl_complain) { + Intent intent = new Intent(this, ComplaintActivity.class); + intent.putExtra("uid", mUid + ""); + intent.putExtra("type", 4); + startActivity(intent); + } else if (view == mRl_clear_chat) { //清空聊天记录 + NIMClient.getService(MsgService.class).clearChattingHistory(mUid + "", SessionTypeEnum.P2P); + MaleToast.showMessage(this, "删除聊天记录成功"); + MessageListPanelHelper.getInstance().notifyClearMessages(mUid + ""); + } else if (view == mRl_top_switch) { //置顶聊天 + + //查询之前是不是存在会话记录 + RecentContact recentContact = NIMClient.getService(MsgService.class).queryRecentContact(mUid + "", SessionTypeEnum.P2P); + //置顶 + if (!SPUtils.getBoolean(this, mUid + "", false)) { + //如果之前不存在,创建一条空的会话记录 + if (recentContact == null) { + // RecentContactsFragment 的 MsgServiceObserve#observeRecentContact 观察者会收到通知 + NIMClient.getService(MsgService.class).createEmptyRecentContact(mUid + "", + SessionTypeEnum.P2P, + RecentContactsFragment.RECENT_TAG_STICKY, + System.currentTimeMillis(), + true); + } + // 之前存在,更新置顶flag + else { + CommonUtil.addTag(recentContact, RecentContactsFragment.RECENT_TAG_STICKY); + NIMClient.getService(MsgService.class).updateRecentAndNotify(recentContact); + } + + SPUtils.saveBoolean(this, mUid + "", true); + } + //取消置顶 + else { + if (recentContact != null) { + SPUtils.saveBoolean(this, mUid + "", false); + CommonUtil.removeTag(recentContact, RecentContactsFragment.RECENT_TAG_STICKY); + NIMClient.getService(MsgService.class).updateRecentAndNotify(recentContact); + } + } + } else if (view.getId() == R.id.rl_clear_remark) { + Intent intent = new Intent(this, RemarkSettingActivity.class); + intent.putExtra("userId", mUid); + startActivityForResult(intent, 100); + } + } + + /** + * 拉黑或者取消拉黑 + */ + private void pullBlack() { + MainManager.doBlack(this, mUid + "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BlackBean result, String message) { + if (null != result) { + String action = result.getAction(); + if (!TextUtils.isEmpty(action)) { + if (action.equals("add")) { + MaleToast.showMessage(ChatSettingActivity.this, "你已将对方拉黑"); + mIs_black = 1; + } else if (action.equals("delete")) { + MaleToast.showMessage(ChatSettingActivity.this, "取消拉黑"); + mIs_black = 0; + } + } + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "拉黑失败"); + } + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 100 && resultCode == 100) { + if (data != null) { + String s = data.getStringExtra("account"); + if (!TextUtils.isEmpty(s)) { + mPersonal_main_page_name.setText(s); + } else { + mPersonal_main_page_name.setText(UserInfoHelper.getUserTitleName(mUid + "", SessionTypeEnum.P2P)); + } + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/Fake2Activity.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/Fake2Activity.java new file mode 100644 index 0000000..71e715a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/Fake2Activity.java @@ -0,0 +1,18 @@ +package com.fengliyan.tianlesue.view.news.activity; + +import android.app.Activity; +import android.os.Bundle; + +/** + * Created by zhangbin on 2018/12/22. + */ + +public class Fake2Activity extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// setContentView(R.layout.activity_fake); +// String sdkVersion = RtcEngine.getSdkVersion(); +// Log.d("nail","sdkVersion===" + sdkVersion); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/FakeActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/FakeActivity.java new file mode 100644 index 0000000..6713e65 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/FakeActivity.java @@ -0,0 +1,30 @@ +package com.fengliyan.tianlesue.view.news.activity; + +import android.app.Activity; +import android.os.Bundle; +import androidx.annotation.Nullable; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.netease.nimlib.sdk.NimIntent; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.ArrayList; + +/** + * Created by zhangbin on 2018/12/7. + */ + +public class FakeActivity extends Activity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ArrayList messages = (ArrayList) getIntent().getSerializableExtra(NimIntent.EXTRA_NOTIFY_CONTENT); +// messages.get(0). +// P2PMessageActivity.start(this, messages.get(0).getFromAccount(), null, null); + if (null != messages && messages.size() > 0) { + NimUIKit.startP2PSession(this, messages.get(0).getFromAccount()); + } + finish(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/RemarkSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/RemarkSettingActivity.java new file mode 100644 index 0000000..5fa55a5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/activity/RemarkSettingActivity.java @@ -0,0 +1,105 @@ +package com.fengliyan.tianlesue.view.news.activity; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.EditText; + +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.news.manager.NewsManager; +import com.fengliyan.tianlesue.model.news.CustomRemarkBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +public class RemarkSettingActivity extends BaseActivity implements View.OnClickListener { + + private View mTitleView; + private View mTitleOk; + private View mTitleOn; + private int mUid; + private EditText mEdit; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mUid = getIntent().getIntExtra("userId", 0); + setContentView(R.layout.activity_remark); + initTitle(); + initView(); + initData(); + } + + private void initTitle() { + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(android.R.color.white); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.remark_setting_title, null); + mTitleOk = mTitleView.findViewById(R.id.remark_title_ok); + mTitleOn = mTitleView.findViewById(R.id.remark_title_on); + mTitleOk.setOnClickListener(this); + mTitleOn.setOnClickListener(this); + + title.addViewTo(mTitleView, POSTION_CENTER); + } + + private void initView() { + mEdit = findViewById(R.id.remark_edit); + } + + @Override + public void onClick(View v) { + if (v == mTitleOn) { + finishActivity(); + } else if (v == mTitleOk) { + final String trim = mEdit.getText().toString().trim(); + NewsManager.remark(this, mUid, trim, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { + MaleToast.showMessage(activity, "修改成功"); + Intent intent = new Intent(); + intent.putExtra("account", trim); + setResult(100, intent); + finishActivity(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + } + + public void initData() { + NewsManager.get_remark(this, mUid, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, CustomRemarkBean result, String message) { + mEdit.setText(result.getRemark()); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/ChatFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/ChatFragment.java new file mode 100644 index 0000000..b52a188 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/ChatFragment.java @@ -0,0 +1,341 @@ +package com.fengliyan.tianlesue.view.news.fragment; + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.fragment.app.Fragment; + +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.messaging.CustomAttachment; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.news.manager.ChatAdapter; +import com.fengliyan.tianlesue.controller.news.manager.NewsManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.news.ChatBean; +import com.fengliyan.tianlesue.model.news.IMCostBean; +import com.fengliyan.tianlesue.model.news.RecentContactBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.news.activity.ChatActivity; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.NimIntent; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class ChatFragment extends Fragment { + private List mChatBeanList = new ArrayList<>(); + private ChatAdapter mChatAdapter; + private LoadMoreListView mListView; + private RecentContactBean mRecentContactBean; + private ChatViewClickListener mChatViewClickListener; + private BaseMessageDialog mMessageDialog; + private int mIndex; + + public interface ChatViewClickListener{ + void onViewClicked(View v); + } + + public void setChatViewClickListener(ChatViewClickListener chatViewClickListener) { + this.mChatViewClickListener = chatViewClickListener; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState){ + View v = inflater.inflate(R.layout.fragment_chat, container, false); + mIndex = getActivity().getIntent().getIntExtra("index", 0); + mRecentContactBean = getActivity().getIntent().getParcelableExtra("RecentContactBean"); + if(null == mRecentContactBean){ +// getActivity().finish(); + mRecentContactBean = new RecentContactBean(); + ArrayList messages = (ArrayList) getActivity().getIntent().getSerializableExtra(NimIntent.EXTRA_NOTIFY_CONTENT); + if (null != messages && messages.size() > 0) { + IMMessage message = messages.get(0); + mRecentContactBean.setAccount(message.getFromAccount()); + mRecentContactBean.setUncheckedMessageId(message.getUuid()); + + List strings = new ArrayList<>(); + strings.add(message.getFromAccount()); + + NIMClient.getService(UserService.class).fetchUserInfo(strings).setCallback(new RequestCallback>() { + @Override + public void onSuccess(List param) { + String avatar = param.get(0).getAvatar(); + mRecentContactBean.setPhotoUrl(avatar); + } + + @Override + public void onFailed(int code) { + + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + + } + + initView(v); + + + if(null != UserManager.getGlobalConfigInfo() && (UserManager.getGlobalConfigInfo().getConfig().getServId().equals(getToAccount()) || + UserManager.getGlobalConfigInfo().getConfig().getSysId().equals(getToAccount()))){ + ((BaseActivity) getActivity()).setTitleName(mRecentContactBean.getName()); + + }else { + ((BaseActivity) getActivity()).setRightCustomImageTitle(mRecentContactBean.getName(), + R.drawable.ic_im_details, new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", Integer.parseInt(getToAccount())); + intent.putExtra("isFromChat", true); + intent.putExtra("index", mIndex); + if(NewFragment.RECENT_TAG_STICKY + == ChatManager.getInstance().getTag(getToAccount())){ + intent.putExtra("isOnTop", true); + } + + getActivity().startActivity(intent); + } + }); + } + + +// ChatManager.getInstance().getUnreadDataList(mRecentContactBean.getUncheckedMessageId(), +// mRecentContactBean.getUncheckedMessageCount()); +// mListView.setOnTouchListener(new View.OnTouchListener() { +// @Override +// public boolean onTouch(View view, MotionEvent event) { +// if (event.getAction() == MotionEvent.ACTION_DOWN) { +// View v = getActivity().getCurrentFocus(); +// if (v!=null&&(!(v instanceof EditText)||!(v instanceof AppCompatEditText))){ +// mChatViewClickListener.onViewClicked(v); +// +// } +// } +// +// return false; +// } +// }); + + mListView.dimissEmptyView(); + + if(null != UserManager.getGlobalConfigInfo() && (UserManager.getGlobalConfigInfo().getConfig().getServId().equals(getToAccount()) || + UserManager.getGlobalConfigInfo().getConfig().getSysId().equals(getToAccount()))){ + ((ChatActivity)getActivity()).dismissVideo(); + } + + if(null != UserManager.getGlobalConfigInfo() + && UserManager.getGlobalConfigInfo().getConfig().getSysId().equals(getToAccount())){ + ((ChatActivity)getActivity()).dismissInput(); + } + + return v; + } + + public String getToAccount(){ + return mRecentContactBean.getAccount(); + } + + private void initView(View v){ + mListView = v.findViewById(R.id.chat_list_view); + mChatAdapter = new ChatAdapter(getActivity()); + mChatAdapter.addChatBeanList(mChatBeanList); + mListView.setAdapter(mChatAdapter); + ChatManager.getInstance().setMessageReceivedListener(new ChatManager.MessageReceivedListener() { + @Override + public void onMessageReceived(List messages) { + Iterator iterator = messages.iterator(); + while (iterator.hasNext()){ + IMMessage message = iterator.next(); + if(!message.getFromAccount().equals(getToAccount()) + && !message.getFromAccount().equals(SPUtils.getInt(getActivity(), ConsUser.USER_ID) + "")){ + continue; + } + + ChatBean chatBean = new ChatBean(); + chatBean.setDatetime(message.getTime() + ""); + if(MsgTypeEnum.image == message.getMsgType()){ + chatBean.setType(1); + ImageAttachment attachment = (ImageAttachment) message.getAttachment(); + if(null != attachment) { + chatBean.setImageUrl(attachment.getUrl()); + } + + }else if(MsgTypeEnum.custom == message.getMsgType()){ + chatBean.setType(2); + CustomAttachment attachment = (CustomAttachment) message.getAttachment(); + chatBean.setCustomAttachment(attachment); + }else { + chatBean.setMessage(message.getContent()); + } + + if(message.getFromAccount().equals(mRecentContactBean.getAccount())){ + chatBean.setFromMe(false); + chatBean.setPhotoUrl(mRecentContactBean.getPhotoUrl()); + chatBean.setAccount(mRecentContactBean.getAccount()); + }else if(message.getFromAccount().equals(ChatManager.getInstance().getAccount())){ + chatBean.setFromMe(true); + chatBean.setPhotoUrl(UserManager.getUserInfo().getAvatar()); + chatBean.setAccount(ChatManager.getInstance().getAccount()); + } + + Map remoteExtensionMap = message.getRemoteExtension(); + Integer cost = null; + if(null != remoteExtensionMap) { + if(remoteExtensionMap.get("cut_coin") instanceof Integer) { + cost = (Integer) remoteExtensionMap.get("cut_coin"); + }else if(remoteExtensionMap.get("cut_coin") instanceof String){ + cost = Integer.parseInt((String) remoteExtensionMap.get("cut_coin")); + } + } + + if(null != cost){ + chatBean.setCost(cost); + } + + mChatBeanList.add(chatBean); + } + + mChatAdapter.addChatBeanList(mChatBeanList); + mChatAdapter.notifyDataSetChanged(); + } + }); + } + + private void imCost(final int type, final String content){ + NewsManager.sendIMCost((BaseActivity) getActivity(), type, + getToAccount(), content,"0", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, IMCostBean result, String message) { + mMessageDialog = new BaseMessageDialog.Builder(getActivity()) + .setMessage(UserManager.getUserInfo().getGender() == 2? "本条消息扣除" + + result.getCut_coin() + "金币,还剩" + result.getCoin()+"金币" + :"本条消息扣除" + result.getCut_coin() + + "金币,还剩" + result.getCoin()+"金币,通过真人认证私信免费哦!") + .setCancelable(true).setNegative("知道了") + .setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mMessageDialog.dismiss(); + } + }).setPositive("不再提醒") + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mMessageDialog.dismiss(); + StorageManager.getInstance(getActivity()) + .putInt("isDynamicNoticeCanceled", 1); + } + }).build(); + + if(result.getIs_cut() == 1 + && 1 != StorageManager.getInstance(getActivity()).getInt("isDynamicNoticeCanceled")) { + mMessageDialog.show(); + } + + if(type == 1) { + ChatManager.getInstance().sendTextWithCost(mRecentContactBean.getAccount(), + content, result.getCut_coin(), result.getIs_cut(), result.getCoin()); + + ChatBean chatBean = new ChatBean(); + chatBean.setFromMe(true); + chatBean.setDatetime(System.currentTimeMillis() + ""); + chatBean.setMessage(content); + chatBean.setPhotoUrl(UserManager.getUserInfo().getAvatar()); + chatBean.setAccount(SPUtils.getInt(getActivity(), ConsUser.USER_ID) + ""); + mChatBeanList.add(chatBean); + mChatAdapter.addChatBeanList(mChatBeanList); + mChatAdapter.notifyDataSetChanged(); + }else if(type == 3){ + ChatManager.getInstance().sendImage(getToAccount(), content); + ChatBean chatBean = new ChatBean(); + chatBean.setFromMe(true); + chatBean.setDatetime(System.currentTimeMillis() + ""); + chatBean.setImageUrl("file://" + content); + chatBean.setPhotoUrl(UserManager.getUserInfo().getAvatar()); + chatBean.setType(1); + chatBean.setAccount(SPUtils.getInt(getActivity(), ConsUser.USER_ID) + ""); + mChatBeanList.add(chatBean); + mChatAdapter.addChatBeanList(mChatBeanList); + mChatAdapter.notifyDataSetChanged(); + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onDestroy(){ + super.onDestroy(); + + } + + public void submitMessage(final String message){ + imCost(1, message); + } + + public void submitImage(final String imagePath){ + imCost(3, imagePath); + } + + /*public void submitGift(GiftBean giftBean){ + CustomGiftDataBean giftDataBean = new CustomGiftDataBean(); + giftDataBean.setGift_url(giftBean.getImg()); + giftDataBean.setGift_count("1"); + giftDataBean.setGift_name(giftBean.getName()); + giftDataBean.setGift_id(giftBean.getId()); + CustomBean customBean = new CustomBean(); + Gson gson = new Gson(); + List beans = new ArrayList<>(); + beans.add(giftDataBean); + String data = gson.toJson(beans); + customBean.setData(data); + customBean.setType(14); + String message = gson.toJson(customBean); + ChatManager.getInstance().sendGift(getToAccount(), message); + ChatBean chatBean = new ChatBean(); + chatBean.setFromMe(true); + chatBean.setDatetime(System.currentTimeMillis() + ""); + chatBean.setPhotoUrl(UserManager.getUserInfo().getAvatar()); + chatBean.setType(2); + chatBean.setMessage(message); + chatBean.setAccount(UserManager.getUserInfo().getUser_id()); + mChatBeanList.add(chatBean); + mChatAdapter.addChatBeanList(mChatBeanList); + mChatAdapter.notifyDataSetChanged(); + }*/ +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/ConversasionFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/ConversasionFragment.java new file mode 100644 index 0000000..67f67fa --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/ConversasionFragment.java @@ -0,0 +1,59 @@ +package com.fengliyan.tianlesue.view.news.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.recent.RecentContactsFragment; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.uikit.title.Title; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +/** + * Created by zhangbin on 2018/12/3. + * 会话列表 + */ + +public class ConversasionFragment extends RecentContactsFragment implements View.OnClickListener { + + private View mTitleView; + private View mNotice; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + initTitle(); + return super.onCreateView(inflater, container, savedInstanceState); + } + + private void initTitle(){ + Title title = ((BaseActivity)getActivity()).getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(R.drawable.shape_backgound); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(getActivity(), R.layout.item_news_title, null); + mNotice = mTitleView.findViewById(R.id.news_title_notice); + mNotice.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + } + + @Override + public void onClick(View view) { + if (view == mNotice) { +// NimUIKit.startP2PSession(getActivity(), UserManager.getGlobalConfigInfo().getConfig().getSysId()); + NimUIKit.startP2PSession(getActivity(), "2"); + } + } + + @Override + public void onHiddenChanged(boolean hidden) { + if (!hidden) { + initTitle(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/EmotionFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/EmotionFragment.java new file mode 100644 index 0000000..727c868 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/EmotionFragment.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.view.news.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.fragment.app.Fragment; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.uikit.emoji.IEmoticonSelectedListener; +import com.fengliyan.uikit.emoji.view.EmoticonPickerView; + +public class EmotionFragment extends Fragment { + private EmoticonPickerView mEmoticonPickerView; + private EmojiSelectListener mListener; + public interface EmojiSelectListener{ + void onSelected(String key); + } + + public void setListener(EmojiSelectListener listener) { + this.mListener = listener; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_emoji, container, false); + initView(v); + return v; + } + + private void initView(View v){ + mEmoticonPickerView = v.findViewById(R.id.emoji_view); + mEmoticonPickerView.show(new IEmoticonSelectedListener() { + @Override + public void onEmojiSelected(String key) { + if(null != mListener){ + mListener.onSelected(key); + } + } + + @Override + public void onStickerSelected(String categoryName, String stickerName) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/GiftFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/GiftFragment.java new file mode 100644 index 0000000..a83bc6e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/GiftFragment.java @@ -0,0 +1,79 @@ +package com.fengliyan.tianlesue.view.news.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.uikit.dialog.DialogGiftBean; +import com.fengliyan.uikit.dialog.GiftListBean; +import com.fengliyan.uikit.dialog.GiftPagesManager; + +public class GiftFragment extends Fragment { + private ViewPager mViewPager; + private LinearLayout mViewGroup; + private TextView mCaiBiText; + private View mCaiBiLayout; + private Button mSendButton; + private GiftListBean mGiftListBean; + private GiftPagesManager mGiftManager; + private OnGiftItemClickedListener mGiftListener; + public interface OnGiftItemClickedListener{ + void onGiftClicked(DialogGiftBean bean); + void onWalletClicked(); + } + + public void setOnGiftItemClickedListener(OnGiftItemClickedListener listener){ + mGiftListener = listener; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.dialog_gift, container, false); + initView(v); + return v; + } + private void initView(View v){ + mViewPager = v.findViewById(com.fengliyan.uikit.R.id.gift_pager); + mViewGroup = v.findViewById(com.fengliyan.uikit.R.id.gift_view_group); + mCaiBiText = v.findViewById(com.fengliyan.uikit.R.id.gift_shell_number); + mCaiBiLayout = v.findViewById(com.fengliyan.uikit.R.id.gift_shell_layout); + mSendButton = v.findViewById(com.fengliyan.uikit.R.id.gift_button); + mCaiBiText.setText(mGiftListBean.getCoin() + ""); + mGiftManager = new GiftPagesManager(mViewPager, mViewGroup, getActivity()); + mGiftManager.addGiftBean(mGiftListBean.getGift_list()); + mGiftManager.manage(); + mGiftManager.setOnGiftItemClickedListener(new GiftPagesManager.OnGiftItemClickedListener() { + @Override + public void onGiftClicked(DialogGiftBean bean) { + if(null != mGiftListener){ + mGiftListener.onGiftClicked(bean); + } + } + }); + + mCaiBiLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if(null != mGiftListener){ + mGiftListener.onWalletClicked(); + } + } + }); + } + + public void setCoin(String coin){ + mCaiBiText.setText(coin); + } + public void setGiftListBean(GiftListBean bean){ + mGiftListBean = bean; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/MainMessageFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/MainMessageFragment.java new file mode 100644 index 0000000..dbd9ada --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/MainMessageFragment.java @@ -0,0 +1,292 @@ +package com.fengliyan.tianlesue.view.news.fragment; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.blankj.utilcode.util.TimeUtils; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.recent.RecentContactsFragment; +import com.fengliyan.tianlesue.model.settings.SignDataListBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.settings.MemberActivity; +import com.fengliyan.tianlesue.view.settings.MissionActivity; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.title.Title; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/27. + */ + +public class MainMessageFragment extends Fragment implements View.OnClickListener { + + private View mTitleView; + private TextView mTitleText1; + private TextView mTitleText2; + private ImageView mTitleBottom1; + private ImageView mTitleBottom2; + private View mTitleTag1; + private View mTitleTag2; + private View mTitlePost; + private ImageView title_clear_unread; + private ViewPager mMainViewPager; + private LinearLayout lin_msg_vip; + private TextView tv_msg_vip_time; + private LinearLayout lin_msg_sign; + private TextView tv_msg_sign_in; + private List mChannelFragments = new ArrayList<>(); + private MainViewPagerAdapter mViewPagerAdapter; + private ConversasionFragment mConversasionFragment; + private VideoRecordFragment mVideoRecordFragment; + private int mIndex; + private RecentContactsFragment mRecentContactsFragment; + private CountDownTimer mVipCountDownTimer = null; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_message_view_pager, container, false); + initTitle(); + initView(v); + return v; + } + + private boolean isFirst = true; + private boolean isSignIn = true; + + @Override + public void onHiddenChanged(boolean hidden) { + if (!hidden) { + initTitle(); + viewPagerChange(mIndex); + if (UserManager.getUserInfo().getGender() == 2) { + if (isSignIn) { + isSignIn = false; + signData(); + } + } else { + lin_msg_sign.setVisibility(View.INVISIBLE); + } + + if (isFirst) { + isFirst = false; + if (UserManager.getUserInfo().getGender() == 2 && !SPUtils.getBoolean(getContext(), ConsUser.USER_VIP, false)) { + if (mVipCountDownTimer != null) { + mVipCountDownTimer.cancel(); + } + mVipCountDownTimer = new CountDownTimer(60_000 * 10, 1000) { + @Override + public void onTick(long millisUntilFinished) { + tv_msg_vip_time.setText(TimeUtils.millis2String(millisUntilFinished, "mm:ss")); + } + + @Override + public void onFinish() { + lin_msg_vip.setVisibility(View.GONE); + } + + }; + lin_msg_vip.setVisibility(View.VISIBLE); + mVipCountDownTimer.start(); + } else { + lin_msg_vip.setVisibility(View.GONE); + } + } + } + } + + public void signData() { + SettingManager.signData((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SignDataListBean result, String message) { + isSignIn = true; + if (result != null && !StrU.isEmpty(result.getSign_day()) && result.getSign_info() != null && result.getSign_info().size() > 0) { + lin_msg_sign.setVisibility(View.VISIBLE); + //按钮状态0去充值1立即签到2已签到 + switch (result.getButton_status()) { + case 0: + tv_msg_sign_in.setText("去充值"); + break; + case 1: + tv_msg_sign_in.setText("立即签到"); + break; + case 2: + tv_msg_sign_in.setText("已签到"); + lin_msg_sign.setVisibility(View.INVISIBLE); + break; + } + } else { + lin_msg_sign.setVisibility(View.INVISIBLE); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + isSignIn = true; + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + isSignIn = true; + } + }); + } + + private void initTitle() { + Title title = ((BaseActivity) getActivity()).getCustomTitle(); + title.setVisibility(View.VISIBLE); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(getActivity(), R.layout.item_main_message_title, null); + mTitleTag1 = mTitleView.findViewById(R.id.title_view_1); + mTitleTag2 = mTitleView.findViewById(R.id.title_view_2); + mTitleText1 = mTitleView.findViewById(R.id.title_name_1); + mTitleText2 = mTitleView.findViewById(R.id.title_name_2); + mTitleBottom1 = mTitleView.findViewById(R.id.title_bottom_line_1); + mTitleBottom2 = mTitleView.findViewById(R.id.title_bottom_line_2); + mTitlePost = mTitleView.findViewById(R.id.title_post); + title_clear_unread = mTitleView.findViewById(R.id.title_clear_unread); + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + mTitlePost.setOnClickListener(this); + title_clear_unread.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + } + + private void initView(View v) { + mMainViewPager = v.findViewById(R.id.dynamic_view_pager); + lin_msg_vip = v.findViewById(R.id.lin_msg_vip); + tv_msg_vip_time = v.findViewById(R.id.tv_msg_vip_time); + lin_msg_sign = v.findViewById(R.id.lin_msg_sign); + tv_msg_sign_in = v.findViewById(R.id.tv_msg_sign_in); + mRecentContactsFragment = new RecentContactsFragment(); + mVideoRecordFragment = new VideoRecordFragment(); + mChannelFragments.add(mRecentContactsFragment); + mChannelFragments.add(mVideoRecordFragment); + + lin_msg_vip.setOnClickListener(this); + lin_msg_sign.setOnClickListener(this); + mViewPagerAdapter = new MainViewPagerAdapter(getChildFragmentManager(), + mChannelFragments); + + mMainViewPager.setAdapter(mViewPagerAdapter); + viewPagerChange(0); + + mMainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPagerAdapter.notifyDataSetChanged(); + mMainViewPager.setCurrentItem(0); + } + + private void viewPagerChange(int index) { + mIndex = index; + switch (index) { + case 0: + mTitleText1.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mTitleBottom1.setVisibility(View.VISIBLE); + + mTitleText2.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom2.setVisibility(View.GONE); + break; + case 1: + mTitleText2.setTextColor(ContextCompat.getColor(getActivity(), R.color.one_text)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + mTitleBottom2.setVisibility(View.VISIBLE); + + mTitleText1.setTextColor(ContextCompat.getColor(getActivity(), R.color.grey_text)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleBottom1.setVisibility(View.GONE); + break; + } + } + + private BaseMessageDialog clearUnreadDialog; + + @Override + public void onClick(View view) { + if (view == mTitleTag1) { + mMainViewPager.setCurrentItem(0); + } else if (view == mTitleTag2) { + mMainViewPager.setCurrentItem(1); + } else if (view == mTitlePost) { + NimUIKit.startP2PSession(getActivity(), "2"); + } else if (view == title_clear_unread) { + clearUnreadDialog = new BaseMessageDialog.Builder(getContext()).setTitle("温馨提示").setMessage("消息气泡会清除,但消息不会丢失").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + clearUnreadDialog.dismiss(); + } + }).setPositive("确定").setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + NIMClient.getService(MsgService.class).clearAllUnreadCount(); + clearUnreadDialog.dismiss(); + } + }).build(); + clearUnreadDialog.show(); + } else if (view == lin_msg_vip) { + Intent intent = new Intent(getActivity(), MemberActivity.class); + intent.putExtra("index", 0); + startActivity(intent); + } else if (view == lin_msg_sign) { + Intent intent = new Intent(getActivity(), MissionActivity.class); + startActivity(intent); +// SignInDialog dialog = new SignInDialog((BaseActivity) getActivity(), ""); +// dialog.show(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/NewFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/NewFragment.java new file mode 100644 index 0000000..4b065bd --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/NewFragment.java @@ -0,0 +1,265 @@ +package com.fengliyan.tianlesue.view.news.fragment; + +import android.content.Intent; +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.news.manager.NewAdapter; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.news.RecentContactBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.messaging.ChatManager; +import com.fengliyan.messaging.CustomAttachment; +import com.fengliyan.messaging.SysInfoDoubleImageAttachment; +import com.fengliyan.messaging.SysInfoSingleImageAttachment; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.tianlesue.view.news.activity.ChatActivity; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.netease.nimlib.sdk.uinfo.model.UserInfo; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +/** + * Created by abby on 2018/4/22. + */ +@Deprecated +public class NewFragment extends Fragment implements View.OnClickListener { + public static final long RECENT_TAG_STICKY = 1; + private LoadMoreListView mListView; + private NewAdapter mNewsAdapter; + private View mNotice; + private View mTitleView; + private Map mRecentContactBeans = new HashMap<>(); + private List mRecentContactList = new ArrayList<>(); + private BottomSelectiveDialog mSelectiveDialog; + private Disposable mDisponsable; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState){ + View v = inflater.inflate(R.layout.fragment_news, container, false); + initTitle(); + getRecentContactList(); + initView(v); + + return v; + } + + @Override + public void onHiddenChanged(boolean hidden) { + if (!hidden) { + initTitle(); + } + } + + private void initView(View v){ + mSelectiveDialog = new BottomSelectiveDialog(getActivity(), R.style.SelectiveDialog); + mListView = (LoadMoreListView)v.findViewById(R.id.news_list_view); + mNewsAdapter = new NewAdapter(getActivity()); + mNewsAdapter.addContactList(mRecentContactList); + mNewsAdapter.setOnLongClickListener(new NewAdapter.OnLongClickListener() { + @Override + public void onLongClicked(View v, final int clickIndex) { + mSelectiveDialog.addSelectButton("删除", + new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + ChatManager.getInstance() + .deleteRecentContact(mRecentContactList + .get(clickIndex).getAccount()); + + mRecentContactList.remove(clickIndex); + mNewsAdapter.notifyDataSetChanged(); + } + }); + + mSelectiveDialog.show(); + } + + @Override + public void onClick(View v, int index) { + RecentContactBean bean = mRecentContactList.get(index); + Intent intent = new Intent(getActivity(), ChatActivity.class); + intent.putExtra("RecentContactBean", bean); + intent.putExtra("index", index); + startActivity(intent); +// ChatManager.getInstance().clearUnreadCount(bean.getAccount()); + } + }); + + mListView.setAdapter(mNewsAdapter); + ChatManager.getInstance().setRecentContactQueryListener(new ChatManager + .RecentContactQueryListener() { + @Override + public void onQueryResultReceived(List recents, + Map userInfoMap) { + mRecentContactBeans.clear(); + mRecentContactList.clear(); + for(RecentContact recentContact : recents){ + int unreadCount = recentContact.getUnreadCount(); + long dateTime = recentContact.getTime(); + String account = recentContact.getContactId(); + String message = null; + if(MsgTypeEnum.custom == recentContact.getMsgType()){ + CustomAttachment attachment = (CustomAttachment) recentContact.getAttachment(); + if(14 == attachment.getType()){ + message = "[礼物]"; + }else if(13 == attachment.getType()){ + SysInfoDoubleImageAttachment sysInfoDoubleImageAttachment + = (SysInfoDoubleImageAttachment) attachment; + + if(null != sysInfoDoubleImageAttachment.getImageList() + && sysInfoDoubleImageAttachment.getImageList().size() != 0) { + message = sysInfoDoubleImageAttachment.getImageList().get(0).getTitle(); + } + }else if(12 == attachment.getType()){ + SysInfoSingleImageAttachment sysInfoSingleImageAttachment + = (SysInfoSingleImageAttachment) attachment; + + if(sysInfoSingleImageAttachment.getAct_type() == 1){ + message = sysInfoSingleImageAttachment.getAct_string(); + }else{ + message = sysInfoSingleImageAttachment.getTitle(); + } + }else if(11 == attachment.getType()){ +// SysInfoTextAttachment sysInfoTextAttachment +// = (SysInfoTextAttachment) attachment; +// +// message = sysInfoTextAttachment.getTitle(); + } + }else { + message = recentContact.getContent(); + } + + String messageId = recentContact.getRecentMessageId(); + UserInfo userInfo = userInfoMap.get(account); + String name = userInfo.getName(); + String photoUrl = userInfo.getAvatar(); + RecentContactBean bean = new RecentContactBean(); + bean.setAccount(userInfo.getAccount()); + bean.setDate(dateTime + ""); + bean.setName(name); + bean.setPhotoUrl(photoUrl); + bean.setRecentMessage(message); + bean.setUncheckedMessageCount(unreadCount); + bean.setUncheckedMessageId(messageId); + mRecentContactBeans.put(bean.getAccount(), bean); + mRecentContactList.add(bean); +// ((MainActivity)getActivity()) +// .setNewsCount(ChatManager.getInstance().getTotalUnreadCount()); + } + mNewsAdapter.notifyDataSetChanged(); + } + }); + + + mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + RecentContactBean bean = mRecentContactList.get(i); + Intent intent = new Intent(getActivity(), ChatActivity.class); + intent.putExtra("RecentContactBean", bean); + intent.putExtra("index", i); + startActivity(intent); +// ChatManager.getInstance().clearUnreadCount(bean.getAccount()); + } + }); + + UserManager.getInstance().registerUserInfoObserver(new Observer() { + @Override + public void onSubscribe(Disposable d) { + mDisponsable = d; + } + + @Override + public void onNext(BaseUserInfo userInfo) { + if(null != userInfo && 0 == userInfo.getUser_id()){ + return; + } + + getRecentContactList(); + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + + } + }); + } + + private void initTitle(){ + Title title = ((BaseActivity)getActivity()).getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(R.drawable.shape_backgound); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(getActivity(), R.layout.item_news_title, null); + mNotice = mTitleView.findViewById(R.id.news_title_notice); + mNotice.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + } + + private void getRecentContactList(){ +// ChatManager.getInstance().registerMessageObserver(); + ChatManager.getInstance().registerRecentContactsObserver(); + ChatManager.getInstance().queryRecentContacts(); + } + + @Override + public void onClick(View view) { + if(view == mNotice){ + RecentContactBean bean = null; + if(mRecentContactBeans.containsKey(UserManager.getGlobalConfigInfo().getConfig().getSysId())){ + bean = mRecentContactBeans.get(UserManager.getGlobalConfigInfo().getConfig().getSysId()); + }else { + bean = new RecentContactBean(); + bean.setAccount(UserManager.getGlobalConfigInfo().getConfig().getSysId()); + bean.setDate("18岁"); + bean.setName("系统通知"); + bean.setPhotoUrl(""); + bean.setUncheckedMessageCount(0); + bean.setUncheckedMessageId(0 + ""); + } + + Intent intent = new Intent(getActivity(), ChatActivity.class); + intent.putExtra("RecentContactBean", bean); + getActivity().startActivity(intent); + } + } + + @Override + public void onDestroy(){ + super.onDestroy(); + if(null !=mSelectiveDialog && mSelectiveDialog.isShowing()){ + mSelectiveDialog.dismiss(); + } + + if(null != mDisponsable && !mDisponsable.isDisposed()){ + mDisponsable.dispose(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/VideoRecordFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/VideoRecordFragment.java new file mode 100644 index 0000000..8972d80 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/fragment/VideoRecordFragment.java @@ -0,0 +1,107 @@ +package com.fengliyan.tianlesue.view.news.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.VideoRecordAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.VideoRecordBean; +import com.fengliyan.tianlesue.model.settings.VideoRecordListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.refresh.LoadMoreListView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/28. + * 通话记录 + */ + +public class VideoRecordFragment extends Fragment { + + private LoadMoreListView mListView; + private int mPage = 1; + private VideoRecordAdapter mAdapter; + private List mListBeans = new ArrayList<>(); + private boolean mPageLoad; + private SwipeRefreshLayout mChannelRefresh; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.activity_video_record, container, false); + initView(v); + getData(mPage); + return v; + } + + private void getData(final int page) { + SettingManager.getVideoRecordList((BaseActivity) getActivity(), page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, VideoRecordBean result, String message) { + if (page == 1) { + mListBeans.clear(); + } + mListBeans.addAll(result.getList()); + mAdapter.notifyDataSetChanged(); + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + private void initView(View v) { + mListView = v.findViewById(R.id.video_record_list_view); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mAdapter = new VideoRecordAdapter(getActivity()); + mAdapter.setData(mListBeans); + mListView.setAdapter(mAdapter); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if(mListBeans.size() != 0 && mListBeans.size() % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mListBeans.size() - 2){ + getData(mPage); + mPageLoad = true; + }else if(mListView.getLastVisiblePosition() <= mListBeans.size() - 2){ + mPageLoad = false; + } + + } + }); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getData(mPage); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/DefaultMessageAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/DefaultMessageAdapter.java new file mode 100644 index 0000000..2b1f32e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/DefaultMessageAdapter.java @@ -0,0 +1,117 @@ +package com.fengliyan.tianlesue.view.news.im; + +import android.content.Context; +import androidx.recyclerview.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/1/18. + */ + +public class DefaultMessageAdapter extends RecyclerView.Adapter { + + private List defaultMessageList = new ArrayList<>(); + private Context mContext; + private int type; + + public DefaultMessageAdapter(Context context) { + mContext = context; + } + + public void setData(List defaultMessageList) { + this.defaultMessageList = defaultMessageList; + } + + public void setType(int type) { + this.type = type; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = View.inflate(mContext, R.layout.item_default_message, null); + RecyclerView.ViewHolder holder = new DefaultMessageHolder(view); + return holder; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + DefaultMessageHolder messageHolder = (DefaultMessageHolder) holder; + messageHolder.tvDefaultMesssage.setText(defaultMessageList.get(position)); + + if (type == 0) { + messageHolder.ivTextDelete.setVisibility(View.GONE); + messageHolder.ivTextEdit.setVisibility(View.GONE); + }else if (type == 1) { + messageHolder.ivTextDelete.setVisibility(View.VISIBLE); + messageHolder.ivTextEdit.setVisibility(View.VISIBLE); + } + + messageHolder.ivTextEdit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mOnClickItem) { + mOnClickItem.onClickTextEdit(position); + } + } + }); + + messageHolder.ivTextDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mOnClickItem) { + mOnClickItem.onClickTextDetele(position); + } + } + }); + + messageHolder.mItemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (null != mOnClickItem) { + mOnClickItem.onClickItem(defaultMessageList.get(position)); + } + } + }); + } + + @Override + public int getItemCount() { + return defaultMessageList == null ? 0 : defaultMessageList.size(); + } + + class DefaultMessageHolder extends RecyclerView.ViewHolder { + + private TextView tvDefaultMesssage; + private ImageView ivTextEdit; + private ImageView ivTextDelete; + private View mItemView; + + public DefaultMessageHolder(View itemView) { + super(itemView); + tvDefaultMesssage = itemView.findViewById(R.id.tv_message); + ivTextEdit = itemView.findViewById(R.id.iv_text_edit); + ivTextDelete = itemView.findViewById(R.id.iv_text_delete); + this.mItemView = itemView; + } + } + + private onClickItem mOnClickItem; + + public void setOnClickItem(onClickItem onClickItem) { + mOnClickItem = onClickItem; + } + + public interface onClickItem { + void onClickTextDetele(int position); + void onClickTextEdit(int position); + void onClickItem(String text); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/DemoCache.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/DemoCache.java new file mode 100644 index 0000000..2101cbc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/DemoCache.java @@ -0,0 +1,64 @@ +package com.fengliyan.tianlesue.view.news.im; + +import android.content.Context; + +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.netease.nimlib.sdk.StatusBarNotificationConfig; + +/** + * Created by jezhee on 2/20/15. + */ +public class DemoCache { + + private static Context context; + + private static String account; + + private static StatusBarNotificationConfig notificationConfig; + + public static void clear() { + account = null; + } + + public static String getAccount() { + return account; + } + + private static boolean mainTaskLaunching; + + public static void setAccount(String account) { + DemoCache.account = account; + NimUIKit.setAccount(account); +// AVChatKit.setAccount(account); +// RTSKit.setAccount(account); + } + + public static void setNotificationConfig(StatusBarNotificationConfig notificationConfig) { + DemoCache.notificationConfig = notificationConfig; + } + + public static StatusBarNotificationConfig getNotificationConfig() { + return notificationConfig; + } + + public static Context getContext() { + return context; + } + + public static void setContext(Context context) { + DemoCache.context = context.getApplicationContext(); + +// AVChatKit.setContext(context); +// RTSKit.setContext(context); + } + + public static void setMainTaskLaunching(boolean mainTaskLaunching) { + DemoCache.mainTaskLaunching = mainTaskLaunching; + +// AVChatKit.setMainTaskLaunching(mainTaskLaunching); + } + + public static boolean isMainTaskLaunching() { + return mainTaskLaunching; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/ImUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/ImUtils.java new file mode 100644 index 0000000..d41ab2e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/ImUtils.java @@ -0,0 +1,46 @@ +package com.fengliyan.tianlesue.view.news.im; + +import android.content.Context; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.controller.news.manager.NewsManager; +import com.fengliyan.tianlesue.model.news.IMCostBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; + +public class ImUtils { + + public static void sendTextImMessage(Context context,String sessionID, String text) { + NIMClient.getService(MsgService.class).sendMessage(MessageBuilder.createTextMessage(sessionID, SessionTypeEnum.P2P, text), false); + MaleToast.showMessage(context, "打招呼成功"); + } + + /** + * 打招呼 + */ + public static void sendIMHello(final Context context, final String sessionID) { + NewsManager.sendIMHello((BaseActivity) context, sessionID, "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, IMCostBean result, String message) { + if (result.getFilter() == 0) { + ImUtils.sendTextImMessage(context, sessionID, result.getContent()); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "打招呼失败"); + } + }); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/AttentionFansHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/AttentionFansHolder.java new file mode 100644 index 0000000..cd44e59 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/AttentionFansHolder.java @@ -0,0 +1,141 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.messaging.AttentionAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +/** + * Created by zhangbin on 2019/1/10. + */ + +public class AttentionFansHolder extends MsgViewHolderBase implements View.OnClickListener { + + private SimpleDraweeView mSv_attention_avatar; + private TextView mTv_attention_name; + private TextView mTv_attention_site; + private TextView mTv_attention_time; + private AttentionAttachment mAttentionAttachment; + private TextView tv_attention_btn; + + public AttentionFansHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.sys_attention_fans_info; + } + + @Override + protected void inflateContentView() { + RelativeLayout.LayoutParams frameLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + frameLayout.topMargin = 0; + frameLayout.leftMargin = 0; + frameLayout.rightMargin = 0; + frameLayout.bottomMargin = 0; + contentContainer.setLayoutParams(frameLayout); + mSv_attention_avatar = view.findViewById(R.id.sv_attention_avatar); + mTv_attention_name = view.findViewById(R.id.tv_attention_name); + mTv_attention_site = view.findViewById(R.id.tv_attention_site); + tv_attention_btn = view.findViewById(R.id.tv_attention_btn); + mTv_attention_time = view.findViewById(R.id.tv_attention_time); + } + + @Override + protected void bindContentView() { + if (message.getAttachment() == null) { + return; + } + mAttentionAttachment = (AttentionAttachment) message.getAttachment(); + switch (mAttentionAttachment.getType()) { + case 16: + mSv_attention_avatar.setImageURI(ConstUrl.IMAGE_URL + mAttentionAttachment.getAvatar()); + mTv_attention_name.setText(mAttentionAttachment.getNickname()); +// mTv_attention_site.setText(mAttentionAttachment.getCity()); + mTv_attention_time.setText(mAttentionAttachment.getTime()); + + mSv_attention_avatar.setOnClickListener(this); + mTv_attention_name.setOnClickListener(this); + tv_attention_btn.setOnClickListener(this); + break; + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.sv_attention_avatar: + case R.id.tv_attention_name: + case R.id.tv_attention_btn: + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", mAttentionAttachment.getUserid()); + context.startActivity(intent); + break; + } + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + @Override + protected boolean isShowTime() { + return false; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/DynamicHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/DynamicHolder.java new file mode 100644 index 0000000..40f8fc7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/DynamicHolder.java @@ -0,0 +1,265 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.content.Intent; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.messaging.DynamicAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.utils.ToolKit; +import com.fengliyan.tianlesue.view.dynamics.activity.DynamicDetailActivity; +import com.fengliyan.tianlesue.view.main.MainDynamicActivity; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +/** + * Created by zhangbin on 2019/1/10. + * 关注的人发布动态自定义通知 + */ + +public class DynamicHolder extends MsgViewHolderBase implements View.OnClickListener { + private ConstraintLayout mLlDynamic; + private SimpleDraweeView sv_avatar; + private TextView tv_dynamic_name; + private TextView tv_dynamic_desc; + private TextView tv_dynamic_time; + private TextView tv_dynamic_content; + private SimpleDraweeView sv_dynamic_img; + private TextView tv_dynamic_jump; + private DynamicAttachment dynamicAttachment; + + public DynamicHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.sys_dynamic_info; + } + + @Override + protected void inflateContentView() { + RelativeLayout.LayoutParams frameLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + frameLayout.topMargin = 0; + frameLayout.leftMargin = 0; + frameLayout.rightMargin = 0; + frameLayout.bottomMargin = 0; + contentContainer.setLayoutParams(frameLayout); + mLlDynamic = view.findViewById(R.id.ll_dynamic); + sv_avatar = view.findViewById(R.id.sv_avatar); + tv_dynamic_name = view.findViewById(R.id.tv_dynamic_name); + tv_dynamic_desc = view.findViewById(R.id.tv_dynamic_desc); + tv_dynamic_time = view.findViewById(R.id.tv_dynamic_time); + tv_dynamic_content = view.findViewById(R.id.tv_dynamic_content); + sv_dynamic_img = view.findViewById(R.id.sv_dynamic_img); + tv_dynamic_jump = view.findViewById(R.id.tv_dynamic_jump); + } + + @Override + protected void bindContentView() { + if (message.getAttachment() == null) { + return; + } + dynamicAttachment = (DynamicAttachment) message.getAttachment(); + switch (dynamicAttachment.getType()) { + case 17: + if (!TextUtils.isEmpty(dynamicAttachment.getAvatar())) { + sv_avatar.setImageURI(ConstUrl.IMAGE_URL + dynamicAttachment.getAvatar()); + sv_avatar.setVisibility(View.VISIBLE); + } else { + sv_avatar.setVisibility(View.GONE); + } + tv_dynamic_name.setText(dynamicAttachment.getNickname()); + tv_dynamic_content.setText(dynamicAttachment.getTitle()); + tv_dynamic_desc.setText("Ta发布了动态"); + + tv_dynamic_time.setText(ToolKit.parseTime(message.getTime() + "")); + if (!TextUtils.isEmpty(dynamicAttachment.getImage())) { + sv_dynamic_img.setVisibility(View.VISIBLE); + sv_dynamic_img.setImageURI(ConstUrl.IMAGE_URL + dynamicAttachment.getImage()); + } else { + sv_dynamic_img.setVisibility(View.GONE); + } + tv_dynamic_jump.setVisibility(View.GONE); + sv_avatar.setOnClickListener(this); + tv_dynamic_name.setOnClickListener(this); + + mLlDynamic.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(context, MainDynamicActivity.class); + intent.putExtra("userId", dynamicAttachment.getUserid()); + intent.putExtra("nickName", dynamicAttachment.getNickname()); + context.startActivity(intent); + } + }); + break; + case 24://点赞 + if (!TextUtils.isEmpty(dynamicAttachment.getAvatar())) { + sv_avatar.setImageURI(ConstUrl.IMAGE_URL + dynamicAttachment.getAvatar()); + sv_avatar.setVisibility(View.VISIBLE); + } else { + sv_avatar.setVisibility(View.GONE); + } + tv_dynamic_name.setText(dynamicAttachment.getNickname()); + Log.i("TAG", "bindContentView: ------->" + dynamicAttachment.getDynamic_content()); + tv_dynamic_content.setText(dynamicAttachment.getDynamic_content()); + tv_dynamic_desc.setText("Ta" + dynamicAttachment.getType_desc()); + tv_dynamic_time.setText(ToolKit.parseTime(dynamicAttachment.getTime() + "000")); + if (!TextUtils.isEmpty(dynamicAttachment.getDynamic_url())) { + sv_dynamic_img.setVisibility(View.VISIBLE); + sv_dynamic_img.setImageURI(ConstUrl.IMAGE_URL + dynamicAttachment.getDynamic_url()); + } else { + sv_dynamic_img.setVisibility(View.GONE); + } + + if (SPUtils.getInt(context, ConsUser.DYNAMICS_TYPE) == 24) { + tv_dynamic_jump.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(context, R.drawable.ic_dynamic_like), null, null, null); + tv_dynamic_jump.setVisibility(View.VISIBLE); + tv_dynamic_jump.setText("私信"); + tv_dynamic_content.setVisibility(View.GONE); + tv_dynamic_jump.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + NimUIKit.startP2PSession(context, dynamicAttachment.getUserid() + ""); + } + }); + } + sv_avatar.setOnClickListener(this); + tv_dynamic_name.setOnClickListener(this); + + mLlDynamic.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(context, DynamicDetailActivity.class); + intent.putExtra("dynamic_id", dynamicAttachment.getDynamic_id()); + context.startActivity(intent); + } + }); + break; + case 26://评论 + if (!TextUtils.isEmpty(dynamicAttachment.getAvatar())) { + sv_avatar.setImageURI(ConstUrl.IMAGE_URL + dynamicAttachment.getAvatar()); + sv_avatar.setVisibility(View.VISIBLE); + } else { + sv_avatar.setVisibility(View.GONE); + } + tv_dynamic_name.setText(dynamicAttachment.getNickname()); + tv_dynamic_content.setText(dynamicAttachment.getComment_content()); + tv_dynamic_desc.setText("Ta" + dynamicAttachment.getType_desc()); + tv_dynamic_time.setText(ToolKit.parseTime(dynamicAttachment.getTime() + "000")); + if (!TextUtils.isEmpty(dynamicAttachment.getDynamic_url())) { + sv_dynamic_img.setVisibility(View.VISIBLE); + sv_dynamic_img.setImageURI(ConstUrl.IMAGE_URL + dynamicAttachment.getDynamic_url()); + } else { + sv_dynamic_img.setVisibility(View.GONE); + } + if (SPUtils.getInt(context, ConsUser.DYNAMICS_TYPE) == 26) { + tv_dynamic_jump.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(context, R.drawable.ic_dynaimc_comment), null, null, null); + tv_dynamic_jump.setVisibility(View.VISIBLE); + tv_dynamic_content.setVisibility(View.GONE); + tv_dynamic_jump.setText("回复"); + tv_dynamic_jump.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, DynamicDetailActivity.class); + intent.putExtra("dynamic_id", dynamicAttachment.getDynamic_id()); + context.startActivity(intent); + } + }); + } + sv_avatar.setOnClickListener(this); + tv_dynamic_name.setOnClickListener(this); + mLlDynamic.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(context, DynamicDetailActivity.class); + intent.putExtra("dynamic_id", dynamicAttachment.getDynamic_id()); + context.startActivity(intent); + } + }); + break; + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.sv_avatar: + case R.id.tv_dynamic_name: + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", dynamicAttachment.getUserid()); + context.startActivity(intent); + break; + } + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + + @Override + protected boolean isShowTime() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/OnlineNoticeHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/OnlineNoticeHolder.java new file mode 100644 index 0000000..fa84fc7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/OnlineNoticeHolder.java @@ -0,0 +1,149 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.content.Intent; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.messaging.OnlineNoticeAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.view.main.MainPageActivity; + +/** + * Created by zhangbin on 2020/2/8. + */ +public class OnlineNoticeHolder extends MsgViewHolderBase { + + private OnlineNoticeAttachment mOnlineNoticeAttachment; + + private SimpleDraweeView mSv_attention_avatar; + private TextView mTv_attention_name; + private TextView mTv_attention_site; + private TextView mTv_attention_time; + private TextView tv_attention_btn; + + public OnlineNoticeHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.sys_online_notice_info; + } + + @Override + protected void inflateContentView() { + RelativeLayout.LayoutParams frameLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + frameLayout.topMargin = 0; + frameLayout.leftMargin = 0; + frameLayout.rightMargin = 0; + frameLayout.bottomMargin = 0; + contentContainer.setLayoutParams(frameLayout); + mSv_attention_avatar = view.findViewById(R.id.sv_attention_avatar); + mTv_attention_name = view.findViewById(R.id.tv_attention_name); + mTv_attention_site = view.findViewById(R.id.tv_attention_site); + tv_attention_btn = view.findViewById(R.id.tv_attention_btn); + mTv_attention_time = view.findViewById(R.id.tv_attention_time); + } + + @Override + protected void bindContentView() { + if (message.getAttachment() == null) { + return; + } + mOnlineNoticeAttachment = (OnlineNoticeAttachment) message.getAttachment(); + switch (mOnlineNoticeAttachment.getType()) { + case 18: + if (!TextUtils.isEmpty(mOnlineNoticeAttachment.getAvatar())) { + mSv_attention_avatar.setImageURI(ConstUrl.IMAGE_URL + mOnlineNoticeAttachment.getAvatar()); + } + mTv_attention_name.setText(mOnlineNoticeAttachment.getNickname()); + mTv_attention_time.setText(mOnlineNoticeAttachment.getTime()); + mSv_attention_avatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", mOnlineNoticeAttachment.getUserid()); + context.startActivity(intent); + } + }); + mTv_attention_name.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userId", mOnlineNoticeAttachment.getUserid()); + context.startActivity(intent); + } + }); + tv_attention_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + NimUIKit.startP2PSession(context, mOnlineNoticeAttachment.getUserid() + ""); + } + }); + break; + } + } + + @Override + protected boolean isShowTime() { + return false; + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoDoubleImageViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoDoubleImageViewHolder.java new file mode 100644 index 0000000..59a53f5 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoDoubleImageViewHolder.java @@ -0,0 +1,170 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.messaging.SysInfoDoubleImageAttachment; +import com.fengliyan.messaging.SysInfoImage; +import com.facebook.drawee.view.SimpleDraweeView; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.List; + +/** + * Created by zhangbin on 2018/12/5. + * 自定义多图文系统通知 + */ + +public class SysInfoDoubleImageViewHolder extends MsgViewHolderBase { + + private SimpleDraweeView mSv_double_image; + private LinearLayout mLl_double_inflate; + private SysInfoDoubleImageAttachment mSysInfoDoubleImageAttachment; + private TextView mTv_double_title; + private View mImageView; + + public SysInfoDoubleImageViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.sys_info_double_image; + } + + @Override + protected void inflateContentView() { + mSv_double_image = view.findViewById(R.id.sv_double_image); + mTv_double_title = view.findViewById(R.id.tv_double_title); + mLl_double_inflate = view.findViewById(R.id.ll_double_inflate); + } + + /** + * 防止滑到底部刷新重复添加动态布局 + * @param holder + * @param data + * @param position + * @param isScrolling + */ + @Override + public void convert(BaseViewHolder holder, IMMessage data, int position, boolean isScrolling) { +// super.convert(holder, data, position, isScrolling); + + if (view == null) { + view = holder.getConvertView(); + context = holder.getContext(); + message = data; + + inflate(); + refresh(); + bindHolder(holder); + } + } + + @Override + protected void bindContentView() { + if (message.getAttachment() == null) { + return; + } + mSysInfoDoubleImageAttachment = (SysInfoDoubleImageAttachment) message.getAttachment(); + + switch (mSysInfoDoubleImageAttachment.getType()) { + case 13: + final List imageList = mSysInfoDoubleImageAttachment.getImageList(); + if (null != imageList) { + mSv_double_image.setImageURI(imageList.get(0).getImage()); + mTv_double_title.setText(imageList.get(0).getTitle()); + + mSv_double_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + JumpUtils.jump(imageList.get(0).getLink_type(), imageList.get(0).getLink_url(), context); + } + }); + + if (imageList.size() > 0) { + for (int i = 1; i < imageList.size(); i++) { + final SysInfoImage sysInfoImage = imageList.get(i); + mImageView = View.inflate(context, R.layout.item_sys_info_double_iamge, null); + SimpleDraweeView childPhoto = mImageView.findViewById(R.id.sv_item_double_image); + TextView childTitle = mImageView.findViewById(R.id.tv_item_double_title); +// LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) imageView.getLayoutParams(); +// Log.d("nail","params===" + params); +// params.height = UiUtils.dip2px(context, 68); +//// params.height = LinearLayout.LayoutParams.WRAP_CONTENT; +// params.width = LinearLayout.LayoutParams.MATCH_PARENT; +// imageView.setLayoutParams(params); + childPhoto.setImageURI(sysInfoImage.getImage()); + childTitle.setText(sysInfoImage.getTitle()); + mLl_double_inflate.addView(mImageView); + + mImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + JumpUtils.jump(sysInfoImage.getLink_type(), sysInfoImage.getLink_url(), context); + } + }); + + } + } + } + break; + } + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoSingleImageViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoSingleImageViewHolder.java new file mode 100644 index 0000000..cc89067 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoSingleImageViewHolder.java @@ -0,0 +1,133 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.messaging.SysInfoSingleImageAttachment; +import com.facebook.drawee.view.SimpleDraweeView; + + +/** + * Created by zhangbin on 2018/12/5. + * 自定义当图文系统通知 + */ + +public class SysInfoSingleImageViewHolder extends MsgViewHolderBase { + + private SimpleDraweeView mSv_single_image; + private TextView mTv_single_title; + private TextView mTv_single_context; + private SysInfoSingleImageAttachment mSysInfoSingleImageAttachment; + private TextView mTv_single_category; + + public SysInfoSingleImageViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.sys_info_single_image; + } + + @Override + protected void inflateContentView() { + mSv_single_image = view.findViewById(R.id.sv_single_image); + mTv_single_title = view.findViewById(R.id.tv_single_title); + mTv_single_context = view.findViewById(R.id.tv_single_context); + mTv_single_category = view.findViewById(R.id.tv_single_category); + } + + @Override + protected void bindContentView() { + if (message.getAttachment() == null) { + return; + } + mSysInfoSingleImageAttachment = (SysInfoSingleImageAttachment) message.getAttachment(); + + switch (mSysInfoSingleImageAttachment.getType()) { + case 12: + mSv_single_image.setImageURI(mSysInfoSingleImageAttachment.getImage()); + + if (mSysInfoSingleImageAttachment.getAct_type() == 1) { + mTv_single_title.setVisibility(View.GONE); + mTv_single_context.setVisibility(View.GONE); + }else if (mSysInfoSingleImageAttachment.getAct_type() == 2) { + mTv_single_title.setVisibility(View.VISIBLE); + mTv_single_title.setText(mSysInfoSingleImageAttachment.getTitle()); + if (!TextUtils.isEmpty(mSysInfoSingleImageAttachment.getTxt())) { + mTv_single_context.setVisibility(View.VISIBLE); + mTv_single_context.setText(mSysInfoSingleImageAttachment.getTxt()); + }else { + mTv_single_context.setVisibility(View.GONE); + } + } + + if (TextUtils.isEmpty(mSysInfoSingleImageAttachment.getAct_string())) { + mTv_single_category.setVisibility(View.GONE); + }else { + mTv_single_category.setVisibility(View.VISIBLE); + } + break; + } + } + + @Override + protected void onItemClick() { + JumpUtils.jump(mSysInfoSingleImageAttachment.getLink_type(), mSysInfoSingleImageAttachment.getLink_url(), context); + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoViewHolder.java new file mode 100644 index 0000000..1fe0234 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/SysInfoViewHolder.java @@ -0,0 +1,219 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.content.Intent; +import android.text.TextUtils; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.messaging.FieldListA; +import com.fengliyan.messaging.SysInfoAttachment; +import com.fengliyan.messaging.SysInfoTextBean; + +import java.util.List; + +/** + * Created by zhangbin on 2018/12/5. + * 自定义普通系统通知 + */ + +public class SysInfoViewHolder extends MsgViewHolderBase { + + private SysInfoAttachment mSysInfoTextAttachment; + private TextView mTv_text_title; + private TextView mTv_text_time; + private TextView mTv_text_context1; + private TextView mTv_text_fields; + private TextView mTv_text_fields1; + private TextView mTv_text_user_code; + private TextView mTv_text_context2; + private LinearLayout mLl_details; + private TextView detailLabel; + private SysInfoTextBean mSysInfoTextBean; + + public SysInfoViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.sys_info_text_attachment; + } + + @Override + protected void inflateContentView() { + + mTv_text_title = view.findViewById(R.id.tv_text_title); + mTv_text_time = view.findViewById(R.id.tv_text_time); + mTv_text_context1 = view.findViewById(R.id.tv_text_context1); + mTv_text_fields = view.findViewById(R.id.tv_text_fields); + mTv_text_fields1 = view.findViewById(R.id.tv_text_fields1); + mTv_text_user_code = view.findViewById(R.id.tv_text_user_code); + mTv_text_context2 = view.findViewById(R.id.tv_text_context2); + mLl_details = view.findViewById(R.id.ll_details); + detailLabel = view.findViewById(R.id.detailLabel); + } + + @Override + protected void bindContentView() { + if (message.getAttachment() == null) { + return; + } + mSysInfoTextAttachment = (SysInfoAttachment) message.getAttachment(); + switch (mSysInfoTextAttachment.getType()) { + case 11: //资金流水通知 + mSysInfoTextBean = mSysInfoTextAttachment.getSysInfoTextBean(); + + + mTv_text_title.setText(mSysInfoTextBean.getTitle()); + mTv_text_time.setText(mSysInfoTextBean.getDate()); + + if (TextUtils.isEmpty(mSysInfoTextBean.getTxt1())) { + mTv_text_context1.setVisibility(View.GONE); + } else { + mTv_text_context1.setVisibility(View.VISIBLE); + mTv_text_context1.setText(mSysInfoTextBean.getTxt1()); + } + + + List fields = mSysInfoTextBean.getFields(); + if (null == fields || fields.size() == 0) { + mTv_text_fields.setVisibility(View.GONE); + mTv_text_user_code.setVisibility(View.GONE); + mTv_text_fields1.setVisibility(View.GONE); + } else { + mTv_text_fields.setVisibility(View.VISIBLE); + mTv_text_user_code.setVisibility(View.VISIBLE); + mTv_text_fields1.setVisibility(View.VISIBLE); + StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringUserCode = new StringBuilder(); + StringBuilder stringBuilder1 = new StringBuilder(); + + boolean isUserCode = false; + String userCode = ""; + for (FieldListA field : fields) { + String key = field.getN(); + String value = field.getV(); + if (StrU.equals("用户号", key)) { + stringUserCode.append(key).append(":").append(value); + userCode = value; + isUserCode = true; + } else if (!isUserCode) { + if (stringBuilder.length() > 0) stringBuilder.append("\n"); + stringBuilder.append(key).append(":").append(value); + } else { + if (stringBuilder1.length() > 0) + stringBuilder1.append(key).append("\n"); + stringBuilder1.append(key).append(":").append(value); + } + } + if (stringUserCode.length() == 0) { + mTv_text_user_code.setVisibility(View.GONE); + mTv_text_fields1.setVisibility(View.GONE); + stringBuilder.setLength(0); + for (FieldListA field : fields) { + String key = field.getN(); + String value = field.getV(); + if (stringBuilder.length() > 0) stringBuilder.append("\n"); + stringBuilder.append(key).append(":").append(value); + } + } + mTv_text_fields.setText(stringBuilder); + String userCode1 = stringUserCode.toString(); + if (!StrU.isEmpty(userCode1)) { + StrU.setSpanTextColor(userCode1, 0, 4, mTv_text_user_code, R.color.two_text, context); + } + mTv_text_fields1.setText(stringBuilder1); + String finalUserCode = userCode; + mTv_text_user_code.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(context, MainPageActivity.class); + intent.putExtra("userCode", finalUserCode); + context.startActivity(intent); + } + }); + } + + if (TextUtils.isEmpty(mSysInfoTextBean.getTxt2())) { + mTv_text_context2.setVisibility(View.GONE); + } else { + mTv_text_context2.setVisibility(View.VISIBLE); + mTv_text_context2.setText(mSysInfoTextBean.getTxt2()); + } + + if (mSysInfoTextBean.getLink_type() == 0) { + mLl_details.setVisibility(View.GONE); + } else { + if (!TextUtils.isEmpty(mSysInfoTextBean.getTxt3())) { + detailLabel.setText(mSysInfoTextBean.getTxt3()); + } else { + detailLabel.setText("详情"); + } + mLl_details.setVisibility(View.VISIBLE); + } + break; + } + } + + @Override + protected void onItemClick() { + JumpUtils.jump(mSysInfoTextBean.getLink_type(), mSysInfoTextBean.getLink_url(), context); + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/VideoViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/VideoViewHolder.java new file mode 100644 index 0000000..73f464a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/VideoViewHolder.java @@ -0,0 +1,293 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.content.Context; +import android.content.Intent; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.fengliyan.messaging.VideoAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.model.main.CallBean; +import com.fengliyan.tianlesue.model.main.MainPageBean; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.AgoraWithFUVideoActivity; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class VideoViewHolder extends MsgViewHolderBase implements View.OnClickListener { + + + private LinearLayout mLl_left; + private LinearLayout mLl_right; + private TextView mTv_left_video_message; + private TextView mTv_right_video_message; + private ImageView iv_left_message; + private ImageView iv_right_message; + private VideoAttachment mVideoAttachment; + + private boolean b; + + public VideoViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.video_custom_message; + } + + @Override + protected void inflateContentView() { + mLl_left = view.findViewById(R.id.ll_left); + mLl_right = view.findViewById(R.id.ll_right); + mTv_left_video_message = view.findViewById(R.id.tv_left_video_message); + mTv_right_video_message = view.findViewById(R.id.tv_right_video_message); + iv_left_message = view.findViewById(R.id.iv_left_message); + iv_right_message = view.findViewById(R.id.iv_right_message); + } + + private void layoutDirection() { + if (isReceivedMessage()) { + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); + + showBorder(info, false, contentContainer); +// bodyTextView.setBackgroundResource(NimUIKitImpl.getOptions().messageLeftBackground); + +// Map remoteExtension = message.getRemoteExtension(); +// if (null != remoteExtension) { +// if (null != remoteExtension.get("is_cut")) { +// int data = (int) remoteExtension.get("is_cut"); +// if (data == 1) { +// mImageView.setVisibility(View.VISIBLE); +// }else { +// mImageView.setVisibility(View.GONE); +// } +// } +// } + } else { + NimUserInfo info = NIMClient.getService(UserService.class).getUserInfo(message.getFromAccount()); +// bodyTextView.setBackgroundResource(NimUIKitImpl.getOptions().messageRightBackground); + b = showBorder(info, true, contentContainer); +// mImageView.setVisibility(View.GONE); + } + } + + @Override + protected void bindContentView() { + layoutDirection(); + if (message.getAttachment() == null) { + return; + } + mVideoAttachment = (VideoAttachment) message.getAttachment(); + Log.i("TAG", "bindContentView: ---------->" + mVideoAttachment); + switch (mVideoAttachment.getType()) { + case 15: + if (mVideoAttachment.getFrom_uid().equals(SPUtils.getInt(context, ConsUser.USER_ID) + "")) { //发送的 + mLl_left.setVisibility(View.GONE); + mLl_right.setVisibility(View.VISIBLE); + if (b) { + mTv_right_video_message.setTextColor(ContextCompat.getColor(this.context, R.color.one_text)); + } else { + mTv_right_video_message.setTextColor(ContextCompat.getColor(this.context, R.color.white)); + } + if (mVideoAttachment.getStatus() == 1) { + mTv_right_video_message.setText("你已取消"); + } else if (mVideoAttachment.getStatus() == 2) { + mTv_right_video_message.setText("你已拒绝"); + } else if (mVideoAttachment.getStatus() == 3) { + mTv_right_video_message.setText("超时未接听"); + } else if (mVideoAttachment.getStatus() == 4) { + mTv_right_video_message.setText("通话时长:" + secondToTime(mVideoAttachment.getCall_time())); + } +// setBackground(mLl_right); + } else { //接收的 + mLl_left.setVisibility(View.VISIBLE); + mLl_right.setVisibility(View.GONE); +// setBackground(mLl_left); + mTv_left_video_message.setTextColor(ContextCompat.getColor(this.context, R.color.one_text)); + if (mVideoAttachment.getStatus() == 1) { + mTv_left_video_message.setText("对方已取消"); + } else if (mVideoAttachment.getStatus() == 2) { + mTv_left_video_message.setText("对方已拒绝"); + } else if (mVideoAttachment.getStatus() == 3) { + mTv_left_video_message.setText("超时未接听"); + } else if (mVideoAttachment.getStatus() == 4) { + mTv_left_video_message.setText("通话时长:" + secondToTime(mVideoAttachment.getCall_time())); + } + } + if (mVideoAttachment.getCalltype() == 1) { + iv_left_message.setImageResource(R.drawable.ic_video_left); + if (b) { + iv_right_message.setImageResource(R.drawable.ic_video_left); + } else { + iv_right_message.setImageResource(R.drawable.ic_video_right); + } + } else { + iv_left_message.setImageResource(R.drawable.ic_voice_left); + if (b) { + iv_right_message.setImageResource(R.drawable.ic_voice_left); + } else { + iv_right_message.setImageResource(R.drawable.ic_voice_right); + } + } + mLl_right.setOnClickListener(this); + mLl_left.setOnClickListener(this); + break; + } + } + +// public String getFormatedDateTime(long dateTime) { +// SimpleDateFormat sDateFormat = new SimpleDateFormat("mm:ss"); +// return sDateFormat.format(new Date(dateTime + 0)); +// } + + private String secondToTime(long second) { + second = second % 86400; + long hours = second / 3600; + second = second % 3600; + long minutes = second / 60; + second = second % 60; + + String strHours = String.format("%02d", hours); + String strMinutes = String.format("%02d", minutes); + String strSecond = String.format("%02d", second); + return strHours + ":" + strMinutes + ":" + strSecond; + } + + @Override + protected boolean shouldDisplayReceipt() { + return false; + } + + + @Override + public void onClick(View v) { + if (!isFastClick()) { + if (!TextUtils.isEmpty(mVideoAttachment.getFrom_uid())) { + if (mVideoAttachment.getFrom_uid().equals(SPUtils.getInt(context, ConsUser.USER_ID) + "")) { + getMainPageData(v.getContext(), Integer.parseInt(mVideoAttachment.getTo_uid())); + } else { + getMainPageData(v.getContext(), Integer.parseInt(mVideoAttachment.getFrom_uid())); + } + } + } else { + MaleToast.showMessage(v.getContext(), "请稍后拨打"); + } + } + + private final int MIN_DELAY_TIME = 5000; // 两次点击间隔不能少于1000ms + private long lastClickTime; + + public boolean isFastClick() { + boolean flag = true; + long currentClickTime = System.currentTimeMillis(); + if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) { + flag = false; + } + lastClickTime = currentClickTime; + return flag; + } + + private void getMainPageData(final Context context, final int userId) { + MainManager.getMainPageData((BaseActivity) context, userId, "", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MainPageBean result, String message) { + if (null != result) { + if (null != result.getAnchor()) { + int video_status = result.getAnchor().getVideo_status(); //视频状态 0 休息中 1 视频中 + int open_video_status; + if (mVideoAttachment.getCalltype() == 1) { + open_video_status = result.getAnchor().getOpen_video_status(); //是否开启视频接听 0 否 1 是 + } else { + open_video_status = result.getAnchor().getOpen_voice_status(); //是否开启语音接听 0 否 1 是 + } + if (open_video_status == 0) { + MaleToast.showMessage(context, "对方开启了勿扰模式"); + } else { + if (video_status == 0) { + // if (null != result.getSkill()) { + // if (0 != result.getSkill().size()) { + if (mVideoAttachment.getCalltype() == 1) { + getCallInfo(context, userId, 0, 0); + } else { + getCallInfo(context, userId, 0, 1); + } + // } + // } + } else { + MaleToast.showMessage(context, "对方正在通话中"); + } + } + + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + + } + }); + } + + private void getCallInfo(final Context context, int uid, int skillId, int callType) { + MainManager.getCallInfo((BaseActivity) context, uid, skillId, callType, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final CallBean result, String message) { + Intent intent = new Intent(context, AgoraWithFUVideoActivity.class); + + intent.putExtra(Constant.SOCKET_URL, result.getSocket_url()); + + intent.putExtra("isCaller", true); + intent.putExtra("callType", callType); + intent.putExtra("roomId", Integer.valueOf(result.getRoom_id())); + intent.putExtra("avatar", result.getTo_avatar()); + intent.putExtra("nickName", result.getTo_nickname()); + intent.putExtra("price", result.getSkill().getPrice()); + intent.putExtra("toUid", result.getTo_uid()); + intent.putExtra("porn_check_bean_v2", result.getPorn_checkV2()); + intent.putExtra("diff_num", result.getGuard().getDiff_num()); + intent.putExtra("guard_price", result.getGuard().getGuard_price()); + intent.putExtra("free_num", result.getFree_num()); + intent.putExtra("isRisk", (result.getFrom_risk_status() == 1 || result.getTo_risk_status() == 1)); + context.startActivity(intent); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/YestodayViewHolder.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/YestodayViewHolder.java new file mode 100644 index 0000000..b09785e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/holder/YestodayViewHolder.java @@ -0,0 +1,197 @@ +package com.fengliyan.tianlesue.view.news.im.holder; + +import android.content.Intent; +import android.graphics.Color; +import androidx.core.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.messaging.FieldListA; +import com.fengliyan.messaging.YestordayAttachment; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.business.session.viewholder.MsgViewHolderBase; +import com.fengliyan.tianlesue.im.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.fengliyan.tianlesue.view.settings.InvitationActivity; +import com.fengliyan.tianlesue.view.settings.WithdrawActivity; + +import java.util.List; + +/** + * Created by zhangbin on 2018/12/5. + * 自定义普通系统通知 + */ + +public class YestodayViewHolder extends MsgViewHolderBase { + + private YestordayAttachment attachment; + private TextView mTv_text_title; + private TextView mTv_text_time; + private TextView mTv_text_context1; + private TextView mTv_text_fields; + private TextView mTv_text_context2; + private LinearLayout mLl_details; + private TextView detailLabel; + private View line; + private ImageView indicatorImageView; + + public YestodayViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.sys_info_text_attachment; + } + + @Override + protected void inflateContentView() { + + mTv_text_title = view.findViewById(R.id.tv_text_title); + mTv_text_time = view.findViewById(R.id.tv_text_time); + mTv_text_context1 = view.findViewById(R.id.tv_text_context1); + mTv_text_fields = view.findViewById(R.id.tv_text_fields); + mTv_text_context2 = view.findViewById(R.id.tv_text_context2); + mLl_details = view.findViewById(R.id.ll_details); + detailLabel = view.findViewById(R.id.detailLabel); + line = view.findViewById(R.id.line); + indicatorImageView = view.findViewById(R.id.indicatorImageView); + indicatorImageView.setVisibility(View.GONE); + line.setVisibility(View.GONE); + detailLabel.setTextColor(Color.parseColor("#333333")); + } + + @Override + protected void bindContentView() { + if (message.getAttachment() == null) { + return; + } + attachment = (YestordayAttachment) message.getAttachment(); + switch (attachment.getType()) { + case 22: //资金流水通知 + mTv_text_title.setText(attachment.title); + mTv_text_time.setText(attachment.date); + + if (TextUtils.isEmpty(attachment.txt1)) { + mTv_text_context1.setVisibility(View.GONE); + } else { + mTv_text_context1.setTextColor(ContextCompat.getColor(context,R.color.mainColor)); + mTv_text_context1.setVisibility(View.VISIBLE); + mTv_text_context1.setText(attachment.txt1); + mTv_text_context1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + context.startActivity(new Intent(context, WithdrawActivity.class)); + } + }); + } + + List fields = attachment.fields; + if (null == fields || fields.size() == 0) { + mTv_text_fields.setVisibility(View.GONE); + } else { + mTv_text_fields.setVisibility(View.VISIBLE); + StringBuilder stringBuilder = new StringBuilder(); + + for (int i = 0; i < fields.size(); i++) { + FieldListA field = fields.get(i); + String key = field.getN(); + String value = field.getV(); + if (i == fields.size() - 1) { + stringBuilder.append(key).append(":").append(value); + } else { + stringBuilder.append(key).append(":").append(value).append("\n"); + } + } + mTv_text_fields.setText(stringBuilder); + } + + + mTv_text_context2.setVisibility(View.GONE); +// if (TextUtils.isEmpty(attachment.txt2)) { +// mTv_text_context2.setVisibility(View.GONE); +// } else { +// mTv_text_context2.setVisibility(View.VISIBLE); +// mTv_text_context2.setText(attachment.txt2); +// } + String s = String.format("%s,%s",attachment.txt2,attachment.txt3); + SpannableStringBuilder builder = new SpannableStringBuilder(s); + int start = s.indexOf(attachment.txt3); + builder.setSpan(new ForegroundColorSpan(Color.parseColor("#208eef")), start,start+attachment.txt3.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + detailLabel.setText(builder); + if (attachment.link_type == 0) { + mLl_details.setVisibility(View.GONE); + } else { + mLl_details.setVisibility(View.VISIBLE); + } + mLl_details.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + context.startActivity(new Intent(context, InvitationActivity.class)); + } + }); + break; + } + } + + @Override + protected void onItemClick() { +// JumpUtils.jump(mSysInfoTextBean.getLink_type(), mSysInfoTextBean.getLink_url(), context); + } + + /** + * 禁止长按 + * + * @return + */ + @Override + protected boolean onItemLongClick() { + return true; + } + + /** + * 居中显示 + * + * @return + */ + @Override + protected boolean isMiddleItem() { + return true; + } + + /** + * 不显示头像 + * + * @return + */ + @Override + protected boolean isShowHeadImage() { + return false; + } + + /** + * 不显示气泡 + * + * @return + */ + @Override + protected boolean isShowBubble() { + return false; + } + + /** + * 不显示已读 + * + * @return + */ + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/mixpush/DemoMixPushMessageHandler.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/mixpush/DemoMixPushMessageHandler.java new file mode 100644 index 0000000..9e9147d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/mixpush/DemoMixPushMessageHandler.java @@ -0,0 +1,98 @@ +package com.fengliyan.tianlesue.view.news.im.mixpush; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; + +import com.fengliyan.tianlesue.view.main.MainActivity; +import com.fengliyan.tianlesue.view.news.im.DemoCache; +import com.netease.nimlib.sdk.StatusBarNotificationConfig; +import com.netease.nimlib.sdk.mixpush.MixPushMessageHandler; + +import java.util.Map; + +/** + * Created by hzchenkang on 2016/11/10. + */ + +public class DemoMixPushMessageHandler implements MixPushMessageHandler { + + + public static final String PAYLOAD_SESSION_ID = "sessionID"; + public static final String PAYLOAD_SESSION_TYPE = "sessionType"; + + // 对于华为推送,这个方法并不能保证一定会回调 + @Override + public boolean onNotificationClicked(Context context, Map payload) { + +// LogUtil.i(DemoMixPushMessageHandler.class.getSimpleName(), "rev pushMessage payload " + payload); +// +// String sessionId = payload.get(PAYLOAD_SESSION_ID); +// String type = payload.get(PAYLOAD_SESSION_TYPE); +// String s = payload.get("link_type"); +// Log.d("nail","s==========" + s); + +// Log.d("nail","sessionId===" + sessionId); +// Log.d("nail","type===" + type); +// // +// if (sessionId != null && type != null) { +// Log.d("nail","aaaaaaaa"); +//// int typeValue = Integer.valueOf(type); +//// ArrayList imMessages = new ArrayList<>(); +//// IMMessage imMessage = MessageBuilder.createEmptyMessage(sessionId, SessionTypeEnum.typeOfValue(typeValue), 0); +//// imMessages.add(imMessage); +//// Intent notifyIntent = new Intent(); +//// notifyIntent.setComponent(initLaunchComponent(context)); +//// notifyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); +//// notifyIntent.setAction(Intent.ACTION_VIEW); +//// notifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 必须 +//// notifyIntent.putExtra(NimIntent.EXTRA_NOTIFY_CONTENT, imMessages); +//// context.startActivity(notifyIntent); +//// Intent intent = new Intent(context, FakeActivity.class); +//// context.startActivity(intent); +// +// NimUIKit.startP2PSession(context, sessionId); +// } else { +// Intent intent = new Intent(context, MainActivity.class); +// context.startActivity(intent); +// } + +// NimUIKit.startP2PSession(context, sessionId); + + Intent intent = new Intent(context, MainActivity.class); + context.startActivity(intent); + return true; + } + + private ComponentName initLaunchComponent(Context context) { + ComponentName launchComponent; + StatusBarNotificationConfig config = DemoCache.getNotificationConfig(); + Class entrance = config.notificationEntrance; + if (entrance == null) { + launchComponent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent(); + } else { + launchComponent = new ComponentName(context, entrance); + } + return launchComponent; + } + + // 将音视频通知 Notification 缓存,清除所有通知后再次弹出 Notification,避免清除之后找不到打开正在进行音视频通话界面的入口 + @Override + public boolean cleanMixPushNotifications(int pushType) { +// Context context = DemoCache.getContext(); +// NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); +// if (manager != null) { +// manager.cancelAll(); +// SparseArray nos = AVChatKit.getNotifications(); +// if (nos != null) { +// int key = 0; +// for (int i = 0; i < nos.size(); i++) { +// key = nos.keyAt(i); +// manager.notify(key, nos.get(key)); +// } +// } +// } + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/news/im/mixpush/DemoPushContentProvider.java b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/mixpush/DemoPushContentProvider.java new file mode 100644 index 0000000..945ea5b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/news/im/mixpush/DemoPushContentProvider.java @@ -0,0 +1,65 @@ +package com.fengliyan.tianlesue.view.news.im.mixpush; + + +import com.fengliyan.tianlesue.im.uikit.api.model.main.CustomPushContentProvider; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import java.util.HashMap; +import java.util.Map; + +/** + * 示例: + * 1.自定义的推送文案 + * 2.自定义推送 payload 实现特定的点击通知栏跳转行为{@linkDemoMixPushMessageHandler} + *

+ * 如果自定义文案和payload,请开发者在各端发送消息时保持一致。 + */ + +public class DemoPushContentProvider implements CustomPushContentProvider { + + @Override + public String getPushContent(IMMessage message) { + + String pushContent = null; + + if (null != message) { + MsgTypeEnum msgType = message.getMsgType(); + int value = msgType.getValue(); + if (value == 0) { //文本 +// pushContent = "收到一条信息"; + pushContent = message.getContent(); + } else if (value == 1) { + pushContent = "收到一张图片"; + } else if (value == 3) { + pushContent = "收到一段小视频"; + } else if (value == 100) { + pushContent = "神秘惊喜"; + } else if (value == 5) { + pushContent = "通知"; + } + } + return pushContent; + } + + @Override + public Map getPushPayload(IMMessage message) { + return getPayload(message); + } + + private Map getPayload(IMMessage message) { + if (message == null) { + return null; + } + HashMap payload = new HashMap<>(); + payload.put("sessionType", message.getSessionType().getValue()); + if (message.getSessionType() == SessionTypeEnum.Team) { + payload.put("sessionID", message.getSessionId()); + } else if (message.getSessionType() == SessionTypeEnum.P2P) { + payload.put("sessionID", message.getFromAccount()); + } + + return payload; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/CharmRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/CharmRankFragment.java new file mode 100644 index 0000000..d6ba90a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/CharmRankFragment.java @@ -0,0 +1,514 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankAdapter; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/27. + * 魅力榜 + */ + +public class CharmRankFragment extends Fragment implements View.OnClickListener { + + private RankAdapter mRankAdpter; + private LoadMoreListView mRankListView; + private SimpleDraweeView mFirstPhoto; + private SimpleDraweeView mSecondPhoto; + private SimpleDraweeView mThirdPhoto; + private TextView mFirstName; + private TextView mSecondName; + private TextView mThirdName; + private TextView mFirstCost; + private TextView mSecondCost; + private TextView mThirdCost; + private TextView mWeeklyView; + private TextView mMonthlyView; + private TextView mTotalView; + private List mRankDataList = new ArrayList<>(); + private int mPage = 1; + private int mType = 1; + private SwipeRefreshLayout mChannelRefresh; + private TextView mDaylyView; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_charm_rank, container, false); + initView(v); + mPage = 1; + chooseDayData(); +// initSvga(v); + return v; + } + + private void initView(View v) { + mRankListView = v.findViewById(R.id.daka_rank_list_view); + mFirstPhoto = v.findViewById(R.id.daka_rank_first_photo); + mSecondPhoto = v.findViewById(R.id.daka_rank_second_photo); + mThirdPhoto = v.findViewById(R.id.daka_rank_third_photo); + mFirstName = v.findViewById(R.id.daka_rank_first_name); + mSecondName = v.findViewById(R.id.daka_rank_second_name); + mThirdName = v.findViewById(R.id.daka_rank_third_name); + mFirstCost = v.findViewById(R.id.daka_rank_first_cost); + mSecondCost = v.findViewById(R.id.daka_rank_second_cost); + mThirdCost = v.findViewById(R.id.daka_rank_third_cost); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mWeeklyView = v.findViewById(R.id.daka_rank_header_week); + mDaylyView = v.findViewById(R.id.daka_rank_header_day); + mMonthlyView = v.findViewById(R.id.daka_rank_header_month); + mTotalView = v.findViewById(R.id.daka_rank_header_total); + mRankAdpter = new RankAdapter(getActivity()); + mRankAdpter.setRankBeans(mRankDataList); + mRankListView.setAdapter(mRankAdpter); +// mRankListView.dimissEmptyView(); + mRankListView.colorLoadMoreViewByResId(R.drawable.shape_dake_rank_header); + + mRankListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + boolean enable = false; + if (mRankListView != null && mRankListView.getChildCount() > 0) { + // check if the first item of the list is visible + boolean firstItemVisible = mRankListView.getFirstVisiblePosition() == 0; + // check if the top of the first item is visible + boolean topOfFirstItemVisible = mRankListView.getChildAt(0).getTop() == 0; + // enabling or disabling the refresh layout + enable = firstItemVisible && topOfFirstItemVisible; + } + mChannelRefresh.setEnabled(enable); + + int size = mRankDataList.size() + 3; + int lastPosition = mRankListView.getLastVisiblePosition() + 3; + + if (size != 0 && size % 10 == 0 && !mPageLoad + && lastPosition > size - 2) { + getLoveRank(mPage, mType); + mPageLoad = true; + } else if (lastPosition <= size - 2) { + mPageLoad = false; + } + } + }); + + mFirstPhoto.setOnClickListener(this); + mSecondPhoto.setOnClickListener(this); + mThirdPhoto.setOnClickListener(this); + mWeeklyView.setOnClickListener(this); + mDaylyView.setOnClickListener(this); + mMonthlyView.setOnClickListener(this); + mTotalView.setOnClickListener(this); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getLoveRank(mPage, mType); + } + }); + } + + private void initSvga(View v) { + final SVGAImageView svga1 = v.findViewById(R.id.svga1); + final SVGAImageView svga2 = v.findViewById(R.id.svga2); + final SVGAImageView svga3 = v.findViewById(R.id.svga3); + new SVGAParser(getContext()).parse("svga/hg1.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga1.setImageDrawable(drawable); + svga1.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg2.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga2.setImageDrawable(drawable); + svga2.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg3.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga3.setImageDrawable(drawable); + svga3.startAnimation(); + } + + @Override + public void onError() { + + } + }); + } + + + private void chooseWeekData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 1; + getLoveRank(mPage, mType); + } + + private void chooseDayData() { + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mDaylyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 4; + getLoveRank(mPage, mType); + } + + private void chooseMonthData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 2; + getLoveRank(mPage, mType); + } + + private void chooseTotalData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 3; + getLoveRank(mPage, mType); + } + + //魅力榜 + public void getLoveRank(final int page, int type) { + SettingManager.rankLove((BaseActivity) getActivity(), type, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(type, result); + if (page == 1) { + notifyRankData(result.getList()); + } else { + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + List rankBeans = new ArrayList<>(); + private boolean mPageLoad = false; + private int oneId; + private int twoId; + private int threeId; + + public void notifyRankData(List rankBeans) { + this.rankBeans = rankBeans; + if (rankBeans.size() == 1) { + final NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = 0; + threeId = 0; + + for (int i = 0; i < 1; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 2) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = 0; + + for (int i = 0; i < 2; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + + } else if (rankBeans.size() > 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + mRankListView.setSelection(0); + } else { + + mFirstName.setVisibility(View.GONE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setImageURI(""); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, String totalMoney) { +// if (totalMoney >= 10000) { +// double money = totalMoney / 10000; +// view.setText(String.format("%.1f", money) + "万"); +// } else { +// view.setText(String.format("%.0f", totalMoney)); +// } + view.setText(totalMoney); + } + + @Override + public void onClick(View v) { + if (v == mDaylyView) { + chooseDayData(); + } else if (v == mWeeklyView) { + chooseWeekData(); + } else if (v == mMonthlyView) { + chooseMonthData(); + } else if (v == mTotalView) { + chooseTotalData(); + } else if (v == mFirstPhoto) { + if (oneId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", oneId); + getActivity().startActivity(intent); + } + } else if (v == mSecondPhoto) { + if (twoId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", twoId); + getActivity().startActivity(intent); + } + } else if (v == mThirdPhoto) { + if (threeId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", threeId); + getActivity().startActivity(intent); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/ConsumptionRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/ConsumptionRankFragment.java new file mode 100644 index 0000000..0f846e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/ConsumptionRankFragment.java @@ -0,0 +1,513 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankAdapter; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/27. + * 消费榜 + */ + +public class ConsumptionRankFragment extends Fragment implements View.OnClickListener { + + private RankAdapter mRankAdpter; + private LoadMoreListView mRankListView; + private SimpleDraweeView mFirstPhoto; + private SimpleDraweeView mSecondPhoto; + private SimpleDraweeView mThirdPhoto; + private TextView mFirstName; + private TextView mSecondName; + private TextView mThirdName; + private TextView mFirstCost; + private TextView mSecondCost; + private TextView mThirdCost; + private TextView mWeeklyView; + private TextView mMonthlyView; + private TextView mTotalView; + private List mRankDataList = new ArrayList<>(); + private int mPage = 1; + private int mType = 1; + private SwipeRefreshLayout mChannelRefresh; + private TextView mDaylyView; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_charm_rank, container, false); + initView(v); + mPage = 1; + chooseDayData(); +// initSvga(v); + return v; + } + + private void initView(View v) { + mRankListView = v.findViewById(R.id.daka_rank_list_view); + mFirstPhoto = v.findViewById(R.id.daka_rank_first_photo); + mSecondPhoto = v.findViewById(R.id.daka_rank_second_photo); + mThirdPhoto = v.findViewById(R.id.daka_rank_third_photo); + mFirstName = v.findViewById(R.id.daka_rank_first_name); + mSecondName = v.findViewById(R.id.daka_rank_second_name); + mThirdName = v.findViewById(R.id.daka_rank_third_name); + mFirstCost = v.findViewById(R.id.daka_rank_first_cost); + mSecondCost = v.findViewById(R.id.daka_rank_second_cost); + mThirdCost = v.findViewById(R.id.daka_rank_third_cost); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mWeeklyView = v.findViewById(R.id.daka_rank_header_week); + mMonthlyView = v.findViewById(R.id.daka_rank_header_month); + mTotalView = v.findViewById(R.id.daka_rank_header_total); + mDaylyView = v.findViewById(R.id.daka_rank_header_day); + mRankAdpter = new RankAdapter(getActivity()); + mRankAdpter.setRankBeans(mRankDataList); + mRankListView.setAdapter(mRankAdpter); +// mRankListView.dimissEmptyView(); + mRankListView.colorLoadMoreViewByResId(R.drawable.shape_dake_rank_header); + + mRankListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + boolean enable = false; + if (mRankListView != null && mRankListView.getChildCount() > 0) { + // check if the first item of the list is visible + boolean firstItemVisible = mRankListView.getFirstVisiblePosition() == 0; + // check if the top of the first item is visible + boolean topOfFirstItemVisible = mRankListView.getChildAt(0).getTop() == 0; + // enabling or disabling the refresh layout + enable = firstItemVisible && topOfFirstItemVisible; + } + mChannelRefresh.setEnabled(enable); + + int size = mRankDataList.size() + 3; + int lastPosition = mRankListView.getLastVisiblePosition() + 3; + + if (size != 0 && size % 10 == 0 && !mPageLoad + && lastPosition > size - 2) { + getLoveRank(mPage, mType); + mPageLoad = true; + } else if (lastPosition <= size - 2) { + mPageLoad = false; + } + } + }); + + mFirstPhoto.setOnClickListener(this); + mSecondPhoto.setOnClickListener(this); + mThirdPhoto.setOnClickListener(this); + mDaylyView.setOnClickListener(this); + mWeeklyView.setOnClickListener(this); + mMonthlyView.setOnClickListener(this); + mTotalView.setOnClickListener(this); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getLoveRank(mPage, mType); + } + }); + } + + private void initSvga(View v) { + final SVGAImageView svga1 = v.findViewById(R.id.svga1); + final SVGAImageView svga2 = v.findViewById(R.id.svga2); + final SVGAImageView svga3 = v.findViewById(R.id.svga3); + new SVGAParser(getContext()).parse("svga/hg1.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga1.setImageDrawable(drawable); + svga1.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg2.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga2.setImageDrawable(drawable); + svga2.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg3.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga3.setImageDrawable(drawable); + svga3.startAnimation(); + } + + @Override + public void onError() { + + } + }); + } + + private void chooseWeekData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 1; + getLoveRank(mPage, mType); + } + + private void chooseDayData() { + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mDaylyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 4; + getLoveRank(mPage, mType); + } + + private void chooseMonthData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 2; + getLoveRank(mPage, mType); + } + + private void chooseTotalData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 3; + getLoveRank(mPage, mType); + } + + //魅力榜 + public void getLoveRank(final int page, int type) { + SettingManager.rankWealth((BaseActivity) getActivity(), type, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(type, result); + if (page == 1) { + notifyRankData(result.getList()); + } else { + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + List rankBeans = new ArrayList<>(); + private boolean mPageLoad = false; + private int oneId; + private int twoId; + private int threeId; + + public void notifyRankData(List rankBeans) { + this.rankBeans = rankBeans; + if (rankBeans.size() == 1) { + final NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = 0; + threeId = 0; + + for (int i = 0; i < 1; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 2) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = 0; + + for (int i = 0; i < 2; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(StrU.getResourcePath(rankBean.getAvatar(), getActivity())); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + + } else if (rankBeans.size() > 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else { + + mFirstName.setVisibility(View.GONE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setImageURI(""); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, String totalMoney) { +// if (totalMoney >= 10000) { +// double money = totalMoney / 10000; +// view.setText(String.format("%.1f", money) + "万"); +// } else { +// view.setText(String.format("%.0f", totalMoney)); +// } + view.setText(totalMoney); + } + + @Override + public void onClick(View v) { + if (v == mDaylyView) { + chooseDayData(); + } else if (v == mWeeklyView) { + chooseWeekData(); + } else if (v == mMonthlyView) { + chooseMonthData(); + } else if (v == mTotalView) { + chooseTotalData(); + } else if (v == mFirstPhoto) { + if (oneId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", oneId); + getActivity().startActivity(intent); + } + } else if (v == mSecondPhoto) { + if (twoId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", twoId); + getActivity().startActivity(intent); + } + } else if (v == mThirdPhoto) { + if (threeId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", threeId); + getActivity().startActivity(intent); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/GiftRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/GiftRankFragment.java new file mode 100644 index 0000000..3338180 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/GiftRankFragment.java @@ -0,0 +1,512 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankAdapter; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/11/8. + */ + +public class GiftRankFragment extends Fragment implements View.OnClickListener { + + private RankAdapter mRankAdpter; + private LoadMoreListView mRankListView; + private SimpleDraweeView mFirstPhoto; + private SimpleDraweeView mSecondPhoto; + private SimpleDraweeView mThirdPhoto; + private TextView mFirstName; + private TextView mSecondName; + private TextView mThirdName; + private TextView mFirstCost; + private TextView mSecondCost; + private TextView mThirdCost; + private TextView mWeeklyView; + private TextView mMonthlyView; + private TextView mTotalView; + private List mRankDataList = new ArrayList<>(); + private int mPage = 1; + private int mType = 1; + private SwipeRefreshLayout mChannelRefresh; + private TextView mDaylyView; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_charm_rank, container, false); + initView(v); + mPage = 1; + chooseDayData(); +// initSvga(v); + return v; + } + + private void initView(View v) { + mRankListView = v.findViewById(R.id.daka_rank_list_view); + mFirstPhoto = v.findViewById(R.id.daka_rank_first_photo); + mSecondPhoto = v.findViewById(R.id.daka_rank_second_photo); + mThirdPhoto = v.findViewById(R.id.daka_rank_third_photo); + mFirstName = v.findViewById(R.id.daka_rank_first_name); + mSecondName = v.findViewById(R.id.daka_rank_second_name); + mThirdName = v.findViewById(R.id.daka_rank_third_name); + mFirstCost = v.findViewById(R.id.daka_rank_first_cost); + mSecondCost = v.findViewById(R.id.daka_rank_second_cost); + mThirdCost = v.findViewById(R.id.daka_rank_third_cost); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mWeeklyView = v.findViewById(R.id.daka_rank_header_week); + mDaylyView = v.findViewById(R.id.daka_rank_header_day); + mMonthlyView = v.findViewById(R.id.daka_rank_header_month); + mTotalView = v.findViewById(R.id.daka_rank_header_total); + mRankAdpter = new RankAdapter(getActivity()); + mRankAdpter.setRankBeans(mRankDataList); + mRankListView.setAdapter(mRankAdpter); +// mRankListView.dimissEmptyView(); + mRankListView.colorLoadMoreViewByResId(R.drawable.shape_dake_rank_header); + + mRankListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + boolean enable = false; + if (mRankListView != null && mRankListView.getChildCount() > 0) { + // check if the first item of the list is visible + boolean firstItemVisible = mRankListView.getFirstVisiblePosition() == 0; + // check if the top of the first item is visible + boolean topOfFirstItemVisible = mRankListView.getChildAt(0).getTop() == 0; + // enabling or disabling the refresh layout + enable = firstItemVisible && topOfFirstItemVisible; + } + mChannelRefresh.setEnabled(enable); + + int size = mRankDataList.size() + 3; + int lastPosition = mRankListView.getLastVisiblePosition() + 3; + + if (size != 0 && size % 10 == 0 && !mPageLoad + && lastPosition > size - 2) { + getLoveRank(mPage, mType); + mPageLoad = true; + } else if (lastPosition <= size - 2) { + mPageLoad = false; + } + } + }); + + mFirstPhoto.setOnClickListener(this); + mSecondPhoto.setOnClickListener(this); + mThirdPhoto.setOnClickListener(this); + mDaylyView.setOnClickListener(this); + mWeeklyView.setOnClickListener(this); + mMonthlyView.setOnClickListener(this); + mTotalView.setOnClickListener(this); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getLoveRank(mPage, mType); + } + }); + } + + private void initSvga(View v) { + final SVGAImageView svga1 = v.findViewById(R.id.svga1); + final SVGAImageView svga2 = v.findViewById(R.id.svga2); + final SVGAImageView svga3 = v.findViewById(R.id.svga3); + new SVGAParser(getContext()).parse("svga/hg1.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga1.setImageDrawable(drawable); + svga1.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg2.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga2.setImageDrawable(drawable); + svga2.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg3.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga3.setImageDrawable(drawable); + svga3.startAnimation(); + } + + @Override + public void onError() { + + } + }); + } + + private void chooseWeekData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 1; + getLoveRank(mPage, mType); + } + + private void chooseDayData() { + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mDaylyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 4; + getLoveRank(mPage, mType); + } + + private void chooseMonthData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 2; + getLoveRank(mPage, mType); + } + + private void chooseTotalData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 3; + getLoveRank(mPage, mType); + } + + //魅力榜 + public void getLoveRank(final int page, int type) { + SettingManager.rankGift((BaseActivity) getActivity(), type, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(type, result); + if (page == 1) { + notifyRankData(result.getList()); + } else { + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + List rankBeans = new ArrayList<>(); + private boolean mPageLoad = false; + private int oneId; + private int twoId; + private int threeId; + + public void notifyRankData(List rankBeans) { + this.rankBeans = rankBeans; + if (rankBeans.size() == 1) { + final NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = 0; + threeId = 0; + + for (int i = 0; i < 1; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 2) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = 0; + + for (int i = 0; i < 2; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + + } else if (rankBeans.size() > 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + mRankListView.setSelection(0); + } else { + + mFirstName.setVisibility(View.GONE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setImageURI(""); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, String totalMoney) { +// if (totalMoney >= 10000) { +// double money = totalMoney / 10000; +// view.setText(String.format("%.1f", money) + "万"); +// } else { +// view.setText(String.format("%.0f", totalMoney)); +// } + view.setText(totalMoney); + } + + @Override + public void onClick(View v) { + if (v == mDaylyView) { + chooseDayData(); + } else if (v == mWeeklyView) { + chooseWeekData(); + } else if (v == mMonthlyView) { + chooseMonthData(); + } else if (v == mTotalView) { + chooseTotalData(); + } else if (v == mFirstPhoto) { + if (oneId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", oneId); + getActivity().startActivity(intent); + } + } else if (v == mSecondPhoto) { + if (twoId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", twoId); + getActivity().startActivity(intent); + } + } else if (v == mThirdPhoto) { + if (threeId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", threeId); + getActivity().startActivity(intent); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/GuardRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/GuardRankFragment.java new file mode 100644 index 0000000..3cc29df --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/GuardRankFragment.java @@ -0,0 +1,511 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankAdapter; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/12/31. + */ +public class GuardRankFragment extends Fragment implements View.OnClickListener { + + private RankAdapter mRankAdpter; + private LoadMoreListView mRankListView; + private SimpleDraweeView mFirstPhoto; + private SimpleDraweeView mSecondPhoto; + private SimpleDraweeView mThirdPhoto; + private TextView mFirstName; + private TextView mSecondName; + private TextView mThirdName; + private TextView mFirstCost; + private TextView mSecondCost; + private TextView mThirdCost; + private TextView mWeeklyView; + private TextView mMonthlyView; + private TextView mTotalView; + private List mRankDataList = new ArrayList<>(); + private int mPage = 1; + private int mType = 1; + private SwipeRefreshLayout mChannelRefresh; + private TextView mDaylyView; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_charm_rank, container, false); + initView(v); + mPage = 1; + chooseDayData(); +// initSvga(v); + return v; + } + + private void initView(View v) { + mRankListView = v.findViewById(R.id.daka_rank_list_view); + mFirstPhoto = v.findViewById(R.id.daka_rank_first_photo); + mSecondPhoto = v.findViewById(R.id.daka_rank_second_photo); + mThirdPhoto = v.findViewById(R.id.daka_rank_third_photo); + mFirstName = v.findViewById(R.id.daka_rank_first_name); + mSecondName = v.findViewById(R.id.daka_rank_second_name); + mThirdName = v.findViewById(R.id.daka_rank_third_name); + mFirstCost = v.findViewById(R.id.daka_rank_first_cost); + mSecondCost = v.findViewById(R.id.daka_rank_second_cost); + mThirdCost = v.findViewById(R.id.daka_rank_third_cost); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mWeeklyView = v.findViewById(R.id.daka_rank_header_week); + mDaylyView = v.findViewById(R.id.daka_rank_header_day); + mMonthlyView = v.findViewById(R.id.daka_rank_header_month); + mTotalView = v.findViewById(R.id.daka_rank_header_total); + mRankAdpter = new RankAdapter(getActivity()); + mRankAdpter.setRankBeans(mRankDataList); + mRankListView.setAdapter(mRankAdpter); +// mRankListView.dimissEmptyView(); + mRankListView.colorLoadMoreViewByResId(R.drawable.shape_dake_rank_header); + + mRankListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + boolean enable = false; + if (mRankListView != null && mRankListView.getChildCount() > 0) { + // check if the first item of the list is visible + boolean firstItemVisible = mRankListView.getFirstVisiblePosition() == 0; + // check if the top of the first item is visible + boolean topOfFirstItemVisible = mRankListView.getChildAt(0).getTop() == 0; + // enabling or disabling the refresh layout + enable = firstItemVisible && topOfFirstItemVisible; + } + mChannelRefresh.setEnabled(enable); + + int size = mRankDataList.size() + 3; + int lastPosition = mRankListView.getLastVisiblePosition() + 3; + + if (size != 0 && size % 10 == 0 && !mPageLoad + && lastPosition > size - 2) { + getLoveRank(mPage, mType); + mPageLoad = true; + } else if (lastPosition <= size - 2) { + mPageLoad = false; + } + } + }); + + mFirstPhoto.setOnClickListener(this); + mSecondPhoto.setOnClickListener(this); + mThirdPhoto.setOnClickListener(this); + mWeeklyView.setOnClickListener(this); + mDaylyView.setOnClickListener(this); + mMonthlyView.setOnClickListener(this); + mTotalView.setOnClickListener(this); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getLoveRank(mPage, mType); + } + }); + } + + private void initSvga(View v) { + final SVGAImageView svga1 = v.findViewById(R.id.svga1); + final SVGAImageView svga2 = v.findViewById(R.id.svga2); + final SVGAImageView svga3 = v.findViewById(R.id.svga3); + new SVGAParser(getContext()).parse("svga/hg1.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga1.setImageDrawable(drawable); + svga1.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg2.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga2.setImageDrawable(drawable); + svga2.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg3.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga3.setImageDrawable(drawable); + svga3.startAnimation(); + } + + @Override + public void onError() { + + } + }); + } + + private void chooseWeekData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 1; + getLoveRank(mPage, mType); + } + + private void chooseDayData() { + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mDaylyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 4; + getLoveRank(mPage, mType); + } + + private void chooseMonthData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 2; + getLoveRank(mPage, mType); + } + + private void chooseTotalData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 3; + getLoveRank(mPage, mType); + } + + //守护榜 + public void getLoveRank(final int page, int type) { + SettingManager.rankGuard((BaseActivity) getActivity(), type, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(type, result); + if (page == 1) { + notifyRankData(result.getList()); + } else { + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + List rankBeans = new ArrayList<>(); + private boolean mPageLoad = false; + private int oneId; + private int twoId; + private int threeId; + + public void notifyRankData(List rankBeans) { + this.rankBeans = rankBeans; + if (rankBeans.size() == 1) { + final NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = 0; + threeId = 0; + + for (int i = 0; i < 1; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 2) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = 0; + + for (int i = 0; i < 2; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + + } else if (rankBeans.size() > 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + mRankListView.setSelection(0); + } else { + + mFirstName.setVisibility(View.GONE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setImageURI(""); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, String totalMoney) { +// if (totalMoney >= 10000) { +// double money = totalMoney / 10000; +// view.setText(String.format("%.1f", money) + "万"); +// }else { +// view.setText(String.format("%.0f", totalMoney)); +// } + view.setText(totalMoney); + } + + @Override + public void onClick(View v) { + if (v == mDaylyView) { + chooseDayData(); + } else if (v == mWeeklyView) { + chooseWeekData(); + } else if (v == mMonthlyView) { + chooseMonthData(); + } else if (v == mTotalView) { + chooseTotalData(); + } else if (v == mFirstPhoto) { + if (oneId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", oneId); + getActivity().startActivity(intent); + } + } else if (v == mSecondPhoto) { + if (twoId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", twoId); + getActivity().startActivity(intent); + } + } else if (v == mThirdPhoto) { + if (threeId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", threeId); + getActivity().startActivity(intent); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/InviteRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/InviteRankFragment.java new file mode 100644 index 0000000..a5cd91f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/InviteRankFragment.java @@ -0,0 +1,511 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankAdapter; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/11/8. + */ + +public class InviteRankFragment extends Fragment implements View.OnClickListener { + + private RankAdapter mRankAdpter; + private LoadMoreListView mRankListView; + private SimpleDraweeView mFirstPhoto; + private SimpleDraweeView mSecondPhoto; + private SimpleDraweeView mThirdPhoto; + private TextView mFirstName; + private TextView mSecondName; + private TextView mThirdName; + private TextView mFirstCost; + private TextView mSecondCost; + private TextView mThirdCost; + private TextView mWeeklyView; + private TextView mMonthlyView; + private TextView mTotalView; + private List mRankDataList = new ArrayList<>(); + private int mPage = 1; + private int mType = 1; + private SwipeRefreshLayout mChannelRefresh; + private TextView mDaylyView; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_charm_rank, container, false); + initView(v); + mPage = 1; + chooseDayData(); +// initSvga(v); + return v; + } + + private void initView(View v) { + mRankListView = v.findViewById(R.id.daka_rank_list_view); + mFirstPhoto = v.findViewById(R.id.daka_rank_first_photo); + mSecondPhoto = v.findViewById(R.id.daka_rank_second_photo); + mThirdPhoto = v.findViewById(R.id.daka_rank_third_photo); + mFirstName = v.findViewById(R.id.daka_rank_first_name); + mSecondName = v.findViewById(R.id.daka_rank_second_name); + mThirdName = v.findViewById(R.id.daka_rank_third_name); + mFirstCost = v.findViewById(R.id.daka_rank_first_cost); + mSecondCost = v.findViewById(R.id.daka_rank_second_cost); + mThirdCost = v.findViewById(R.id.daka_rank_third_cost); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mWeeklyView = v.findViewById(R.id.daka_rank_header_week); + mDaylyView = v.findViewById(R.id.daka_rank_header_day); + mMonthlyView = v.findViewById(R.id.daka_rank_header_month); + mTotalView = v.findViewById(R.id.daka_rank_header_total); + mRankAdpter = new RankAdapter(getActivity()); + mRankAdpter.setRankBeans(mRankDataList); + mRankListView.setAdapter(mRankAdpter); +// mRankListView.dimissEmptyView(); + mRankListView.colorLoadMoreViewByResId(R.drawable.shape_dake_rank_header); + + mRankListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + boolean enable = false; + if (mRankListView != null && mRankListView.getChildCount() > 0) { + // check if the first item of the list is visible + boolean firstItemVisible = mRankListView.getFirstVisiblePosition() == 0; + // check if the top of the first item is visible + boolean topOfFirstItemVisible = mRankListView.getChildAt(0).getTop() == 0; + // enabling or disabling the refresh layout + enable = firstItemVisible && topOfFirstItemVisible; + } + mChannelRefresh.setEnabled(enable); + + int size = mRankDataList.size() + 3; + int lastPosition = mRankListView.getLastVisiblePosition() + 3; + + if (size != 0 && size % 10 == 0 && !mPageLoad + && lastPosition > size - 2) { + getLoveRank(mPage, mType); + mPageLoad = true; + } else if (lastPosition <= size - 2) { + mPageLoad = false; + } + } + }); + + mFirstPhoto.setOnClickListener(this); + mSecondPhoto.setOnClickListener(this); + mThirdPhoto.setOnClickListener(this); + mDaylyView.setOnClickListener(this); + mWeeklyView.setOnClickListener(this); + mMonthlyView.setOnClickListener(this); + mTotalView.setOnClickListener(this); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getLoveRank(mPage, mType); + } + }); + } + + private void initSvga(View v) { + final SVGAImageView svga1 = v.findViewById(R.id.svga1); + final SVGAImageView svga2 = v.findViewById(R.id.svga2); + final SVGAImageView svga3 = v.findViewById(R.id.svga3); + new SVGAParser(getContext()).parse("svga/hg1.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga1.setImageDrawable(drawable); + svga1.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg2.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga2.setImageDrawable(drawable); + svga2.startAnimation(); + } + + @Override + public void onError() { + + } + }); + new SVGAParser(getContext()).parse("svga/hg3.svga", new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga3.setImageDrawable(drawable); + svga3.startAnimation(); + } + + @Override + public void onError() { + + } + }); + } + + private void chooseWeekData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 1; + getLoveRank(mPage, mType); + } + + private void chooseDayData() { + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mDaylyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 4; + getLoveRank(mPage, mType); + } + + private void chooseMonthData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 2; + getLoveRank(mPage, mType); + } + + private void chooseTotalData() { + mDaylyView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(R.drawable.shape_daka_rank_frame1); + mWeeklyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mWeeklyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mMonthlyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mMonthlyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mDaylyView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + mDaylyView.setTextColor(ContextCompat.getColor(getContext(), R.color.white)); + mTotalView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTotalView.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow_ffd33e)); + mPage = 1; + mType = 3; + getLoveRank(mPage, mType); + } + + //邀请榜 + public void getLoveRank(final int page, int type) { + SettingManager.rankInvite((BaseActivity) getActivity(), type, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { + if (page == 1) { + notifyRankData(result.getList()); + } else { + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + List rankBeans = new ArrayList<>(); + private boolean mPageLoad = false; + private int oneId; + private int twoId; + private int threeId; + + public void notifyRankData(List rankBeans) { + this.rankBeans = rankBeans; + if (rankBeans.size() == 1) { + final NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = 0; + threeId = 0; + + for (int i = 0; i < 1; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 2) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = 0; + + for (int i = 0; i < 2; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } else if (rankBeans.size() == 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + + } else if (rankBeans.size() > 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getGap()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getGap()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getGap()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + mRankListView.setSelection(0); + } else { + + mFirstName.setVisibility(View.GONE); + mFirstCost.setVisibility(View.GONE); + mFirstPhoto.setImageURI(""); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } + } + + /** + * 大于一万,用小数表示 + * + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, String totalMoney) { +// if (totalMoney >= 10000) { +// double money = totalMoney / 10000; +// view.setText(String.format("%.1f", money) + "万"); +// } else { +// view.setText(String.format("%.0f", totalMoney)); +// } + view.setText(totalMoney); + } + + @Override + public void onClick(View v) { + if (v == mDaylyView) { + chooseDayData(); + } else if (v == mWeeklyView) { + chooseWeekData(); + } else if (v == mMonthlyView) { + chooseMonthData(); + } else if (v == mTotalView) { + chooseTotalData(); + } else if (v == mFirstPhoto) { + if (oneId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", oneId); + getActivity().startActivity(intent); + } + } else if (v == mSecondPhoto) { + if (twoId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", twoId); + getActivity().startActivity(intent); + } + } else if (v == mThirdPhoto) { + if (threeId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", threeId); + getActivity().startActivity(intent); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/MainRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/MainRankFragment.java new file mode 100644 index 0000000..1747141 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/MainRankFragment.java @@ -0,0 +1,315 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/27. + */ +public class MainRankFragment extends Fragment implements View.OnClickListener { + private View mTitleView; + private TextView mTitleText1; + private TextView mTitleText2; + private TextView mTitleText3; + private TextView mTitleText4; + private TextView mTitleText5; + private TextView mTitleText6; + private View mTitleBottom1; + private View mTitleBottom2; + private View mTitleBottom3; + private View mTitleBottom4; + private View mTitleBottom5; + private View mTitleBottom6; + private View mTitleTag1; + private View mTitleTag2; + private View mTitleTag3; + private View mTitleTag4; + private View mTitleTag5; + private View mTitleTag6; + private ViewPager mDynamicViewPager; + private List mRankFragments = new ArrayList<>(); + private MainViewPagerAdapter mViewPagerAdapter; + private int mIndex; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_rank_view_pager, container, false); + initTitle(); + initView(v); + return v; + } + + @Override + public void onHiddenChanged(boolean hidden) { + if (!hidden) { + initTitle(); + viewPagerChange(mIndex); + } + } + + private void initTitle() { + + ((BaseActivity) getActivity()).hideTitleBar(); +// Title title = ((BaseActivity) getActivity()).getCustomTitle(); +// title.setVisibility(View.VISIBLE); +// title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); +// title.dismissBottomLine(); +// title.dimissRight(); +// title.dismissLeft(); +// title.setTitle(""); +// +// title.addViewTo(mTitleView, POSTION_CENTER); + } + private void initView(View v) { + + + mTitleTag1 = v.findViewById(R.id.dynamic_title_view_1); + mTitleTag2 = v.findViewById(R.id.dynamic_title_view_2); + mTitleTag3 = v.findViewById(R.id.dynamic_title_view_3); + mTitleTag4 = v.findViewById(R.id.dynamic_title_view_4); + mTitleTag5 = v.findViewById(R.id.dynamic_title_view_5); + mTitleTag6 = v.findViewById(R.id.dynamic_title_view_6); + mTitleText1 = v.findViewById(R.id.dynamic_title_name_1); + mTitleText2 = v.findViewById(R.id.dynamic_title_name_2); + mTitleText3 = v.findViewById(R.id.dynamic_title_name_3); + mTitleText4 = v.findViewById(R.id.dynamic_title_name_4); + mTitleText5 = v.findViewById(R.id.dynamic_title_name_5); + mTitleText6 = v.findViewById(R.id.dynamic_title_name_6); + mTitleBottom1 = v.findViewById(R.id.dynamic_title_bottom_line_1); + mTitleBottom2 = v.findViewById(R.id.dynamic_title_bottom_line_2); + mTitleBottom3 = v.findViewById(R.id.dynamic_title_bottom_line_3); + mTitleBottom4 = v.findViewById(R.id.dynamic_title_bottom_line_4); + mTitleBottom5 = v.findViewById(R.id.dynamic_title_bottom_line_5); + mTitleBottom6 = v.findViewById(R.id.dynamic_title_bottom_line_6); + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + mTitleTag3.setOnClickListener(this); + mTitleTag4.setOnClickListener(this); + mTitleTag5.setOnClickListener(this); + mTitleTag6.setOnClickListener(this); + + mDynamicViewPager = v.findViewById(R.id.dynamic_view_pager); + mDynamicViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + @Override + public void onPageSelected(int position) { + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + } + }); + mViewPagerAdapter = new MainViewPagerAdapter(getChildFragmentManager(), + mRankFragments); + + CharmRankFragment charmRankFragment = new CharmRankFragment(); + ConsumptionRankFragment consumptionRankFragment = new ConsumptionRankFragment(); + GuardRankFragment guardRankFragment = new GuardRankFragment(); + GiftRankFragment giftRankFragment = new GiftRankFragment(); + InviteRankFragment inviteRankFragment = new InviteRankFragment(); + ZhimiMiBiRankFragment zhimiMiBiRankFragment = new ZhimiMiBiRankFragment(); + + mRankFragments.add(charmRankFragment); + mRankFragments.add(consumptionRankFragment); + mRankFragments.add(guardRankFragment); + mRankFragments.add(giftRankFragment); + mRankFragments.add(inviteRankFragment); +// mRankFragments.add(zhimiMiBiRankFragment); + + mDynamicViewPager.setAdapter(mViewPagerAdapter); + mDynamicViewPager.setCurrentItem(mIndex, false); + viewPagerChange(mIndex); + } + + private void viewPagerChange(int index) { + mIndex = index; + switch (index) { + case 0: + mTitleText1.setTextColor(getResources().getColor(R.color.white)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom1.setVisibility(View.VISIBLE); + + mTitleText2.setTextColor(getResources().getColor(R.color.white)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + + mTitleText3.setTextColor(getResources().getColor(R.color.white)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + + mTitleText4.setTextColor(getResources().getColor(R.color.white)); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + + mTitleText5.setTextColor(getResources().getColor(R.color.white)); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + + mTitleText6.setTextColor(getResources().getColor(R.color.white)); + mTitleText6.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom6.setVisibility(View.GONE); + break; + case 1: + mTitleText2.setTextColor(getResources().getColor(R.color.white)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom2.setVisibility(View.VISIBLE); + + mTitleText1.setTextColor(getResources().getColor(R.color.white)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + + mTitleText3.setTextColor(getResources().getColor(R.color.white)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + + mTitleText4.setTextColor(getResources().getColor(R.color.white)); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + + mTitleText5.setTextColor(getResources().getColor(R.color.white)); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + + mTitleText6.setTextColor(getResources().getColor(R.color.white)); + mTitleText6.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom6.setVisibility(View.GONE); + break; + case 2: + mTitleText3.setTextColor(getResources().getColor(R.color.white)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom3.setVisibility(View.VISIBLE); + + mTitleText4.setTextColor(getResources().getColor(R.color.white)); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + + mTitleText2.setTextColor(getResources().getColor(R.color.white)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + + mTitleText1.setTextColor(getResources().getColor(R.color.white)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + + mTitleText5.setTextColor(getResources().getColor(R.color.white)); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + + mTitleText6.setTextColor(getResources().getColor(R.color.white)); + mTitleText6.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom6.setVisibility(View.GONE); + break; + case 3: + mTitleText4.setTextColor(getResources().getColor(R.color.white)); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom4.setVisibility(View.VISIBLE); + + mTitleText2.setTextColor(getResources().getColor(R.color.white)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + + mTitleText1.setTextColor(getResources().getColor(R.color.white)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + + mTitleText3.setTextColor(getResources().getColor(R.color.white)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + + mTitleText5.setTextColor(getResources().getColor(R.color.white)); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + + mTitleText6.setTextColor(getResources().getColor(R.color.white)); + mTitleText6.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom6.setVisibility(View.GONE); + break; + case 5: + mTitleText5.setTextColor(getResources().getColor(R.color.white)); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom5.setVisibility(View.VISIBLE); + + mTitleText1.setTextColor(getResources().getColor(R.color.white)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + + mTitleText2.setTextColor(getResources().getColor(R.color.white)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + + mTitleText3.setTextColor(getResources().getColor(R.color.white)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + + mTitleText4.setTextColor(getResources().getColor(R.color.white)); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + + mTitleText6.setTextColor(getResources().getColor(R.color.white)); + mTitleText6.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom6.setVisibility(View.GONE); + break; + case 4: + mTitleText6.setTextColor(getResources().getColor(R.color.white)); + mTitleText6.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom6.setVisibility(View.VISIBLE); + + mTitleText1.setTextColor(getResources().getColor(R.color.white)); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + + mTitleText2.setTextColor(getResources().getColor(R.color.white)); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + + mTitleText3.setTextColor(getResources().getColor(R.color.white)); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + + mTitleText4.setTextColor(getResources().getColor(R.color.white)); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + + mTitleText5.setTextColor(getResources().getColor(R.color.white)); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + break; + } + } + + @Override + public void onClick(View view) { + if (view == mTitleTag1) { + mDynamicViewPager.setCurrentItem(0); + } else if (view == mTitleTag2) { + mDynamicViewPager.setCurrentItem(1); + } else if (view == mTitleTag3) { + mDynamicViewPager.setCurrentItem(2); + } else if (view == mTitleTag4) { + mDynamicViewPager.setCurrentItem(3); + } else if (view == mTitleTag5) { + mDynamicViewPager.setCurrentItem(5); + } else if (view == mTitleTag6) { + mDynamicViewPager.setCurrentItem(4); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/MibiRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/MibiRankFragment.java new file mode 100644 index 0000000..cd2863a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/MibiRankFragment.java @@ -0,0 +1,108 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.rank.MibiRankAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.refresh.LoadMoreListView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/2/27. + * 金币榜 + */ + +public class MibiRankFragment extends Fragment { + + private LoadMoreListView mListView; + private MibiRankAdapter mAdapter; + private List mListBeans = new ArrayList<>(); + private int mPage; + private boolean mPageLoad; + private SwipeRefreshLayout mChannelRefresh; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_mibi_rank, container, false); + initView(v); + mPage = 1; + getData(mPage); + return v; + } + + private void initView(View v) { + mListView = v.findViewById(R.id.mibi_list_view); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mAdapter = new MibiRankAdapter(getActivity()); + mAdapter.setData(mListBeans); + mListView.setAdapter(mAdapter); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if(mListBeans.size() != 0 && mListBeans.size() % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mListBeans.size() - 2){ + getData(mPage); + mPageLoad = true; + }else if(mListView.getLastVisiblePosition() <= mListBeans.size() - 2){ + mPageLoad = false; + } + + } + }); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getData(mPage); + } + }); + } + + private void getData(final int page) { + SettingManager.rankRich((BaseActivity) getActivity(), 3, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { + if (page == 1) { + mListBeans.clear(); + } + mListBeans.addAll(result.getList()); + mAdapter.notifyDataSetChanged(); + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/ZhiRankActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/ZhiRankActivity.java new file mode 100644 index 0000000..cb2b377 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/ZhiRankActivity.java @@ -0,0 +1,312 @@ +package com.fengliyan.tianlesue.view.rank; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.TypedValue; +import android.view.View; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.uikit.title.Title; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/11/8. + */ + +public class ZhiRankActivity extends BaseActivity implements View.OnClickListener { + + private View mTitleView; + private TextView mTitleText1; + private TextView mTitleText2; + private TextView mTitleText3; + private TextView mTitleText4; + private TextView mTitleText5; + private View mTitleBottom1; + private View mTitleBottom2; + private View mTitleBottom3; + private View mTitleBottom4; + private View mTitleBottom5; + private View mTitleTag1; + private View mTitleTag2; + private View mTitleTag3; + private View mTitleTag4; + private View mTitleTag5; + private View rl_back; + private ViewPager mDynamicViewPager; + private List mRankFragments = new ArrayList<>(); + private MainViewPagerAdapter mViewPagerAdapter; + private int mIndex; //0 魅力榜 1消费榜 2礼物榜 3金币榜 + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_zhi_rank); + mIndex = getIntent().getIntExtra("rankType", 0); +// initTitle(); + initView(); + } + + private void initTitle() { + Title title = getCustomTitle(); + title.setVisibility(View.VISIBLE); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.item_zhi_rank_title, null); + mTitleTag1 = mTitleView.findViewById(R.id.dynamic_title_view_1); + mTitleTag2 = mTitleView.findViewById(R.id.dynamic_title_view_2); + mTitleTag3 = mTitleView.findViewById(R.id.dynamic_title_view_3); + mTitleTag4 = mTitleView.findViewById(R.id.dynamic_title_view_4); + mTitleTag5 = mTitleView.findViewById(R.id.dynamic_title_view_5); + mTitleText1 = mTitleView.findViewById(R.id.dynamic_title_name_1); + mTitleText2 = mTitleView.findViewById(R.id.dynamic_title_name_2); + mTitleText3 = mTitleView.findViewById(R.id.dynamic_title_name_3); + mTitleText4 = mTitleView.findViewById(R.id.dynamic_title_name_4); + mTitleText5 = mTitleView.findViewById(R.id.dynamic_title_name_5); + mTitleBottom1 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_1); + mTitleBottom2 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_2); + mTitleBottom3 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_3); + mTitleBottom4 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_4); + mTitleBottom5 = mTitleView.findViewById(R.id.dynamic_title_bottom_line_5); + rl_back = mTitleView.findViewById(R.id.rl_back); + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + mTitleTag3.setOnClickListener(this); + mTitleTag4.setOnClickListener(this); + mTitleTag5.setOnClickListener(this); + rl_back.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + + } + + private void initView() { + hideTitleBar(); + mTitleTag1 = findViewById(R.id.dynamic_title_view_1); + mTitleTag2 = findViewById(R.id.dynamic_title_view_2); + mTitleTag3 = findViewById(R.id.dynamic_title_view_3); + mTitleTag4 = findViewById(R.id.dynamic_title_view_4); + mTitleTag5 = findViewById(R.id.dynamic_title_view_5); + mTitleText1 = findViewById(R.id.dynamic_title_name_1); + mTitleText2 = findViewById(R.id.dynamic_title_name_2); + mTitleText3 = findViewById(R.id.dynamic_title_name_3); + mTitleText4 = findViewById(R.id.dynamic_title_name_4); + mTitleText5 = findViewById(R.id.dynamic_title_name_5); + mTitleBottom1 = findViewById(R.id.dynamic_title_bottom_line_1); + mTitleBottom2 = findViewById(R.id.dynamic_title_bottom_line_2); + mTitleBottom3 = findViewById(R.id.dynamic_title_bottom_line_3); + mTitleBottom4 = findViewById(R.id.dynamic_title_bottom_line_4); + mTitleBottom5 = findViewById(R.id.dynamic_title_bottom_line_5); + rl_back = findViewById(R.id.rl_back); + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + mTitleTag3.setOnClickListener(this); + mTitleTag4.setOnClickListener(this); + mTitleTag5.setOnClickListener(this); + rl_back.setOnClickListener(this); + mDynamicViewPager = findViewById(R.id.dynamic_view_pager); + mDynamicViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + + } + + @Override + public void onPageSelected(int position) { + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPagerAdapter = new MainViewPagerAdapter(getSupportFragmentManager(), + mRankFragments); + + CharmRankFragment charmRankFragment = new CharmRankFragment(); + GiftRankFragment giftRankFragment = new GiftRankFragment(); + GuardRankFragment guardRankFragment = new GuardRankFragment(); + InviteRankFragment inviteRankFragment = new InviteRankFragment(); + ConsumptionRankFragment consumptionRankFragment = new ConsumptionRankFragment(); + ZhimiMiBiRankFragment zhimiMiBiRankFragment = new ZhimiMiBiRankFragment(); + + mRankFragments.add(charmRankFragment); + mRankFragments.add(giftRankFragment); + mRankFragments.add(guardRankFragment); + mRankFragments.add(inviteRankFragment); + mRankFragments.add(consumptionRankFragment); +// mRankFragments.add(zhimiMiBiRankFragment); + + mDynamicViewPager.setAdapter(mViewPagerAdapter); + mDynamicViewPager.setCurrentItem(mIndex, false); + viewPagerChange(mIndex); + } + + private void viewPagerChange(int index) { + mIndex = index; + switch (index) { + case 0: +// mTitleText1.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom1.setVisibility(View.VISIBLE); + +// mTitleText2.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + +// mTitleText3.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + +// mTitleText4.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + +// mTitleText5.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText5.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + break; + case 1: +// mTitleText2.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom2.setVisibility(View.VISIBLE); + +// mTitleText1.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + +// mTitleText3.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + +// mTitleText4.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + +// mTitleText5.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText5.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + break; + case 2: +// mTitleText3.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom3.setVisibility(View.VISIBLE); + +// mTitleText4.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + +// mTitleText2.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + +// mTitleText1.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + +// mTitleText5.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText5.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + break; + case 3: +// mTitleText4.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom4.setVisibility(View.VISIBLE); + +// mTitleText2.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + +// mTitleText1.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + +// mTitleText3.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + +// mTitleText5.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText5.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom5.setVisibility(View.GONE); + break; + case 4: +// mTitleText5.setTextColor(getResources().getColor(R.color.zhimi_one_text)); + mTitleText5.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + mTitleText5.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + mTitleBottom5.setVisibility(View.VISIBLE); + +// mTitleText1.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom1.setVisibility(View.GONE); + +// mTitleText2.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom2.setVisibility(View.GONE); + +// mTitleText3.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText3.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom3.setVisibility(View.GONE); + +// mTitleText4.setTextColor(getResources().getColor(R.color.two_text)); + mTitleText4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + mTitleText4.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//常规 + mTitleBottom4.setVisibility(View.GONE); + break; + } + } + + @Override + public void onClick(View view) { + if (view == mTitleTag1) { + mDynamicViewPager.setCurrentItem(0); + } else if (view == mTitleTag2) { + mDynamicViewPager.setCurrentItem(1); + } else if (view == mTitleTag3) { + mDynamicViewPager.setCurrentItem(2); + } else if (view == mTitleTag4) { + mDynamicViewPager.setCurrentItem(3); + } else if (view == mTitleTag5) { + mDynamicViewPager.setCurrentItem(4); + } else if (view == rl_back) { + finish(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/rank/ZhimiMiBiRankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/rank/ZhimiMiBiRankFragment.java new file mode 100644 index 0000000..f34d56f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/rank/ZhimiMiBiRankFragment.java @@ -0,0 +1,351 @@ +package com.fengliyan.tianlesue.view.rank; + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankAdapter; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2019/4/26. + */ + +public class ZhimiMiBiRankFragment extends Fragment { + + private RankAdapter mRankAdpter; + private LoadMoreListView mRankListView; + private SimpleDraweeView mFirstPhoto; + private SimpleDraweeView mSecondPhoto; + private SimpleDraweeView mThirdPhoto; + private TextView mFirstName; + private TextView mSecondName; + private TextView mThirdName; + private TextView mFirstCost; + private TextView mSecondCost; + private TextView mThirdCost; + private List mRankDataList = new ArrayList<>(); + private int mPage = 1; + private SwipeRefreshLayout mChannelRefresh; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_xiabi_rank, container, false); + initView(v); + mPage = 1; + getLoveRank(mPage); + return v; + } + + private void initView(View v) { + mRankListView = v.findViewById(R.id.daka_rank_list_view); + mFirstPhoto = v.findViewById(R.id.daka_rank_first_photo); + mSecondPhoto = v.findViewById(R.id.daka_rank_second_photo); + mThirdPhoto = v.findViewById(R.id.daka_rank_third_photo); + mFirstName = v.findViewById(R.id.daka_rank_first_name); + mSecondName = v.findViewById(R.id.daka_rank_second_name); + mThirdName = v.findViewById(R.id.daka_rank_third_name); + mFirstCost = v.findViewById(R.id.daka_rank_first_cost); + mSecondCost = v.findViewById(R.id.daka_rank_second_cost); + mThirdCost = v.findViewById(R.id.daka_rank_third_cost); + mChannelRefresh = v.findViewById(R.id.channel_refresh); + mRankAdpter = new RankAdapter(getActivity()); + mRankAdpter.setRankBeans(mRankDataList); + mRankListView.setAdapter(mRankAdpter); +// mRankListView.dimissEmptyView(); + mRankListView.colorLoadMoreViewByResId(R.drawable.shape_dake_rank_header); + + mRankListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + + boolean enable = false; + if(mRankListView != null && mRankListView.getChildCount() > 0){ + // check if the first item of the list is visible + boolean firstItemVisible = mRankListView.getFirstVisiblePosition() == 0; + // check if the top of the first item is visible + boolean topOfFirstItemVisible = mRankListView.getChildAt(0).getTop() == 0; + // enabling or disabling the refresh layout + enable = firstItemVisible && topOfFirstItemVisible; + } + mChannelRefresh.setEnabled(enable); + + int size = mRankDataList.size() + 3; + int lastPosition = mRankListView.getLastVisiblePosition() + 3; + + if(size != 0 && size % 10 == 0 && !mPageLoad + && lastPosition > size - 2){ + getLoveRank(mPage); + mPageLoad = true; + }else if(lastPosition <= size - 2){ + mPageLoad = false; + } + } + }); + + mFirstPhoto.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (oneId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", oneId); + getActivity().startActivity(intent); + } + } + }); + + mSecondPhoto.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (twoId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", twoId); + getActivity().startActivity(intent); + } + } + }); + + mThirdPhoto.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (threeId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", threeId); + getActivity().startActivity(intent); + } + } + }); + + mChannelRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = 1; + getLoveRank(mPage); + } + }); + } + + //魅力榜 + public void getLoveRank(final int page) { + SettingManager.rankRich((BaseActivity) getActivity(), 3, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(type, result); + if (page == 1) { + notifyRankData(result.getList()); + }else { + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + } + mPage++; + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + mChannelRefresh.setRefreshing(false); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + mChannelRefresh.setRefreshing(false); + } + }); + } + + List rankBeans = new ArrayList<>(); + private boolean mPageLoad = false; + private int oneId; + private int twoId; + private int threeId; + + public void notifyRankData(List rankBeans){ + this.rankBeans = rankBeans; + if (rankBeans.size() == 1) { + final NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = 0; + threeId = 0; + + for (int i = 0; i < 1; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + }else if (rankBeans.size() == 2) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getTotalMoney()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = 0; + + for (int i = 0; i < 2; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + }else if (rankBeans.size() == 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getTotalMoney()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getTotalMoney()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + + }else if (rankBeans.size() > 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getTotalMoney()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getTotalMoney()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } + } + + /** + * 大于一万,用小数表示 + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, double totalMoney) { + if (totalMoney >= 10000) { + double money = totalMoney / 10000; + view.setText(String.format("%.1f", money) + "万"); + }else { + view.setText(String.format("%.0f", totalMoney)); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/register/InfoEditActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/register/InfoEditActivity.java new file mode 100644 index 0000000..e37f742 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/register/InfoEditActivity.java @@ -0,0 +1,550 @@ +package com.fengliyan.tianlesue.view.register; + +import android.Manifest; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import com.bigkoo.pickerview.builder.TimePickerBuilder; +import com.bigkoo.pickerview.listener.OnTimeSelectListener; +import com.bigkoo.pickerview.view.TimePickerView; +import com.facebook.drawee.view.SimpleDraweeView; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.location.LocationManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.controller.settings.manager.UserAvatarManager; +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.login.bean.NickNameBean; +import com.fengliyan.tianlesue.utils.InviteCodeUpdateUtils; +import com.fengliyan.tianlesue.utils.PermissionUtil; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.login.LoginActivity; +import com.fengliyan.tianlesue.view.login.utils.LoginUtils; +import com.fengliyan.tianlesue.view.main.CityPickerActivity; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.picker.citypicker.CityPicker; +import com.fengliyan.uikit.picker.citypicker.adapter.OnPickListener; +import com.fengliyan.uikit.picker.citypicker.model.City; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; + +import java.io.File; +import java.net.URI; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by abby on 2018/3/20. + */ + +public class InfoEditActivity extends BaseActivity implements View.OnClickListener, UserAvatarManager.UserImgListener { + public static final int SINGLE_SELECTOR_REQUEST = 201; + public static final int PERMISSION_REQUEST_CODE = 101; + private TextView changePhotoBtn; + private View mCityLayout; + private View mAgeLayout; + private EditText mNameText; + private EditText mRefereeText; + private TextView mAgeText; + private TextView mCityText; + private SimpleDraweeView mPhoto; + private LinearLayout mConfirmButton; + + private MultiImageSelector mSelector; + private TimePickerView mAgePicker; + private String mPhotoPath; + private String mToken; + private String mPhotoUrl; + private String mCityId; + private boolean isAllPermissionsGranted; + // private Disposable mDisposable; +// private LocationBean mLocationBean; + private String mBirthDay; + LinearLayout manLayout; + LinearLayout womenLayout; + private int isGoLogin = 0; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_info_edit); + setTitleName(""); + setDefaultTitle(); + Title title = getCustomTitle(); + RelativeLayout left = title.findViewById(R.id.rl_base_back); + left.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (isGoLogin == 2) { + startMainActivity(LoginActivity.class); + } + finish(); + } + }); + mManager = new UserAvatarManager(this); + +// OpenInstall.getInstall(new AppInstallAdapter() { +// @Override +// public void onInstall(AppData appData) { +// //获取渠道数据 +// String channelCode = appData.getChannel(); +// //获取自定义数据 +// String bindData = appData.getData(); +// Gson gson = new Gson(); +// InviteCodeBean inviteCodeBean = gson.fromJson(bindData, InviteCodeBean.class); +// if (inviteCodeBean != null) { +// // BaseApplication.getInstance().setInvite_code(inviteCodeBean.getInvite_code()); +// UserManager.setInviteCode(inviteCodeBean.getInvite_code()); +// } + initView(); +// +// } +// }); + + +// initView(); +// initAgePicker(); + +// checkMyPermission(); +// checkNewPermission(); + mSelector = MultiImageSelector.create().single(); + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); + mToken = getIntent().getStringExtra("token"); + isGoLogin = getIntent().getIntExtra("isRegister", 0); +// LocationManager.getInstance().addLocationObserver(new Observer() { +// @Override +// public void onSubscribe(Disposable d) { +// mDisposable = d; +// } +// +// @Override +// public void onNext(LocationBean locationBean) { +// mLocationBean = locationBean; +// mCityText.setText(locationBean.getCity() + ""); +// mCityId = GlobalManager.getCityMap().get(locationBean.getCity()); +// LocationManager.getInstance().stop(); +// CityPicker.getInstance().setLocatedCity(new LocatedCity(locationBean.getCity(), +// locationBean.getProvince(), +// locationBean.getCityCode())); +// mDisposable.dispose(); +// } +// +// @Override +// public void onError(Throwable e) { +// mCityText.setText("北京"); +// } +// +// @Override +// public void onComplete() { +// mCityText.setText("北京"); +// } +// }); + +// checkMyPermission(); + + } + + private void initAgePicker() { + Calendar endCalendar = Calendar.getInstance(); + endCalendar.set(endCalendar.get(Calendar.YEAR) - 18 + , endCalendar.get(Calendar.MONTH) + , endCalendar.get(Calendar.DAY_OF_MONTH)); + + int months_day = endCalendar.get(Calendar.MONTH) + 1; + mBirthDay = endCalendar.get(Calendar.YEAR) + "-" + months_day + "-" + endCalendar.get(Calendar.DATE); + String astro = getAstro(endCalendar.get(Calendar.MONTH) + 1, endCalendar.get(Calendar.DATE)); + mAgeText.setText(mBirthDay + astro); + + Calendar startCalendar = Calendar.getInstance(); + startCalendar.set(1940, 1, 1); + + mAgePicker = new TimePickerBuilder(this, new OnTimeSelectListener() { + @Override + public void onTimeSelect(Date date, View v) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int month = calendar.get(Calendar.MONTH) + 1; + int day = calendar.get(Calendar.DATE); + int year = calendar.get(Calendar.YEAR); + String astro = getAstro(month, day); + mAgeText.setText(year + "-" + month + "-" + day + " " + astro); + mBirthDay = year + "-" + month + "-" + day; + } + }).setRangDate(startCalendar, endCalendar).build(); + + mAgePicker.setDate(endCalendar); + } + + + private String getAstro(int month, int day) { + String[] starArr = {"魔羯座", "水瓶座", "双鱼座", "牡羊座", + "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座"}; + int[] DayArr = {22, 20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22}; // 两个星座分割日 + int index = month; + if (day < DayArr[month - 1]) { + index = index - 1; + } else { + if (month == 12) { + index = 0; + } + } + return starArr[index]; + } + + private void showCityPicker() { + CityPicker.getInstance() + .setFragmentManager(getSupportFragmentManager()) + .enableAnimation(true) + .setOnPickListener(new OnPickListener() { + @Override + public void onPick(int position, City data) { + if (null != data && null != data.getName()) { + mCityText.setText(data.getName()); + mCityId = GlobalManager.getCityMap().get(data.getName()); + } + } + + @Override + public void onLocate() { + if (isAllPermissionsGranted) { + LocationManager.getInstance().start(); + } else { +// checkMyPermission(); + checkNewPermission(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); + } + } + }).show(); + } + + public void onDestroy() { + super.onDestroy(); + if (null != mAgePicker && mAgePicker.isShowing()) { + mAgePicker.dismiss(); + } + + +// if (null != mDisposable && !mDisposable.isDisposed()) { +// mDisposable.dispose(); +// } + } + + private void initView() { + manLayout = findViewById(R.id.manLayout); + womenLayout = findViewById(R.id.womenLayout); + manLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + womenLayout.setSelected(false); + manLayout.setSelected(true); + refreshNickName(); + + + } + }); + womenLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + womenLayout.setSelected(true); + manLayout.setSelected(false); + refreshNickName(); + } + }); + manLayout.setSelected(true); + changePhotoBtn = findViewById(R.id.changePhotoBtn); + mPhoto = (SimpleDraweeView) findViewById(R.id.info_edit_photo); + mCityLayout = findViewById(R.id.info_edit_city_layout); + mCityText = (TextView) findViewById(R.id.info_edit_city_text); + mAgeLayout = findViewById(R.id.info_edit_age_layout); + mAgeText = (TextView) findViewById(R.id.info_edit_age_text); + mNameText = findViewById(R.id.info_edit_name_text); + mRefereeText = findViewById(R.id.info_edit_referee_text); + mConfirmButton = findViewById(R.id.info_edit_confirm_button); + changePhotoBtn.setOnClickListener(this); + mCityLayout.setOnClickListener(this); + mAgeLayout.setOnClickListener(this); + mConfirmButton.setOnClickListener(this); + findViewById(R.id.changeNameBtn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + refreshNickName(); + } + }); + initAgePicker(); +// mNameText.setText(getIntent().getExtras().getString("nickname")); + refreshNickName(); + + } + + public void openPhoto() { + mSelector.single(); + mSelector.start(this, SINGLE_SELECTOR_REQUEST); + } + + private UserAvatarManager mManager; + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (mManager != null) { + mManager.onActivityResult(requestCode, resultCode, data); + } + if (requestCode == SINGLE_SELECTOR_REQUEST && resultCode == RESULT_OK) { +// mPhotoPath = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT).get(0); + List albumList = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + String s = "file://" + albumList.get(0); + mManager.whoStartCropWithUi(Uri.parse(s)); + } else if (requestCode == 1001 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(this, ConsUser.PICKER_CITY + "", city); + if (!TextUtils.isEmpty(city)) { + mCityText.setText(city); + mCityId = GlobalManager.getCityMap().get(city); + } + } + } + } + + private void addPhoto(String path) { + if (path != null) { + File file = new File(path); + if (null != file) { + URI uri = file.toURI(); + mPhoto.setImageURI(uri.toString()); + } + } + } + + @Override + public void onClick(View view) { + if (view == mCityLayout) { + Intent intent = new Intent(this, CityPickerActivity.class); + startActivityForResult(intent, 1001); +// checkNewPermission(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); +// showCityPicker(); + } else if (view == mAgeLayout) { + if (null != mAgePicker) { + InputMethodManager imm = (InputMethodManager) + getSystemService(Context.INPUT_METHOD_SERVICE); + + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + mAgePicker.show(); + } + + } else if (view == changePhotoBtn) { + checkNewPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE); +// openPhoto(); + } else if (view == mConfirmButton) { + + if (TextUtils.isEmpty(mNameText.getText().toString()) || TextUtils.isEmpty(mAgeText.getText().toString())) { + MaleToast.showMessage(InfoEditActivity.this, "个人资料不完善,请更新"); + } else { +// if (null == mCityId) { +// mCityId = "110100"; +// } + + Map map = new HashMap<>(); + map.put("nickname", mNameText.getText().toString()); + + if (manLayout.isSelected()) { + map.put("gender", "2"); + } else { + map.put("gender", "1"); + } + if (!TextUtils.isEmpty(mPhotoPath)) { + map.put("albums", mPhotoUrl); + } +// map.put("city", mCityId); + map.put("birthday", mBirthDay); + if (!mRefereeText.getText().toString().isEmpty()) { + map.put("inviteId", mRefereeText.getText().toString()); + } else { + map.put("inviteId", InviteCodeUpdateUtils.getLocalInviteCode()); + } + completeProfile(map); + } + } + } + + private void checkNewPermission(String... permissions) { + PermissionDialog permissionDialog = new PermissionDialog(this, permissions); + permissionDialog.show(); + XXPermissions.with(this).permission(permissions).request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + permissionDialog.dismiss(); + if (all) { + if (permissions.contains(Manifest.permission.ACCESS_COARSE_LOCATION)) { + isAllPermissionsGranted = true; + LocationManager.getInstance().start(); + } else { + openPhoto(); + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + OnPermissionCallback.super.onDenied(permissions, never); + String str; + if (permissions.contains(Manifest.permission.ACCESS_COARSE_LOCATION)) { + isAllPermissionsGranted = false; + str = "私语请求定位手机权限,是否允许?"; + } else { + str = "私语请求存储权限,是否允许?"; + } + if (never) { + CustomAlertDialog dialog = new CustomAlertDialog(InfoEditActivity.this); + dialog.setTitle(str); + dialog.hideContent(true); + dialog.setRightBtnText("去开启"); + dialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(InfoEditActivity.this); + } + }); + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + dialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + void refreshNickName() { + String gender = "1"; + if (manLayout.isSelected()) { + gender = "2"; + } + RegisterManager.getNickname(this, gender, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, NickNameBean result, String tips) { + mNameText.setText(result.getNickname()); + if (TextUtils.isEmpty(mPhotoPath)) { + mPhoto.setImageURI(StrU.getResourcePath(result.getAvatar(), activity)); +// mPhotoUrl = result.getAvatar(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + public void completeProfile(Map map) { + + RegisterManager.completeProfile(this, map, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final LoginBean result, String message) { + MaleToast.showMessage(InfoEditActivity.this, "资料修改成功"); +// setResult(RESULT_OK); + LoginUtils.checkLoginStatus(InfoEditActivity.this, result, 1); +// EventBus.getDefault().post(new RegisterInfoEvent(result)); +// finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(InfoEditActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showFailureMsg(InfoEditActivity.this, "修改资料错误"); + } + }); + } + + public void uploadHeadPhoto(String photoPath) { + File file = new File(photoPath); + UploadFile[] uploadFiles = new UploadFile[1]; + uploadFiles[0] = new UploadFile("file[" + 0 + "]", file); + + DynamicsManager.uploadImage(this, uploadFiles, "album", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + + if (result != null && result.size() > 0) { + mPhotoUrl = result.get(0).getUrl(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "图片上传失败"); + } + }); + } + + @Override + public void getUserImg(@Nullable String path) { + if (null != path && !TextUtils.isEmpty(path)) { + mPhotoPath = path; + uploadHeadPhoto(mPhotoPath); + addPhoto(mPhotoPath); + + } + } + + @Override + public void onPointerCaptureChanged(boolean hasCapture) { + + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + if (isGoLogin == 2) { + startMainActivity(LoginActivity.class); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/register/RegisterActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/register/RegisterActivity.java new file mode 100644 index 0000000..75697d2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/register/RegisterActivity.java @@ -0,0 +1,344 @@ +package com.fengliyan.tianlesue.view.register; + +import android.content.Intent; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.CodeUtils; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.dialog.PrivateDialogs; +import com.fengliyan.uikit.editor.CaiEditText; +import com.fengliyan.uikit.toast.MaleToast; +import com.netease.htprotect.HTProtect; +import com.netease.htprotect.callback.GetTokenCallback; +import com.netease.htprotect.result.AntiCheatResult; + +/** + * Created by abby on 2018/3/20. + */ + +public class RegisterActivity extends BaseActivity implements View.OnClickListener { + + private Button mRegisterButton; + private Button mSendCodeButton; + private CaiEditText mPhoneEditText; + private CaiEditText mPasswordEditText; + private CaiEditText mAuthCodeEditText; + private TextView mContractTitle; + private boolean isPasswordShowed; + private boolean isCodeSend; + private ImageView captchaImageView; + private String code; + private CaiEditText imageVerifyEditText; + private CheckBox isSelectBox; + private Boolean isSelect = false; + private CountDownTimer mTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + mSendCodeButton.setText((l / 1000) + ""); + } + + //test + @Override + public void onFinish() { + mSendCodeButton.setEnabled(true); + isCodeSend = false; + mSendCodeButton.setText("获取验证码"); + } + }; + + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if (!TextUtils.isEmpty(mPhoneEditText.getText()) + && !TextUtils.isEmpty(mPasswordEditText.getText()) + && !TextUtils.isEmpty(mAuthCodeEditText.getText())) { + mRegisterButton.setEnabled(true); + } else { + mRegisterButton.setEnabled(false); + } + + if (!TextUtils.isEmpty(mPhoneEditText.getText()) && !isCodeSend) { + mSendCodeButton.setEnabled(true); + } else { + mSendCodeButton.setEnabled(false); + } + } + }; + private TextView mAbout_contract_2; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register); + setTitleName("注册"); + setDefaultTitle(); + hideTitleBar(); + dissmissTitleBottomLine(); + initPicCode(); + initView(); + String phoneNumber = getIntent().getStringExtra("phoneNumber"); + mPhoneEditText.setText(phoneNumber); + } + + private void initView() { + findViewById(R.id.backBtn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + mRegisterButton = findViewById(R.id.register_button); + mPhoneEditText = findViewById(R.id.register_phone_num_layout); + mPasswordEditText = findViewById(R.id.register_password_layout); + mAuthCodeEditText = findViewById(R.id.register_verify_edit); + mSendCodeButton = findViewById(R.id.register_send_code_button); + mContractTitle = findViewById(R.id.register_contract_title); + mAbout_contract_2 = findViewById(R.id.about_contract_2); + captchaImageView = findViewById(R.id.image); + imageVerifyEditText = findViewById(R.id.register_image_verify_edit); + isSelectBox = findViewById(R.id.activity_register_select_box); + + captchaImageView.setOnClickListener(this); + mRegisterButton.setOnClickListener(this); + mSendCodeButton.setOnClickListener(this); + mContractTitle.setOnClickListener(this); + mAbout_contract_2.setOnClickListener(this); + isSelectBox.setOnClickListener(this); + mPhoneEditText.getEditText().addTextChangedListener(mTextWatcher); + mPasswordEditText.getEditText().addTextChangedListener(mTextWatcher); + mAuthCodeEditText.getEditText().addTextChangedListener(mTextWatcher); + mPhoneEditText.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + mPhoneEditText.setText(""); + } + }); + + mPasswordEditText.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + if (isPasswordShowed) { + isPasswordShowed = false; + mPasswordEditText.setRightButtonImageById(R.drawable.ic_sign_input2); + mPasswordEditText + .getEditText() + .setTransformationMethod(PasswordTransformationMethod.getInstance()); + mPasswordEditText + .getEditText() + .setSelection(mPasswordEditText.getEditText().getText().length()); + } else { + isPasswordShowed = true; + mPasswordEditText.setRightButtonImageById(R.drawable.ic_sign_input3); + mPasswordEditText + .getEditText() + .setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + mPasswordEditText + .getEditText() + .setSelection(mPasswordEditText.getEditText().getText().length()); + } + } + }); + } + + //获取图形验证码 + public void initPicCode() { + RegisterManager.getPicCode(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + if (ConstUrl.LOGDEBUG) Log.d("ssz", tips); + code = result.toString(); + captchaImageView.setImageBitmap(CodeUtils.getInstance().createBitmap(code)); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + + @Override + public void onClick(View view) { + if (view == mRegisterButton) { + if (isSelect) { + register(mPhoneEditText.getText(), + mPasswordEditText.getText(), + mAuthCodeEditText.getText(), + "1", + UserManager.getInviteCode()); + } else { + PrivateDialogs.getInstace().message("").sure("同意").cancle("取消") + .setOnTipItemClickListener(new PrivateDialogs.OnTipItemClickListener() { + @Override + public void cancleClick() { + } + + @Override + public void sureClick() { + isSelectBox.setChecked(true); + isSelect = true; + register(mPhoneEditText.getText(), + mPasswordEditText.getText(), + mAuthCodeEditText.getText(), + "1", + UserManager.getInviteCode()); + + } + + @Override + public void userClick() { + Intent intent = new Intent(RegisterActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } + + @Override + public void termsClick() { + Intent intent = new Intent(RegisterActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } + }).create(this); + } + + } else if (view == mSendCodeButton) { + sendCode(mPhoneEditText.getText()); + } else if (view == mContractTitle) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } else if (view == mAbout_contract_2) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } else if (view == captchaImageView) { + initPicCode(); + } else if (view == isSelectBox) { + if (isSelect) { + isSelectBox.setChecked(false); + isSelect = false; + } else { + isSelectBox.setChecked(true); + isSelect = true; + } + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mTimer) { + mTimer.cancel(); + } + } + + public void register(final String userName, final String password, String authCode, String agreement, String inviteCode) { + HTProtect.getTokenAsync(3000, "8eda6854bb5a63940348f0325659a527", new GetTokenCallback() { + @Override + public void onResult(AntiCheatResult antiCheatResult) { + NoClearSPUtils.saveString(RegisterActivity.this, "x-risk-engine-token", antiCheatResult.token); + RegisterManager.register(RegisterActivity.this, userName, password, inviteCode, agreement, authCode, false, antiCheatResult.token, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + DeviceManager.getInstance().setToken(result.getUserinfo().getToken()); + NoClearSPUtils.saveString(activity, "token", result.getUserinfo().getToken()); +// Intent newIntent = new Intent(); +// newIntent.putExtra("UserName", userName); +// newIntent.putExtra("Password", password); + if (null != result.getUserinfo().getInvite_code()) { + UserManager.setInviteResult(true); + } + +// setResult(RESULT_OK, newIntent); + Intent intent = new Intent(RegisterActivity.this, InfoEditActivity.class); + intent.putExtra("nickname", result.getUserinfo().getNickname()); + startActivity(intent); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + }); + } + + public void sendCode(String number) { + if (StringUtil.isEmpty(mPhoneEditText.getText().toString())) { + MaleToast.showFailureMsg(RegisterActivity.this, "请输入您的手机号码"); + return; + } + if (StringUtil.isEmpty(imageVerifyEditText.getText().toString())) { + MaleToast.showFailureMsg(RegisterActivity.this, "请输入图片验证码"); + return; + } + if (!imageVerifyEditText.getText().toString().toLowerCase().equals(code.toLowerCase())) { + MaleToast.showFailureMsg(RegisterActivity.this, "图片验证码错误"); + return; + } + RegisterManager.sendAuthCode(this, number, code, "register", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + mTimer.start(); + mSendCodeButton.setEnabled(false); + isCodeSend = true; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/AboutActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/AboutActivity.java new file mode 100644 index 0000000..f886a7a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/AboutActivity.java @@ -0,0 +1,233 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.Manifest; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.os.Bundle; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.appcompat.app.AlertDialog; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.tianlesue.BuildConfig; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.main.SystemVersionBean; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.login.utils.LoginUtils; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.main.dialog.UpdateDialog; +import com.fengliyan.uikit.toast.MaleToast; + +import java.io.File; +import java.util.List; + +public class AboutActivity extends BaseActivity implements View.OnClickListener { + private TextView mAppNameView; + private TextView mContract1; + private TextView tv_icp; + private TextView mContract2; + private RelativeLayout mRl_version; + public static final String DOWNLOAD_PATH = ConstUrl.DEFAULT_PATH + "/cache/"; + private UpdateDialog mUpdateDialog; + private String mDownloadUrl; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_about); + setDefaultTitle(); + setTitleName("关于私语"); + initView(); + } + + private void initView() { + mAppNameView = findViewById(R.id.about_name); + mContract1 = findViewById(R.id.about_contract_1); + mContract2 = findViewById(R.id.about_contract_2); + tv_icp = findViewById(R.id.tv_icp); + mRl_version = findViewById(R.id.rl_version); + mContract1.setOnClickListener(this); + mContract2.setOnClickListener(this); + mRl_version.setOnClickListener(this); + tv_icp.setOnClickListener(this); + findViewById(R.id.about_logo).setOnClickListener(this); + mAppNameView.setText(getAppName() + getVersionName()); + + mUpdateDialog = new UpdateDialog(this, R.style.SelectiveDialog); + mUpdateDialog.setConfirmListener(new UpdateDialog.DownloadConfirmListener() { + @Override + public void onConfirm() { + permissionDialog = new PermissionDialog(AboutActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}); + permissionDialog.show(); + XXPermissions.with(AboutActivity.this) + .permission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + File file = new File(DOWNLOAD_PATH); + if (file.isFile()) { + file.delete(); + } + + if (!file.exists()) { + file.mkdirs(); + } + + MainManager.downloadNewApp(AboutActivity.this, mDownloadUrl, + DOWNLOAD_PATH + "temp.apk", + new HttpCallback() { + @Override + public void onFailure(int httpStatusCode, String message, Throwable throwable) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } + } + + @Override + public void onSuccess(int httpStatusCode, String responseObject) { + if (null != mUpdateDialog && mUpdateDialog.isShowing()) { + mUpdateDialog.dismiss(); + } +// checkIsAndroidO(); + LoginUtils.install(DOWNLOAD_PATH + "temp.apk", AboutActivity.this); + } + + @Override + public void onProgress(long bytesCount, long contentLength, boolean done) { + mUpdateDialog.setProgress((int) (((double) bytesCount) / contentLength * 100)); + } + }); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + permissionDialog.dismiss(); + } + }); + } + + @Override + public void onCancel() { + + } + }); + } + + @Override + public void onClick(View view) { + if (view == mContract1) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.AGREEMENT_URL); + startActivity(intent); + } else if (view == mContract2) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.USER_PRIVACY_URL); + startActivity(intent); + } else if (view == mRl_version) { + getVersion(); + } else if (view.getId() == R.id.about_logo) { + setEnvironmentType(); + } else if (view.getId() == R.id.tv_icp) { + Intent intent = new Intent(this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", "https://beian.miit.gov.cn"); + startActivity(intent); + } + } + + private PermissionDialog permissionDialog; + + private void getVersion() { + MainManager.checkUpdate(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final SystemVersionBean result, String message) { + mUpdateDialog.setCancelable(false); + mDownloadUrl = result.getDownloadurl(); + mUpdateDialog.setInfo(result.getUpgradetext()); + mUpdateDialog.setVersionName(result.getNewversion()); + if (result.getVersioncode() > LoginUtils.getVersionCode(AboutActivity.this)) { + mUpdateDialog.show(); + } else { + MaleToast.showMessage(AboutActivity.this, "您已是最新版本"); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(AboutActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + public String getAppName() { + try { + PackageManager packageManager = getPackageManager(); + PackageInfo packageInfo = packageManager.getPackageInfo( + getPackageName(), 0); + return packageInfo.applicationInfo.loadLabel(packageManager).toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public String getVersionName() { + PackageManager pm = getPackageManager(); + try { + PackageInfo packageInfo = pm.getPackageInfo(getPackageName(), 0); + return packageInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + } + return null; + } + + //切换开发环境 + private void setEnvironmentType() { + if (BuildConfig.IS_DEV) { + String msg = ""; + if (NoClearSPUtils.getBoolean(AboutActivity.this, Constans.ENVIRONMENT_TYPE, true)) { + msg = "当前为开发环境"; + } else { + msg = "当前为正式环境"; + } + AlertDialog dialog = new AlertDialog.Builder(this).create(); + dialog.setMessage(msg); + dialog.setButton(DialogInterface.BUTTON_POSITIVE, "切换,重启后生效", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + NoClearSPUtils.saveBoolean(AboutActivity.this, Constans.ENVIRONMENT_TYPE, !NoClearSPUtils.getBoolean(AboutActivity.this, Constans.ENVIRONMENT_TYPE, true)); + } + }); + dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + dialog.show(); + dialog.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(Color.BLACK); + dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(Color.BLACK); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/AddSkillActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/AddSkillActivity.java new file mode 100644 index 0000000..031a6ee --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/AddSkillActivity.java @@ -0,0 +1,165 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.view.View; +import android.widget.Button; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.AddSkillRecyclerAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.main.SkillAnchorBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class AddSkillActivity extends BaseActivity implements View.OnClickListener { + private RecyclerView mChannelList; + private AddSkillRecyclerAdapter mRecyclerAdapter; + private List dataList = new ArrayList<>(); + private List mSelectedSkillList = new ArrayList<>(); + private Button mSelectedButton; + private int mIndex = -1; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_add_skill); + setDefaultTitle(); + setTitleName("添加技能"); + initView(); + getAllChannelData(); + } + + private boolean isAddSkill = false; + + private void initView() { + mChannelList = findViewById(R.id.add_skill_list_view); + mSelectedButton = findViewById(R.id.add_skill_select_button); + mSelectedButton.setOnClickListener(this); + mRecyclerAdapter = new AddSkillRecyclerAdapter(this); + mRecyclerAdapter.setSkillList(dataList); + mRecyclerAdapter.setOnItemClickListener(new AddSkillRecyclerAdapter.OnItemClickListener() { + @Override + public void onItemClicked(View v, int position) { + SkillAnchorBean bean = dataList.get(position); + if (2 == bean.getStatus() || 1 == bean.getIs_add()) { + return; + } + + // + if (isAddSkill) { + MaleToast.showMessage(AddSkillActivity.this, "已经添加过技能"); + }else { + if(0 == bean.getStatus()) { + bean.setStatus(3); //出现勾 + mSelectedSkillList.add(bean); + }else if(3 == bean.getStatus()){ + bean.setStatus(0); //消失勾 + mSelectedSkillList.remove(bean); + } + + if (mIndex != -1 && mIndex != position) { + SkillAnchorBean bean1 = dataList.get(mIndex); + if (3 == bean1.getStatus()) { + bean1.setStatus(0); + mSelectedSkillList.remove(bean1); + } + } + if (0 != mSelectedSkillList.size()) { + mSelectedButton.setEnabled(true); + } else { + mSelectedButton.setEnabled(false); + } + mIndex = position; + mRecyclerAdapter.notifyDataSetChanged(); + } + } + }); + + mChannelList.setAdapter(mRecyclerAdapter); + mChannelList.setLayoutManager(new StaggeredGridLayoutManager(3, + StaggeredGridLayoutManager.VERTICAL)); + + } + + private void getAllChannelData() { + SettingManager.getMySkill(this, new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + dataList = result; + if (null != dataList) { //判断是否添加过技能 + int size = dataList.size(); + if (size != 0) { + for (int i = 0; i < size; i++) { + SkillAnchorBean skillAnchorBean = dataList.get(i); + if (skillAnchorBean.getIs_add() == 1 || skillAnchorBean.getStatus() == 2) { + isAddSkill = true; + break; + } + } + } + } + mRecyclerAdapter.setSkillList(dataList); + mRecyclerAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void addSkills() { + Iterator iterator = mSelectedSkillList.iterator(); + StringBuilder stringBuilder = new StringBuilder(); + int count = 0; + while (iterator.hasNext()) { + SkillAnchorBean bean = iterator.next(); + if (count != 0) { + stringBuilder.append(","); + } + + stringBuilder.append(bean.getId() + ""); + count++; + } + + SettingManager.addSkill(this, stringBuilder.toString(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(AddSkillActivity.this, "技能添加成功"); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(AddSkillActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(AddSkillActivity.this, "技能添加失败"); + } + }); + } + + @Override + public void onClick(View view) { + if (view == mSelectedButton) { + addSkills(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BeAnchorActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BeAnchorActivity.java new file mode 100644 index 0000000..8bc89b0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BeAnchorActivity.java @@ -0,0 +1,283 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.eventBus.BeAnchorEvent; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.settings.BeAnchorStatusBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.view.settings.dialog.BeAnchorDialog; + +import de.greenrobot.event.EventBus; + +/** + * 成为女神界面 + */ +public class BeAnchorActivity extends BaseActivity implements View.OnClickListener { + public static int REQUEST_BE_ANCHOR = 100; + public static int REQUEST_BE_PHONE = 101; + private Button mContractButton; + private Button mSelfieButton; + private Button mAlbumButton; + private Button mSkillButton; + private Button mConfirmButton; + private TextView mAbnormalStatus; + private int agree; //0代表未同意,1代表同意 + private String mTip; + private BeAnchorDialog mBeAnchorDialog; + private int mAudit_status; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_be_daka); + setDefaultTitle(); + setTitleName("真人认证"); + initView(); + mBeAnchorDialog = new BeAnchorDialog(this, new BeAnchorDialog.OnClickListener() { + @Override + public void onClick() { + BeAnchorActivity.super.finishActivity(); + } + }); + + } + + private void initView() { + mContractButton = findViewById(R.id.be_anchor_button_contract); + mSelfieButton = findViewById(R.id.be_anchor_button_selfie); + mAlbumButton = findViewById(R.id.be_anchor_button_album); + mSkillButton = findViewById(R.id.be_anchor_button_skill); + mConfirmButton = findViewById(R.id.be_anchor_button_confirm); + mAbnormalStatus = findViewById(R.id.be_anchor_abnormal_status); + mConfirmButton.setOnClickListener(this); + mSelfieButton.setOnClickListener(this); + mAlbumButton.setOnClickListener(this); + mSkillButton.setOnClickListener(this); + mContractButton.setOnClickListener(this); + } + + private void getAnchorStatus() { + SettingManager.getAnchorStatus(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BeAnchorStatusBean result, String message) { + mTip = result.getTip(); + mAudit_status = result.getAudit_status(); + if (1 == result.getAnchor_status()) { + anchorStatus(); + } else { + if (1 == result.getApply_status()) { + verifyStatus("审核中"); + } else if (3 == result.getApply_status()) { + verifyStatus("审核通过"); + } else { + agree = result.getAgree_protocol(); + if (1 == result.getAgree_protocol()) { + readyStatus(0); + } + + if (1 == result.getCamera_status()) { + readyStatus(1); + } + if (1 == result.getPhoto_status()) { + readyStatus(2); + } + + if (1 == result.getSkill_status()) { + readyStatus(3); + } + + if (1 == result.getAgree_protocol() && 1 == result.getCamera_status() && 1 == result.getPhoto_status() && 1 == result.getSkill_status()) { + mConfirmButton.setEnabled(true); + mConfirmButton.setText("提交申请"); + } + } + + if (2 == result.getApply_status()) { + mAbnormalStatus.setText("抱歉,审核不通过"); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + protected void onStart() { + getAnchorStatus(); + super.onStart(); + } + + @Override + public void onActivityResult(int request, int result, Intent intent) { + super.onActivityResult(request, result, intent); + if (request == REQUEST_BE_ANCHOR && result == RESULT_OK) { + // getAnchorStatus(); + } else if (request == REQUEST_BE_PHONE && result == RESULT_OK) { + startActivityForResult(new Intent(this, CertificationActivity.class), REQUEST_BE_ANCHOR); + } + } + + private void anchorStatus() { + mContractButton.setBackgroundResource(R.drawable.be_gray); + mContractButton.setText("已完成"); + mSelfieButton.setBackgroundResource(R.drawable.be_gray); + mSelfieButton.setText("已完成"); + mAlbumButton.setBackgroundResource(R.drawable.be_gray); + mAlbumButton.setText("已完成"); + mSkillButton.setBackgroundResource(R.drawable.be_gray); + mSkillButton.setText("已完成"); + mConfirmButton.setEnabled(false); + mConfirmButton.setText("你已经是主播"); + } + + private void verifyStatus(String message) { + mContractButton.setBackgroundResource(R.drawable.be_gray); + mContractButton.setText("已完成"); + mSelfieButton.setBackgroundResource(R.drawable.be_gray); + mSelfieButton.setText("已完成"); + mAlbumButton.setBackgroundResource(R.drawable.be_gray); + mAlbumButton.setText("已完成"); + mSkillButton.setBackgroundResource(R.drawable.be_gray); + mSkillButton.setText("已完成"); + mConfirmButton.setEnabled(false); + mConfirmButton.setText(message); + } + + private void readyStatus(int finishIndex) { + switch (finishIndex) { + case 0: + mContractButton.setBackgroundResource(R.drawable.be_gray); + mContractButton.setText("已完成"); + break; + case 1: + mSelfieButton.setBackgroundResource(R.drawable.be_gray); + mSelfieButton.setText("已完成"); + break; + case 2: + mAlbumButton.setBackgroundResource(R.drawable.be_gray); + mAlbumButton.setText("已完成"); + break; + case 3: + mSkillButton.setBackgroundResource(R.drawable.be_gray); + mSkillButton.setText("已完成"); + break; + } + + +// mConfirmButton.setEnabled(true); +// mConfirmButton.setText("提交申请"); + } + + private void apply() { + SettingManager.apply(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(BeAnchorActivity.this, "申请成功"); + setAnchor(); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(BeAnchorActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(BeAnchorActivity.this, "申请失败,请重试"); + } + }); + } + + /** + * 设置成为主播后is_anchor字段的改变 + */ + private void setAnchor() { + BaseUserInfo userInfo = UserManager.getInstance().getUserInfo(); + userInfo.setIs_anchor(1); + UserManager.getInstance().notifyUserInfoChanged(userInfo); + UserManager.setUserInfo(userInfo); + + LoginBean loginBean = (LoginBean) StorageManager.getInstance(BeAnchorActivity.this).getBean("loginBean", LoginBean.class); + loginBean.getUserinfo().setIs_anchor(1); + + //修改后本地要进行储存更新 + StorageManager.getInstance(BeAnchorActivity.this).putBean("loginBean", loginBean); + + EventBus.getDefault().post(new BeAnchorEvent()); + } + + @Override + public void onClick(View view) { + if (view == mContractButton) { + Intent intent = new Intent(this, ContractActivity.class); + intent.putExtra("agree", agree); + startActivityForResult(intent, REQUEST_BE_ANCHOR); + } else if (view == mSelfieButton) { + // 判断是否绑定了电话 没绑定走绑定 + if (TextUtils.isEmpty(SPUtils.getString(this, ConsUser.MOBILE))) { + Intent intent = new Intent(this, BindPhoneConfirmActivity.class); + intent.putExtra("bindPhone", "banding"); + startActivityForResult(intent, REQUEST_BE_PHONE); + } else { + Intent intent = new Intent(this, CertificationActivity.class); + startActivityForResult(intent, REQUEST_BE_ANCHOR); + } + } else if (view == mAlbumButton) { + Intent intent = new Intent(this, InfoEditActivity.class); + startActivityForResult(intent, REQUEST_BE_ANCHOR); + } else if (view == mSkillButton) { + Intent intent = new Intent(this, AddSkillActivity.class); + startActivityForResult(intent, REQUEST_BE_ANCHOR); + } else if (view == mConfirmButton) { + apply(); + } + } + + @Override + public void finishActivity() { + if (!TextUtils.isEmpty(mTip)) { + if (mAudit_status == 0) + mBeAnchorDialog.show(mTip); + else{ + MaleToast.showMessage(this, mTip); + super.finishActivity(); + } + } else + super.finishActivity(); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + finishActivity(); + return true; + } + return super.onKeyUp(keyCode, event); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BeautySettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BeautySettingActivity.java new file mode 100644 index 0000000..4be23fb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BeautySettingActivity.java @@ -0,0 +1,525 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.Manifest; +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.TextureView; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.enumeration.FUAIProcessorEnum; +import com.faceunity.core.model.facebeauty.FaceBeauty; +import com.faceunity.core.model.facebeauty.FaceBeautyBlurTypeEnum; +import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum; +import com.faceunity.nama.FURenderer; +import com.faceunity.nama.control.FaceBeautyControlView; +import com.faceunity.nama.data.FaceUnityDataFactory; +import com.faceunity.nama.listener.FURendererListener; +import com.faceunity.nama.repo.FaceBeautySource; +import com.faceunity.nama.ui.FaceUnityView; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.agora.framework.PreprocessorFaceUnity; +import com.fengliyan.tianlesue.agora.profile.CSVUtils; +import com.fengliyan.tianlesue.utils.BeautySPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.uikit.toast.MaleToast; + +import java.io.File; +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; + +import io.agora.capture.video.camera.CameraVideoManager; +import io.agora.capture.video.camera.Constant; +import io.agora.capture.video.camera.VideoCapture; +import io.agora.rtc.RtcEngine; + +/** + * Created by zhangbin on 2019/1/19. + */ + +public class BeautySettingActivity extends BaseActivity implements SensorEventListener, View.OnClickListener { + private static final String TAG = "BeautySettingActivity"; + + private static final int CAPTURE_WIDTH = 1280; + private static final int CAPTURE_HEIGHT = 720; + private static final int CAPTURE_FRAME_RATE = 24; + + private final FURenderer mFURenderer = FURenderer.getInstance(); + private CameraVideoManager mVideoManager; + private FaceUnityDataFactory mFaceUnityDataFactory; + private PreprocessorFaceUnity preprocessor; + private SensorManager mSensorManager; + private FaceBeauty faceBeauty; + + private TextureView local_video_view; + private RelativeLayout rl_beauty_container; + private TextView mIvBeautyShow; + private ImageView mIvCancel; + private TextView mTvRecover; + private TextView mIvBeautyOpen; + private TextView mIvBeautySave; + private TextView mTvBeautySwitch; + + private boolean isClose = false; + private FaceBeautyControlView mFaceBeautyControlView; + private float remoteX1 = 0; + private float remoteX2 = 0; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final Window win = getWindow(); + win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + win.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); + + setContentView(R.layout.activity_beauty_setting); + + hideTitleBar(); + local_video_view = findViewById(R.id.local_video_view); + mIvBeautyShow = findViewById(R.id.iv_beauty_show); + mIvCancel = findViewById(R.id.iv_cancel); + mTvRecover = findViewById(R.id.tv_default); + mIvBeautyOpen = findViewById(R.id.tv_open); + mIvBeautySave = findViewById(R.id.iv_beauty_save); + mTvBeautySwitch = findViewById(R.id.tv_camera); + rl_beauty_container = findViewById(R.id.rl_beauty_container); + + mIvBeautyShow.setOnClickListener(this); + mIvCancel.setOnClickListener(this); + mTvRecover.setOnClickListener(this); + mIvBeautyOpen.setOnClickListener(this); + mIvBeautySave.setOnClickListener(this); + mTvBeautySwitch.setOnClickListener(this); + //权限允许 + PermissionDialog permissionDialog = new PermissionDialog(this, new String[]{Manifest.permission.CAMERA}); + permissionDialog.show(); + XXPermissions.with(this) + .permission(new String[]{Manifest.permission.CAMERA}) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + initVideoModule(); + mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); + mFURenderer.bindListener(mFURendererListener); + String sdkVersion = RtcEngine.getSdkVersion(); + Log.i(TAG, "onCreate: agora sdk version " + sdkVersion); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + permissionDialog.dismiss(); + String market = DeviceManager.getInstance().getApplicationMarket(); + if (market != null && market.equals("huawei")) { + finish(); + } + } + }); +// initCsvUtil(this); + if (preprocessor != null) { + preprocessor.setCSVUtils(mCSVUtils); + } + + local_video_view.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent event) { + if (MotionEvent.ACTION_DOWN == event.getAction()) {//按下 + remoteX1 = event.getX(); + if (null != rl_beauty_container) { + if (rl_beauty_container.getVisibility() == View.VISIBLE) { + rl_beauty_container.setVisibility(View.GONE); + } + } + } + if (MotionEvent.ACTION_UP == event.getAction()) { + remoteX2 = event.getX(); + if (null != rl_beauty_container && (Math.abs(remoteX2 - remoteX1) < 100)) { + if (rl_beauty_container.getVisibility() == View.VISIBLE) { + rl_beauty_container.setVisibility(View.GONE); + } + } + } + return true; + } + }); + } + + private void onCameraChangeRequested() { + preprocessor.doGLAction(() -> Log.e("ECRP", "test doGLAction thread id:" + Thread.currentThread().getId())); + + mVideoManager.switchCamera(); + } + + /** + * FURenderer状态回调 + */ + private final FURendererListener mFURendererListener = new FURendererListener() { + @Override + public void onTrackStatusChanged(FUAIProcessorEnum type, int status) { + /*runOnUiThread(() -> { + mTrackingText.setText(type == FUAIProcessorEnum.FACE_PROCESSOR ? R.string.toast_not_detect_face : R.string.toast_not_detect_body); + mTrackingText.setVisibility(status > 0 ? View.INVISIBLE : View.VISIBLE); + });*/ + } + + @Override + public void onFpsChanged(double fps, double callTime) { + + } + }; + + private void initVideoModule() { + mVideoManager = new CameraVideoManager(this, new PreprocessorFaceUnity(this)); + mVideoManager.setCameraStateListener(new VideoCapture.VideoCaptureStateListener() { + @Override + public void onFirstCapturedFrame(int width, int height) { + Log.i(TAG, "onFirstCapturedFrame: " + width + "x" + height); + } + + @Override + public void onCameraCaptureError(int error, String msg) { + Log.i(TAG, "onCameraCaptureError: error:" + error + " " + msg); + if (mVideoManager != null) { + // When there is a camera error, the capture should + // be stopped to reset the internal states. + mVideoManager.stopCapture(); + } + } + + @Override + public void onCameraClosed() { + + } + }); + preprocessor = (PreprocessorFaceUnity) mVideoManager.getPreprocessor(); + //mTrackingText = findViewById(R.id.iv_face_detect); + FaceUnityView faceUnityView = findViewById(R.id.fu_view); + mFaceBeautyControlView = faceUnityView.getFaceBeautyControlView(); + mFaceBeautyControlView.setListener(new FaceBeautyControlView.ViewDownListener() { + @Override + public void ViewDown() { + rl_beauty_container.setVisibility(View.GONE); + } + }); + + //美颜是关闭状态 + isClose = BeautySPUtils.getBoolean("isClose"); + changeFaceBeautySwitchUI(isClose); + + String beautySettings = BeautySPUtils.getString("newFaceBeautySettings"); + Log.i(TAG, "setBeauty: beautySettings----->" + beautySettings); + if (beautySettings != null && !beautySettings.isEmpty()) { + Type type = new TypeToken>() { + }.getType(); + HashMap clonedMap = new Gson().fromJson(beautySettings, type); + faceBeauty = FaceBeautySource.hashMapToFaceBeauty(clonedMap); + } + + if (faceBeauty == null) { + Log.i("美颜", "开始设置数据"); + FaceBeauty recommendFaceBeauty = new FaceBeauty(new FUBundleData(FaceBeautySource.BUNDLE_FACE_BEAUTIFICATION)); + recommendFaceBeauty.setFilterName(FaceBeautyFilterEnum.ZIRAN_1); + recommendFaceBeauty.setFilterIntensity(0.4); + /*美肤*/ + recommendFaceBeauty.setBlurType(FaceBeautyBlurTypeEnum.FineSkin); + recommendFaceBeauty.setBlurIntensity(3); // 赋值范围0-6 + recommendFaceBeauty.setColorIntensity(0.3); + recommendFaceBeauty.setRedIntensity(0.3); + recommendFaceBeauty.setSharpenIntensity(0.2); + recommendFaceBeauty.setEyeBrightIntensity(0); + recommendFaceBeauty.setToothIntensity(0); + recommendFaceBeauty.setRemovePouchIntensity(0); + recommendFaceBeauty.setRemoveLawPatternIntensity(0); + + /*美型*/ + recommendFaceBeauty.setCheekThinningIntensity(0);//瘦脸 + recommendFaceBeauty.setCheekVIntensity(0.5);//V脸 + recommendFaceBeauty.setCheekNarrowIntensity(0);//窄脸 + recommendFaceBeauty.setCheekSmallIntensity(0);//小脸 + recommendFaceBeauty.setEyeEnlargingIntensity(0.4);//大眼 + recommendFaceBeauty.setChinIntensity(0.3);//下巴 + recommendFaceBeauty.setForHeadIntensity(0.3);//额头 + recommendFaceBeauty.setNoseIntensity(0.3);//瘦鼻 + recommendFaceBeauty.setMouthIntensity(0.4);//嘴型 + recommendFaceBeauty.setCanthusIntensity(0);//开眼角 + recommendFaceBeauty.setEyeSpaceIntensity(0.5);//眼距 + recommendFaceBeauty.setEyeRotateIntensity(0.5);//眼睛角度 + recommendFaceBeauty.setLongNoseIntensity(0.5);//鼻子长度 + recommendFaceBeauty.setPhiltrumIntensity(0.5);//缩人中 + recommendFaceBeauty.setSmileIntensity(0); //微笑嘴角 + faceBeauty = recommendFaceBeauty; + } + FaceBeautySource.setCustomFaceBeauty(faceBeauty); + mFaceUnityDataFactory = new FaceUnityDataFactory(0); + faceUnityView.bindDataFactory(mFaceUnityDataFactory); + setEnableFaceBeautySwitch(isClose); + + mVideoManager.setPictureSize(CAPTURE_WIDTH, CAPTURE_HEIGHT); + mVideoManager.setFrameRate(CAPTURE_FRAME_RATE); + mVideoManager.setFacing(Constant.CAMERA_FACING_FRONT); + mVideoManager.setLocalPreviewMirror(Constant.MIRROR_MODE_AUTO); + mVideoManager.setLocalPreview(local_video_view); + + preprocessor.setSurfaceListener(new PreprocessorFaceUnity.SurfaceViewListener() { + @Override + public void onSurfaceCreated() { + Log.i(TAG, "onSurfaceCreated: -------->"); + mFaceUnityDataFactory.bindCurrentRenderer(); + } + + @Override + public void onSurfaceDestroyed() { + mFURenderer.release(); + } + }); + + local_video_view.setOnClickListener(this); + } + + private void changeFaceBeautySwitchUI(boolean isClose) { + if (isClose) { + mIvBeautyOpen.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(this, R.drawable.ic_beauty_setting_off), null, null); + mIvBeautyOpen.setText("关闭"); + } else { + mIvBeautyOpen.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(this, R.drawable.ic_beauty_setting_on), null, null); + mIvBeautyOpen.setText("开启"); + } + } + + /** + * 设置是否开启美颜 + * + * @param isClose true-关闭美颜 + */ + private void setEnableFaceBeautySwitch(boolean isClose) { + if (mFaceBeautyControlView != null) { + mFaceBeautyControlView.setEnableFaceBeauty(!isClose); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (preprocessor != null) { + preprocessor.releaseFURender(); + } + if (mVideoManager != null) { + mVideoManager.stopCapture(); + } + if (mSensorManager != null) { + mSensorManager.unregisterListener(this); + } + } + + @Override + public void onResume() { + super.onResume(); + if (mSensorManager != null) { + Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL); + } + if (preprocessor != null) { + preprocessor.setRenderEnable(true); + } + if (mVideoManager != null) { + mVideoManager.startCapture(); + } + } + + @Override + public void onDestroy() { + mVideoManager = null; + super.onDestroy(); + } + + /** + * public static float sSkinDetect = 1.0f;//精准磨皮 + * public static float sHeavyBlur = 0.0f;//美肤类型 + * public static float sHeavyBlurLevel = 0.7f;//磨皮 + * public static float sBlurLevel = 0.7f;//磨皮 + * public static float sColorLevel = 0.5f;//美白 + * public static float sRedLevel = 0.5f;//红润 + * public static float sEyeBright = 0.0f;//亮眼 + * public static float sToothWhiten = 0.0f;//美牙 + *

+ * public static float sFaceShape = 4.0f;//脸型 + * public static float sFaceShapeLevel = 1.0f;//程度 + * public static float sEyeEnlarging = 0.4f;//大眼 + * public static float sEyeEnlargingOld = 0.4f;//大眼 + * public static float sCheekThinning = 0.4f;//瘦脸 + * public static float sCheekThinningOld = 0.4f;//瘦脸 + * public static float sIntensityChin = 0.3f;//下巴 + * public static float sIntensityForehead = 0.3f;//额头 + * public static float sIntensityNose = 0.5f;//瘦鼻 + * public static float sIntensityMouth = 0.4f;//嘴形 + * + * @param view + */ + @Override + public void onClick(View view) { + if (view == mIvBeautyShow) { //显示美颜设置 + rl_beauty_container.setVisibility(View.VISIBLE); + } else if (view == mIvCancel) { //取消 + showLeaveMessage(); + } else if (view == mTvRecover) { //恢复默认 + if (mFaceBeautyControlView != null) { + mFaceBeautyControlView.faceBeautyRecoverData(); + } + setEnableFaceBeautySwitch(false); + } else if (view == mIvBeautyOpen) { + if (isClose) {//打开美颜 + isClose = false; + changeFaceBeautySwitchUI(false); + setEnableFaceBeautySwitch(false); + } else {//关闭美颜 + isClose = true; + changeFaceBeautySwitchUI(true); + setEnableFaceBeautySwitch(true); + } + + } else if (view == mIvBeautySave) { //保存美颜设置 + showLeaveMessage(); + } else if (view == mTvBeautySwitch) { //前后摄像头切换 + preprocessor.skipFrame(); + onCameraChangeRequested(); + } else if (view == local_video_view) { + rl_beauty_container.setVisibility(View.GONE); + } + } + + private void showLeaveMessage() { + CustomAlertDialog dialog = new CustomAlertDialog(this); + dialog.setTitle("是否保存美颜设置?"); + dialog.hideContent(true); + dialog.setOnDialogClickListener(new CustomAlertDialog.OnDialogLeftClickListener() { + @Override + public void leftClick() { + finishActivity(); + } + }, new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + setBeauty(); + finishActivity(); + } + }); + dialog.show(); + } + + @Override + public void onSensorChanged(SensorEvent event) { + if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + if (Math.abs(x) > 3 || Math.abs(y) > 3) { + if (Math.abs(x) > Math.abs(y)) { + mFURenderer.setDeviceOrientation(x > 0 ? 0 : 180); + } else { + mFURenderer.setDeviceOrientation(y > 0 ? 90 : 270); + } + } + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (null != rl_beauty_container) { + if (rl_beauty_container.getVisibility() == View.VISIBLE) { + rl_beauty_container.setVisibility(View.GONE); + } else { + if (mFaceBeautyControlView != null && mFaceBeautyControlView.isFaceBeautyDataChange()) { + showLeaveMessage(); + } else { + finishActivity(); + } + } + } + return true; + } + return super.onKeyDown(keyCode, event); + } + + private void setBeauty() { + if (isClose) { //美颜是关闭状态 保存 + BeautySPUtils.saveBoolean("isClose", true); + } else { //美颜是打开状态 + if (mFaceUnityDataFactory != null && mFaceUnityDataFactory.mFaceBeautyDataFactory != null) { + FaceBeauty beauty = mFaceUnityDataFactory.mFaceBeautyDataFactory.getCurrentFaceBeauty(); + if (beauty != null) { + HashMap hashMap = FaceBeautySource.faceBeautyToHashMap(beauty); + Gson gson = new Gson(); + String beautySettings = gson.toJson(hashMap); + Log.i(TAG, "setBeauty: beautySettings----->" + beautySettings); + BeautySPUtils.saveString("newFaceBeautySettings", beautySettings); + BeautySPUtils.saveBoolean("isSet", true); + BeautySPUtils.saveBoolean("isClose", false); + } + } else { + MaleToast.showMessage(this, "美颜设置保存失败"); + } + } + } + + private static final int ENCODE_FRAME_WIDTH = 960; + private static final int ENCODE_FRAME_HEIGHT = 540; + private static final int ENCODE_FRAME_BITRATE = 1000; + private static final int ENCODE_FRAME_FPS = 30; + private CSVUtils mCSVUtils; + + private void initCsvUtil(Context context) { + mCSVUtils = new CSVUtils(context); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault()); + String dateStrDir = format.format(new Date(System.currentTimeMillis())); + dateStrDir = dateStrDir.replaceAll("-", "").replaceAll("_", ""); + SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()); + String dateStrFile = df.format(new Date()); + String filePath = com.fengliyan.tianlesue.agora.profile.Constant.filePath + dateStrDir + File.separator + "excel-" + dateStrFile + ".csv"; + Log.d(TAG, "initLog: CSV file path:" + filePath); + StringBuilder headerInfo = new StringBuilder(); + headerInfo.append("version:").append(FURenderer.getInstance().getVersion()).append(CSVUtils.COMMA) + .append("机型:").append(android.os.Build.MANUFACTURER).append(android.os.Build.MODEL).append(CSVUtils.COMMA) + .append("处理方式:双输入纹理输出").append(CSVUtils.COMMA) + .append("编码方式:硬件编码").append(CSVUtils.COMMA) + .append("编码分辨率:").append(ENCODE_FRAME_WIDTH).append("x").append(ENCODE_FRAME_HEIGHT).append(CSVUtils.COMMA) + .append("编码帧率:").append(ENCODE_FRAME_FPS).append(CSVUtils.COMMA) + .append("编码码率:").append(ENCODE_FRAME_BITRATE).append(CSVUtils.COMMA) + .append("预览分辨率:").append(CAPTURE_WIDTH).append("x").append(CAPTURE_HEIGHT).append(CSVUtils.COMMA) + .append("预览帧率:").append(CAPTURE_FRAME_RATE).append(CSVUtils.COMMA); + mCSVUtils.initHeader(filePath, headerInfo); + //mCSVUtils.setRtcEngineEventHandler(((BaseApplication) getApplication()).getRtcEventHandler()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BillActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BillActivity.java new file mode 100644 index 0000000..777b302 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BillActivity.java @@ -0,0 +1,246 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.view.View; +import android.widget.AbsListView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.BillAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.BillBean; +import com.fengliyan.tianlesue.model.settings.BillListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; +import com.fengliyan.uikit.refresh.LoadMoreListView; + +import java.util.ArrayList; +import java.util.List; + +public class BillActivity extends BaseActivity implements View.OnClickListener { + private int mType = 0; + private LoadMoreListView mListView; + private BillAdapter mBillAdapter; + private List mBillBeans = new ArrayList<>(); + private int mPage = 1; + private int mAccountType = 0; + private int mAccountCat = 0; + private boolean mPageLoad; + private BottomSelectiveDialog mSelectiveDialog; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_bill); + mType = getIntent().getIntExtra("type", 0); + + if (mType == 0) { + setRightCustomTextTitle("账单明细", "筛选", new View.OnClickListener() { + @Override + public void onClick(View view) { + mSelectiveDialog = new BottomSelectiveDialog(BillActivity.this, R.style.SelectiveDialog); + mSelectiveDialog.addSelectButton("全部账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 0; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + + mSelectiveDialog.addSelectButton("充值账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 1; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + + mSelectiveDialog.addSelectButton("提现账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 2; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + + mSelectiveDialog.addSelectButton("音视频账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 3; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + + mSelectiveDialog.addSelectButton("礼物账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 4; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + mSelectiveDialog.addSelectButton("私信账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 7; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + + mSelectiveDialog.addSelectButton("守护账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 9; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + mSelectiveDialog.addSelectButton("系统账单", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 5; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); + mSelectiveDialog.addSelectButton("VIP分成", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mSelectiveDialog.dismiss(); + mAccountType = 0; + mAccountCat = 20; + mPage = 1; + mBillBeans.clear(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + }); +// mSelectiveDialog.addSelectButton("兑换账单", new BottomSelectiveDialog.OnButtonSelectListener() { +// @Override +// public void onClicked(View view, int index) { +// mSelectiveDialog.dismiss(); +// mAccountType = 0; +// mAccountCat = 6; +// mPage = 1; +// mBillBeans.clear(); +// getBillInfo(mAccountType, mAccountCat, mPage); +// } +// }); + + +// mSelectiveDialog.addSelectButton("工会账单", new BottomSelectiveDialog.OnButtonSelectListener() { +// @Override +// public void onClicked(View view, int index) { +// mSelectiveDialog.dismiss(); +// mAccountType = 0; +// mAccountCat = 10; +// mPage = 1; +// mBillBeans.clear(); +// getBillInfo(mAccountType, mAccountCat, mPage); +// } +// }); + mSelectiveDialog.show(); + } + }); + } else if (1 == mType) { + setTitleName("充值记录"); + mAccountType = 1; + mAccountCat = 1; + } else { + setTitleName("充值记录"); + mAccountType = 3; + mAccountCat = 1; + } + + initView(); + getBillInfo(mAccountType, mAccountCat, mPage); + } + + private void initView() { + mListView = findViewById(R.id.bill_list); + mBillAdapter = new BillAdapter(this); + mBillAdapter.setBillList(mBillBeans); + mListView.setAdapter(mBillAdapter); + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (mBillBeans.size() != 0 && mBillBeans.size() % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mBillBeans.size() - 2) { +// getBillInfo(mType, mPage); + getBillInfo(mAccountType, mAccountCat, mPage); + mPageLoad = true; + } else if (mListView.getLastVisiblePosition() <= mBillBeans.size() - 2) { + mPageLoad = false; + } + + } + }); + } + + private void getBillInfo(int type, int cateId, int page) { + SettingManager.getBillList(this, type, cateId, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BillListBean result, String message) { + mBillBeans.addAll(result.getList()); + mBillAdapter.notifyDataSetChanged(); + mPage++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mSelectiveDialog && mSelectiveDialog.isShowing()) { + mSelectiveDialog.dismiss(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindAliActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindAliActivity.java new file mode 100644 index 0000000..d262164 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindAliActivity.java @@ -0,0 +1,136 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.AccountBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +public class BindAliActivity extends BaseActivity implements View.OnClickListener{ + private EditText mNameView; + private EditText mAccountView; + private Button mConfirmButton; + EditText phoneField; + EditText idField; + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if(TextUtils.isEmpty(mNameView.getText().toString()) + || TextUtils.isEmpty(mAccountView.getText().toString())){ + mConfirmButton.setEnabled(false); + }else{ + mConfirmButton.setEnabled(true); + } + } + }; + + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName("绑定支付宝"); + setContentView(R.layout.activity_bind_ali); + initView(); + getAccountInfo(); + } + + private void initView(){ + phoneField = findViewById(R.id.phoneField); + idField = findViewById(R.id.idField); + mNameView = findViewById(R.id.bind_account_name); + mAccountView = findViewById(R.id.bind_account_account); + mConfirmButton = findViewById(R.id.bind_account_confirm_button); + mNameView.addTextChangedListener(mTextWatcher); + mAccountView.addTextChangedListener(mTextWatcher); + mConfirmButton.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if(mConfirmButton == view){ + bindAccount(); + } + } + + private void getAccountInfo(){ + SettingManager.getAccountInfo(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, AccountBean result, String message) { + String card_account = result.getCard_account(); + String card_name = result.getCard_name(); + if (!TextUtils.isEmpty(card_name)) { + mNameView.setText(card_name); + } + + if (!TextUtils.isEmpty(card_account)) { + mAccountView.setText(card_account); + } + if (!TextUtils.isEmpty(result.getMobile())){ + phoneField.setText(result.getMobile()); + } + if (!TextUtils.isEmpty(result.getCard())){ + idField.setText(result.getCard()); + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void bindAccount(){ + String name = mNameView.getText().toString(); + String account = mAccountView.getText().toString(); + String id = idField.getText().toString(); + String phone = phoneField.getText().toString(); + if (TextUtils.isEmpty(name)||TextUtils.isEmpty(account)||TextUtils.isEmpty(id)||TextUtils.isEmpty(phone)){ + MaleToast.showMessage(this,"请完善账户信息"); + return; + } + SettingManager.bindAccount(this, name, + account,id,phone, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { + MaleToast.showMessage(BindAliActivity.this, "绑定成功"); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(BindAliActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(BindAliActivity.this, "绑定失败"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindBankActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindBankActivity.java new file mode 100644 index 0000000..da871e7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindBankActivity.java @@ -0,0 +1,151 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.uikit.ContentWithSpaceEditText; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.BankInfoBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import java.util.List; + +public class BindBankActivity extends BaseActivity implements View.OnClickListener{ + private EditText nameField; + private ContentWithSpaceEditText bankAccountField; + private Button mConfirmButton; + EditText phoneField; + EditText bankNameField; + EditText idField; + TextView tipLabel; + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if(TextUtils.isEmpty(nameField.getText().toString()) + || TextUtils.isEmpty(bankAccountField.getText().toString()) + ||TextUtils.isEmpty(bankNameField.getText().toString()) + ||TextUtils.isEmpty(phoneField.getText().toString()) + ||TextUtils.isEmpty(idField.getText().toString()) + ){ + mConfirmButton.setEnabled(false); + }else{ + mConfirmButton.setEnabled(true); + } + } + }; + + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName("绑定银行卡"); + setContentView(R.layout.activity_bind_bank); + initView(); + getAccountInfo(); + } + + private void initView(){ + tipLabel = findViewById(R.id.tipLabel); + phoneField = findViewById(R.id.phoneField); + bankNameField = findViewById(R.id.bankNameField); + nameField = findViewById(R.id.bind_account_name); + idField = findViewById(R.id.idField); + bankAccountField = findViewById(R.id.bind_account_account); + bankAccountField.setContentType(ContentWithSpaceEditText.TYPE_BANK_CARD); + mConfirmButton = findViewById(R.id.bind_account_confirm_button); + nameField.addTextChangedListener(mTextWatcher); + bankAccountField.addTextChangedListener(mTextWatcher); + mConfirmButton.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if(mConfirmButton == view){ + bindAccount(); + } + } + + private void getAccountInfo(){ + SettingManager.bank(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BankInfoBean result, String tips) { + phoneField.setText(result.getMobile()+""); + bankAccountField.setText(result.getCard_account()+""); + bankNameField.setText(result.getBank()+""); + nameField.setText(result.getCard_name()+""); + if (!TextUtils.isEmpty(result.getCard())){ + idField.setText(result.getCard()+""); + } + StringBuilder builder = new StringBuilder(); + List tipArray = result.getDescribe(); + for (int i = 0;i() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + MaleToast.showMessage(BindBankActivity.this, "绑定成功"); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(BindBankActivity.this, tip); + + } + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(BindBankActivity.this, "绑定失败"+e.getMessage()); + + } + }); + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindPhoneActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindPhoneActivity.java new file mode 100644 index 0000000..fc50572 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindPhoneActivity.java @@ -0,0 +1,406 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.model.settings.SelfieExampleBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.settings.BindInfoBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.xinlingwu.share.ShareManager; + +import java.util.Map; + +public class BindPhoneActivity extends BaseActivity implements View.OnClickListener { + public static int REQUEST_BIND_PHONE = 211; + private View mBindPhoneView; + private RelativeLayout rl_change_mobile; + private TextView tv_change_mobile; + private RelativeLayout rl_change_password; + private TextView tv_set_password; + private TextView tv_change_password; + private RelativeLayout bind_real_name; + private RelativeLayout bind_certification; + private View mBindWeixinView; + private View mBindQQView; + private View mBindWeiboView; + private TextView mBindPhoneText; + private TextView bind_real_name_text; + private TextView bind_certification_text; + private TextView mBindWeixinText; + private TextView mBindQQText; + private TextView mBindWeiboText; + private int mBlueColor; + private int mGrayColor; + private RelativeLayout rl_delete_account; + + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName("账号与安全"); + setContentView(R.layout.activity_bind_phone); + mBlueColor = Color.parseColor("#26a1f4"); + mGrayColor = Color.parseColor("#999999"); + initView(); + getBindData(); + } + + private void initView() { + mBindPhoneView = findViewById(R.id.bind_phone_confirm); + rl_change_mobile = findViewById(R.id.rl_change_mobile); + tv_change_mobile = findViewById(R.id.tv_change_mobile); + rl_change_password = findViewById(R.id.rl_change_password); + tv_set_password = findViewById(R.id.tv_set_password); + tv_change_password = findViewById(R.id.tv_change_password); + bind_real_name = findViewById(R.id.bind_real_name); + bind_certification = findViewById(R.id.bind_certification); + mBindWeixinView = findViewById(R.id.bind_phone_confirm_weixin); + mBindQQView = findViewById(R.id.bind_phone_confirm_qq); + mBindWeiboView = findViewById(R.id.bind_phone_confirm_weibo); + mBindPhoneText = findViewById(R.id.bind_phone_confirm_text); + bind_real_name_text = findViewById(R.id.bind_real_name_text); + bind_certification_text = findViewById(R.id.bind_certification_text); + mBindWeixinText = findViewById(R.id.bind_phone_confirm_weixin_text); + mBindQQText = findViewById(R.id.bind_phone_confirm_qq_text); + mBindWeiboText = findViewById(R.id.bind_phone_confirm_weibo_text); + rl_delete_account = findViewById(R.id.rl_delete_account); + mBindPhoneView.setOnClickListener(this); + rl_change_mobile.setOnClickListener(this); + rl_change_password.setOnClickListener(this); + bind_real_name.setOnClickListener(this); + bind_certification.setOnClickListener(this); + mBindWeixinView.setOnClickListener(this); + mBindQQView.setOnClickListener(this); + mBindWeiboView.setOnClickListener(this); + rl_delete_account.setOnClickListener(this);//注销账号 + + if (UserManager.getUserInfo().isWomen()) { + bind_certification.setVisibility(View.VISIBLE); + getSelfieExample(); + } else { + bind_certification.setVisibility(View.GONE); + } + } + + private BindInfoBean mBindInfoBean; + + private void getBindData() { + SettingManager.getBindInfo(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BindInfoBean result, String message) { + mBindInfoBean = result; + if ("".equals(result.getMobile())) { + mBindPhoneText.setText("去绑定"); + mBindPhoneText.setTextColor(mBlueColor); + rl_change_mobile.setVisibility(View.GONE); + } else { + mBindPhoneText.setText(result.getMobile()); + mBindPhoneText.setTextColor(mGrayColor); + rl_change_mobile.setVisibility(View.VISIBLE); + tv_change_mobile.setTextColor(mBlueColor); + } + if (TextUtils.equals("1", result.getIs_set_pwd())) { + tv_set_password.setText("修改密码"); + tv_change_password.setText("去修改"); + } else { + tv_set_password.setText("设置密码"); + tv_change_password.setText("去设置"); + } + tv_change_password.setTextColor(mBlueColor); + if (TextUtils.equals("1", result.getReal_name_status())) { + bind_real_name_text.setText("已实名"); + bind_real_name_text.setTextColor(mGrayColor); + } else { + bind_real_name_text.setText("去实名"); + bind_real_name_text.setTextColor(mBlueColor); + } + if ("".equals(result.getWechat())) { + mBindWeixinText.setText("去绑定"); + mBindWeixinText.setTextColor(mBlueColor); + } else { + mBindWeixinText.setText(result.getWechat()); + mBindWeixinText.setTextColor(mGrayColor); + } + + if ("".equals(result.getQq())) { + mBindQQText.setText("去绑定"); + mBindQQText.setTextColor(mBlueColor); + } else { + mBindQQText.setText(result.getQq()); + mBindQQText.setTextColor(mGrayColor); + } + + if ("".equals(result.getWeibo())) { + mBindWeiboText.setText("去绑定"); + mBindWeiboText.setTextColor(mBlueColor); + } else { + mBindWeiboText.setText(result.getWeibo()); + mBindWeiboText.setTextColor(mGrayColor); + } + +// mBindPhoneText.setText("".equals(result.getMobile()) ? "去绑定": result.getMobile()); +// mBindWeixinText.setText("".equals(result.getWechat()) ? "去绑定": result.getWechat()); +// mBindQQText.setText("".equals(result.getQq()) ? "去绑定": result.getQq()); +// mBindWeiboText.setText("".equals(result.getWeibo()) ? "去绑定": result.getWeibo()); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void getSelfieExample() { + SettingManager.getSelfieExample(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SelfieExampleBean result, String message) { + //人脸认证-1未认证0认证中1认证成功2认证失败 + if (StrU.equals("0", result.getFace_status())) { + bind_certification_text.setText("认证中"); + bind_certification_text.setTextColor(mGrayColor); + } else if (StrU.equals("1", result.getFace_status())) { + bind_certification_text.setText("已认证"); + bind_certification_text.setTextColor(mGrayColor); + } else { + bind_certification_text.setText("去认证"); + bind_certification_text.setTextColor(mBlueColor); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void bindPlatform(String platform, String openid, String token) { + SettingManager.bindPlatform(this, platform, openid, token, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(BindPhoneActivity.this, "绑定成功"); + getBindData(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(BindPhoneActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(BindPhoneActivity.this, "绑定失败"); + + } + }); + } + + public void showConfirmDialog() { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(BindPhoneActivity.this); + customAlertDialog.hideTitle(true); +// customAlertDialog.setTitle("账号注销"); + + + customAlertDialog.setContent("注销账号将清理所有数据不可恢复\n" + + "该操作不可撤销,请谨慎对待"); + customAlertDialog.setRightBtnText("确定"); + customAlertDialog.setLeftBtnText("取消"); + customAlertDialog.setCanceledOnTouchOutside(false); + customAlertDialog.show(); + customAlertDialog.setOnDialogClickListener(new CustomAlertDialog.OnDialogLeftClickListener() { + @Override + public void leftClick() { + customAlertDialog.dismiss(); + } + }, new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + startActivity(new Intent(BindPhoneActivity.this, CancellationActivity.class)); +// deleteAccount(); + } + }); + } + + //注销账号 + public void deleteAccount() { + SettingManager.deleteAccount(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + UserManager.getInstance().notifyUserInfoChanged(new BaseUserInfo()); + StorageManager.getInstance(BindPhoneActivity.this).clear(); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + + @Override + public void onClick(View view) { + if (view == mBindPhoneView) { + if (null != mBindInfoBean) { + if (TextUtils.isEmpty(mBindInfoBean.getMobile()) || mBindInfoBean.getMobile().equals("")) { + Intent intent = new Intent(BindPhoneActivity.this, + BindPhoneConfirmActivity.class); + startActivityForResult(intent, REQUEST_BIND_PHONE); + } else { + MaleToast.showMessage(BindPhoneActivity.this, "您已经绑定了手机号"); + } + } + } else if (view == rl_change_mobile) { + Intent intent = new Intent(this, VerifyCodeActivity.class); + intent.putExtra("mobile", mBindInfoBean.getMobile()); + intent.putExtra("OriginMobile", mBindInfoBean.getOrigin_mobile()); + startActivity(intent); + + } else if (view == rl_change_password) { + Intent intent = new Intent(this, ChangePasswordActivity.class); + intent.putExtra("type", mBindInfoBean.getIs_set_pwd()); + startActivity(intent); + } else if (view == bind_real_name) { + if (null != mBindInfoBean) { + if (!TextUtils.equals("1", mBindInfoBean.getReal_name_status())) { + Intent intent = new Intent(BindPhoneActivity.this, RealNameActivity.class); + startActivityForResult(intent, REQUEST_BIND_PHONE); + } + } + } else if (view == mBindWeixinView) { + if (null != mBindInfoBean) { + if (TextUtils.isEmpty(mBindInfoBean.getWechat()) || mBindInfoBean.getWechat().equals("")) { + if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_WEIXIN)) { + MaleToast.showMessage(this, "请先安装微信"); + return; + } + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map params) { + String uid = (null == params.get("uid")) ? params.get("unionid") : params.get("uid"); + String accessToken = params.get("accessToken"); + bindPlatform("wechat", uid, accessToken); + } + + @Override + public void error() { + + } + + @Override + public void cancel() { + + } + }, this, ShareManager.TYPE_WEIXIN); + } else { + MaleToast.showMessage(BindPhoneActivity.this, "您已经绑定了微信"); + } + } + } else if (view == mBindQQView) { + if (null != mBindInfoBean) { + if (TextUtils.isEmpty(mBindInfoBean.getQq()) || mBindInfoBean.getQq().equals("")) { + if (!ShareManager.getInstance().isInstalled(this, ShareManager.TYPE_QQ)) { + MaleToast.showMessage(this, "请先安装QQ"); + return; + } + + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map params) { + String uid = (null == params.get("uid")) ? params.get("unionid") : params.get("uid"); + String accessToken = params.get("accessToken"); + bindPlatform("qq", uid, accessToken); + } + + @Override + public void error() { + + } + + @Override + public void cancel() { + + } + }, this, ShareManager.TYPE_QQ); + } + } else { + MaleToast.showMessage(BindPhoneActivity.this, "您已经绑定了QQ"); + } + } else if (view == mBindWeiboView) { + if (null != mBindInfoBean.getWeibo()) { + if (TextUtils.isEmpty(mBindInfoBean.getWeibo())) { + ShareManager.getInstance().verify(new ShareManager.iAuthStatus() { + @Override + public void success(Map params) { + String uid = (null == params.get("uid")) ? params.get("unionid") : params.get("uid"); + String accessToken = params.get("accessToken"); + bindPlatform("weibo", uid, accessToken); + } + + @Override + public void error() { + + } + + @Override + public void cancel() { + + } + }, this, ShareManager.TYPE_WEIBO); + } else { + MaleToast.showMessage(BindPhoneActivity.this, "您已经绑定了微博"); + } + } + } else if (view == rl_delete_account) { + showConfirmDialog(); + // deleteAccount(); + } else if (view == bind_certification) { + Intent intentApplyBigCast = new Intent(this, EditVerifyInfoActivity.class); + startActivityForResult(intentApplyBigCast, 201); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + ShareManager.getInstance().onActivityResult(this, requestCode, resultCode, data); + if (REQUEST_BIND_PHONE == requestCode && RESULT_OK == resultCode) { + getBindData(); + } + if (requestCode == 201) { + if (200 == resultCode) { + getSelfieExample(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindPhoneConfirmActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindPhoneConfirmActivity.java new file mode 100644 index 0000000..2e9b7cf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BindPhoneConfirmActivity.java @@ -0,0 +1,233 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.CodeUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.editor.CaiEditText; +import com.fengliyan.uikit.toast.MaleToast; + +public class BindPhoneConfirmActivity extends BaseActivity implements View.OnClickListener{ + private Button mConfirmButton; + private Button mSendCodeButton; + private CaiEditText mPhoneEditText; + private CaiEditText mAuthCodeEditText; + private CaiEditText mBind_password_layout; + private TextView mConfirmTitle; + private boolean isCodeSend; + private boolean isPasswordShowed; + private ImageView captchaImageView; + private String code; + private CaiEditText imageVerifyEditText; + private CountDownTimer mTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + mSendCodeButton.setText((l / 1000) + ""); + } + + @Override + public void onFinish() { + mSendCodeButton.setEnabled(true); + isCodeSend = false; + mSendCodeButton.setText("获取验证码"); + + } + }; + + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if(!TextUtils.isEmpty(mPhoneEditText.getText()) + && !TextUtils.isEmpty(mBind_password_layout.getText()) + && !TextUtils.isEmpty(mAuthCodeEditText.getText())){ + mConfirmButton.setEnabled(true); + }else{ + mConfirmButton.setEnabled(false); + } + + if(!TextUtils.isEmpty(mPhoneEditText.getText()) && !isCodeSend){ + mSendCodeButton.setEnabled(true); + }else{ + mSendCodeButton.setEnabled(false); + } + } + }; + + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName("绑定手机"); + setContentView(R.layout.activity_bind_phone2); + initPicCode(); + initView(); + } + + private void initView(){ + mConfirmButton = findViewById(R.id.bind_phone_confirm_confirm); + mSendCodeButton = findViewById(R.id.bind_phone_confirm_code_button); + mPhoneEditText = findViewById(R.id.bind_phone_confirm_edit); + mBind_password_layout = findViewById(R.id.bind_password_layout); + mAuthCodeEditText = findViewById(R.id.bind_phone_confirm_code_input); + mConfirmTitle = findViewById(R.id.bind_phone_confirm_title); + captchaImageView= findViewById(R.id.image); + imageVerifyEditText= findViewById(R.id.register_image_verify_edit); + + captchaImageView.setOnClickListener(this); + mSendCodeButton.setEnabled(false); + mConfirmButton.setEnabled(false); + mConfirmButton.setOnClickListener(this); + mSendCodeButton.setOnClickListener(this); + mPhoneEditText.getEditText().addTextChangedListener(mTextWatcher); + mBind_password_layout.getEditText().addTextChangedListener(mTextWatcher); + mAuthCodeEditText.getEditText().addTextChangedListener(mTextWatcher); + + mPhoneEditText.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + mPhoneEditText.setText(""); + } + }); + + mConfirmTitle.setVisibility(TextUtils.isEmpty(getIntent().getStringExtra("bindPhone")) ? View.GONE : View.VISIBLE); + + mBind_password_layout.setRightButtonFunction(new CaiEditText.OnRightFunctionButtonClickListener() { + @Override + public void onClick(View v) { + if(isPasswordShowed){ + isPasswordShowed = false; + mBind_password_layout.setRightButtonImageById(R.drawable.ic_sign_input2); + mBind_password_layout + .getEditText() + .setTransformationMethod(PasswordTransformationMethod.getInstance()); + mBind_password_layout + .getEditText() + .setSelection(mBind_password_layout.getEditText().getText().length()); + }else{ + isPasswordShowed = true; + mBind_password_layout.setRightButtonImageById(R.drawable.ic_sign_input3); + mBind_password_layout + .getEditText() + .setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + mBind_password_layout + .getEditText() + .setSelection(mBind_password_layout.getEditText().getText().length()); + } + } + }); + } + + public void sendCode(String number){ + if(StringUtil.isEmpty(mPhoneEditText.getText().toString())){ + MaleToast.showFailureMsg(BindPhoneConfirmActivity.this, "请输入您的手机号码"); + return; + } + if(StringUtil.isEmpty(imageVerifyEditText.getText().toString())){ + MaleToast.showFailureMsg(BindPhoneConfirmActivity.this, "请输入图片验证码"); + return; + } + if(!imageVerifyEditText.getText().toString().toLowerCase().equals(code.toLowerCase())){ + MaleToast.showFailureMsg(BindPhoneConfirmActivity.this, "图片验证码错误"); + return; + } + RegisterManager.sendAuthCode(this, number,code, "bind", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + mTimer.start(); + isCodeSend = true; + mSendCodeButton.setEnabled(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showFailureMsg(activity, "验证码获取失败"); + } + }); + } + + public void bindPhone(final String phone, String code, String password){ + SettingManager.bindPhone(this, phone, code, password, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + SPUtils.saveString(activity, ConsUser.MOBILE, phone); + MaleToast.showMessage(BindPhoneConfirmActivity.this, "绑定成功"); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(BindPhoneConfirmActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(BindPhoneConfirmActivity.this, "绑定失败"); + } + }); + } + //获取图形验证码 + public void initPicCode(){ + RegisterManager.getPicCode(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + if(ConstUrl.LOGDEBUG) Log.d("ssz",tips); + code=result.toString(); + captchaImageView.setImageBitmap(CodeUtils.getInstance().createBitmap(code)); + } + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + @Override + public void onClick(View view) { + if(view == mSendCodeButton){ + sendCode(mPhoneEditText.getText()); + }else if(view == mConfirmButton){ + bindPhone(mPhoneEditText.getText(), mAuthCodeEditText.getText(), mBind_password_layout.getText()); + }else if(view==captchaImageView){ + initPicCode(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/BlackListActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BlackListActivity.java new file mode 100644 index 0000000..971b7f1 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/BlackListActivity.java @@ -0,0 +1,130 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.text.TextUtils; +import android.widget.AbsListView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.BlackAdapter; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.main.BlackBean; +import com.fengliyan.tianlesue.model.settings.SocialBean; +import com.fengliyan.tianlesue.model.settings.SocialListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +public class BlackListActivity extends BaseActivity { + private LoadMoreListView mListView; + private BlackAdapter mSocailAdapter; + private List mDataList = new ArrayList<>(); + private boolean mPageLoad; + private int mPage = 1; + + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setTitleName("黑名单"); + setContentView(R.layout.activity_black_list); + initView(); + getBlackListData(mPage); + } + + private void initView(){ + mListView = findViewById(R.id.black_list_view); + mSocailAdapter = new BlackAdapter(this); + mSocailAdapter.setSocialBeans(mDataList); + mListView.setAdapter(mSocailAdapter); + + mSocailAdapter.setOnButtonClickedListener(new BlackAdapter.OnButtonClickedListener() { + + @Override + public void onCliked(int position, String userId) { + if (!TextUtils.isEmpty(userId) && !"0".equals(userId)) { + black(position, userId); + } + } + }); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if(mDataList.size() != 0 && mDataList.size() % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mDataList.size() - 2){ + getBlackListData(mPage); + mPageLoad = true; + }else if(mListView.getLastVisiblePosition() <= mDataList.size() - 2){ + mPageLoad = false; + } + + } + }); + } + + private void getBlackListData(final int page){ + SettingManager.getBlackList(this, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SocialListBean result, String message) { + mDataList.addAll(result.getList()); + mSocailAdapter.notifyDataSetChanged(); + mPage ++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void black(final int position, String userId) { + MainManager.doBlack(this, userId, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BlackBean result, String message) { + if (null != result) { + String action = result.getAction(); + if (!TextUtils.isEmpty(action)) { + if (action.equals("add")) { + MaleToast.showMessage(BlackListActivity.this, "你已将对方拉黑"); + }else if (action.equals("delete")){ + if (mDataList != null) { + if (mDataList.size() != 0) { + mDataList.remove(position); + mSocailAdapter.notifyDataSetChanged(); + } + } + + MaleToast.showMessage(BlackListActivity.this, "取消拉黑"); + } + } + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "拉黑失败"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/CaibeiRechargeActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CaibeiRechargeActivity.java new file mode 100644 index 0000000..748dcaf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CaibeiRechargeActivity.java @@ -0,0 +1,629 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.alipay.sdk.app.PayTask; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.eventBus.PayEvent; +import com.fengliyan.tianlesue.controller.settings.adapter.RechargeAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.ScreenUtil; +import com.fengliyan.tianlesue.model.settings.PayBean; +import com.fengliyan.tianlesue.model.settings.RechargeBean; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.model.settings.WXPayTypeBean; +import com.fengliyan.tianlesue.model.settings.WeChatPayInfoBean; +import com.fengliyan.tianlesue.utils.PayUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.PayWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; +import com.sand.qzf.paytypesdk.base.CallBack; +import com.sand.qzf.paytypesdk.base.PayTypeSdk; +import com.sand.qzf.paytypesdk.base.Resp; +import com.tencent.mm.opensdk.modelpay.PayReq; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import de.greenrobot.event.EventBus; + +public class CaibeiRechargeActivity extends BaseActivity implements View.OnClickListener { + public static int SDK_PAY_FLAG = 101; + private TextView mAmount; + private RecyclerView mRechargeGoodList; + private Button mConfirmButton; + private TextView caibei_recharge_hint; + private RechargeAdapter mRechargeAdapter; + private List mRechargeList = new ArrayList<>(); + private View mSelectedGoodView; + private int mSelectedGoodPosition = 1; + private boolean isSelected = false; + private String mSelectedPayMethod = "alipay"; + private String mOrderInfo; + private int payType = 1; + private Runnable mPayRunnable = new Runnable() { + + @Override + public void run() { + PayTask alipay = new PayTask(CaibeiRechargeActivity.this); + Map result = alipay.payV2(mOrderInfo, true); + Message msg = new Message(); + msg.what = SDK_PAY_FLAG; + msg.obj = result; + mHandler.sendMessage(msg); + } + }; + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + Uri uri = intent.getData(); + if (uri != null) { + String payCode = uri.getQueryParameter("payCode"); // 支付宝支付完后返回app后 所传的code + if (ConstUrl.LOGDEBUG) Log.e("TAG", "payCode:" + payCode); // 2为成功 + } + } + + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + if (msg.what == SDK_PAY_FLAG) { + getRechargeInfo(mSelectedPayMethod); + } + } + }; + private LinearLayout mLlRechargeAlipay; + private LinearLayout ll_recharge_way; + private LinearLayout lin_alipay; + private LinearLayout lin_wechat_pay; + private View pay_line; + private TextView mTvRechargeAlipay; + private LinearLayout mLlRechargeWinxin; + private TextView mTvRechargeWinxin; + private int mSelectedWay; + private int mSelectWay; + private ImageView mIvAlipay; + private ImageView mIvWinxin; + private ImageView mIvAlipayImage; + private ImageView mIvWinxinImage; + private ImageView mIweixin; + private Bitmap mResource; + boolean isWXHF;//微信支付是否是走汇付的微信小程序 + private String ghOriId; + private int mini_program_type; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_caibei_recharge); + EventBus.getDefault().register(this); + initTitle(); + initView(); + + if (TextUtils.equals("1", StorageManager.getInstance(this).getString(Constans.DEFAULT_PAY_TYPE))) { + payType = 0; + } else { + payType = 1; + } + if (payType == 0) { //支付宝支付 + mRechargeAdapter.setWXRecharge(false); + mTvRechargeAlipay.setTextColor(mSelectedWay); + mTvRechargeWinxin.setTextColor(mSelectWay); + mIvAlipay.setVisibility(View.VISIBLE); + mIvWinxin.setVisibility(View.INVISIBLE); + mIvAlipayImage.getBackground().setAlpha(255); + mIvWinxinImage.getBackground().setAlpha(100); + mSelectedPayMethod = "alipay"; + } else { //微信支付 + mRechargeAdapter.setWXRecharge(false); + mTvRechargeAlipay.setTextColor(mSelectWay); + mTvRechargeWinxin.setTextColor(mSelectedWay); + mIvAlipay.setVisibility(View.INVISIBLE); + mIvWinxin.setVisibility(View.VISIBLE); + mIvAlipayImage.getBackground().setAlpha(100); + mIvWinxinImage.getBackground().setAlpha(255); + mSelectedPayMethod = "wechat"; + } +// getRechargeInfo(mSelectedPayMethod); + } + + void getWXPayType() { + SettingManager.getWechatPaySite(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WXPayTypeBean result, String tips) { + isWXHF = result.getWechat_type() == 3; + ghOriId = result.getGh_ori_id(); + mini_program_type = result.getMini_program_type(); + confirmToPay(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void initView() { + mAmount = findViewById(R.id.caibei_recharge_pay); + mRechargeGoodList = findViewById(R.id.caibei_recharge_listview); + mConfirmButton = findViewById(R.id.caibei_recharge_confirm_button); + + mLlRechargeAlipay = findViewById(R.id.ll_recharge_alipay); + mTvRechargeAlipay = findViewById(R.id.tv_recharge_alipay); + mLlRechargeWinxin = findViewById(R.id.ll_recharge_weixin); + mTvRechargeWinxin = findViewById(R.id.tv_recharge_weixin); + ll_recharge_way = findViewById(R.id.ll_recharge_way); + lin_alipay = findViewById(R.id.lin_alipay); + lin_wechat_pay = findViewById(R.id.lin_wechat_pay); + pay_line = findViewById(R.id.pay_line); + mIvAlipay = findViewById(R.id.iv_alipay); + mIvWinxin = findViewById(R.id.iv_weixin); + mIvAlipayImage = findViewById(R.id.iv_alipay_image); + mIvWinxinImage = findViewById(R.id.iv_weixin_image); + caibei_recharge_hint = findViewById(R.id.caibei_recharge_hint); + StrU.setSpanTextColor(caibei_recharge_hint.getText().toString(), caibei_recharge_hint.getText().length() - 4, caibei_recharge_hint.getText().length(), caibei_recharge_hint, R.color.email_color, this); + + caibei_recharge_hint.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + NimUIKit.startP2PSession(CaibeiRechargeActivity.this, "4"); + } + }); + + mIweixin = findViewById(R.id.caibei_recharge_confirm_weixin); + mIweixin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(CaibeiRechargeActivity.this, "长按保存到图库", Toast.LENGTH_SHORT).show(); + } + }); + mIweixin.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (saveImageToGallery(mResource)) { + Toast.makeText(CaibeiRechargeActivity.this, "保存成功", Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(CaibeiRechargeActivity.this, "保存失败", Toast.LENGTH_SHORT).show(); + return true; + } + }); + + mSelectedWay = Color.parseColor("#333333"); + mSelectWay = Color.parseColor("#999999"); + +// mIvAlipayImage.getBackground().setAlpha(255); +// mIvWinxinImage.getBackground().setAlpha(100); +// +// mTvRechargeAlipay.setTextColor(mSelectedWay); +// mTvRechargeWinxin.setTextColor(mSelectWay); + + mLlRechargeAlipay.setOnClickListener(this); + mLlRechargeWinxin.setOnClickListener(this); + + mConfirmButton.setOnClickListener(this); + + mRechargeAdapter = new RechargeAdapter(this); + mRechargeAdapter.setRechargeList(mRechargeList); + mRechargeAdapter.setType(1); + mRechargeAdapter.setOnItemClickListener(new RechargeAdapter.OnItemClickListener() { + @Override + public void onItemClicked(View v, int position) { + isSelected = true; + mRechargeAdapter.setSelectedPosition(position); + mRechargeAdapter.notifyDataSetChanged(); + mSelectedGoodView = v; + mSelectedGoodPosition = position; + mConfirmButton.setText("支付¥" + mRechargeList.get(position).getPrice()); + } + }); + + mRechargeGoodList.setLayoutManager(new StaggeredGridLayoutManager(3, + StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + return false; + } + }); + mRechargeGoodList.setNestedScrollingEnabled(true); + mRechargeGoodList.setAdapter(mRechargeAdapter); + } + + private void getRechargeInfo(String payType) { + int type; + if (TextUtils.equals("alipay", payType)) { + type = 2; + } else { + type = 6; + } + SettingManager.getRechargeInfo(this, type, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RechargeListBean result, String message) { + if (!isSelected) { + mSelectedGoodPosition = result.getSelected_id(); + } + mRechargeAdapter.setSelectedPosition(mSelectedGoodPosition); + mAmount.setText((result.getCoin() + result.getIncome_coin()) + ""); + mRechargeList.clear(); + mRechargeList.addAll(result.getList()); + if (result.getShow_wx_pay_type() == 0 && result.getShow_alipay_pay_type() == 0) { + ll_recharge_way.setVisibility(View.GONE); + Glide.with(CaibeiRechargeActivity.this).asBitmap().load(ConstUrl.IMAGE_URL + result.getChongzhi_bg()).into(new SimpleTarget() { + @Override + public void onResourceReady(Bitmap resource, Transition transition) { + mResource = resource; + ViewGroup.LayoutParams layoutParams = mIweixin.getLayoutParams(); + if (layoutParams == null) + layoutParams = new ViewGroup.LayoutParams(ScreenUtil.getDisplayWidth(), ScreenUtil.getDisplayWidth()); + else { + layoutParams.width = ScreenUtil.getDisplayWidth(); + layoutParams.height = ScreenUtil.getDisplayWidth(); + } + mIweixin.setLayoutParams(layoutParams); + mIweixin.setImageBitmap(mResource); + } + }); + mIweixin.setVisibility(View.VISIBLE); + mConfirmButton.setVisibility(View.GONE); + mRechargeGoodList.setVisibility(View.GONE); + } else { + ll_recharge_way.setVisibility(View.VISIBLE); + pay_line.setVisibility(View.VISIBLE); + mIweixin.setVisibility(View.GONE); + mConfirmButton.setVisibility(View.VISIBLE); + mRechargeGoodList.setVisibility(View.VISIBLE); + mRechargeAdapter.setType(1); + mRechargeAdapter.notifyDataSetChanged(); + if (!mRechargeList.isEmpty()) { +// mConfirmButton.setText("支付¥" + mRechargeList.get(mSelectedGoodPosition).getPrice()); + } + setResult(RESULT_OK); + if (result.getShow_wx_pay_type() == 0) { + lin_wechat_pay.setVisibility(View.GONE); + pay_line.setVisibility(View.GONE); + mTvRechargeAlipay.setTextColor(mSelectedWay); + mTvRechargeWinxin.setTextColor(mSelectWay); + mIvAlipay.setVisibility(View.VISIBLE); + mIvWinxin.setVisibility(View.INVISIBLE); + mIvAlipayImage.getBackground().setAlpha(255); + mIvWinxinImage.getBackground().setAlpha(100); + mSelectedPayMethod = "alipay"; + } else { + mLlRechargeWinxin.setVisibility(View.VISIBLE); + } + if (result.getShow_alipay_pay_type() == 0) { + lin_alipay.setVisibility(View.GONE); + pay_line.setVisibility(View.GONE); + mTvRechargeAlipay.setTextColor(mSelectWay); + mTvRechargeWinxin.setTextColor(mSelectedWay); + mIvAlipay.setVisibility(View.INVISIBLE); + mIvWinxin.setVisibility(View.VISIBLE); + mIvAlipayImage.getBackground().setAlpha(100); + mIvWinxinImage.getBackground().setAlpha(255); + mSelectedPayMethod = "wechat"; + } else { + mLlRechargeAlipay.setVisibility(View.VISIBLE); + } + } + +// // if (TextUtils.isEmpty(result.getChongzhi_bg())) { +// /** +// * 添加微信支付 +// */ +// if (type == 2) { +// mIweixin.setVisibility(View.GONE); +// mConfirmButton.setVisibility(View.VISIBLE); +// mRechargeGoodList.setVisibility(View.VISIBLE); +// mRechargeAdapter.setType(1); +// mRechargeAdapter.notifyDataSetChanged(); +// if (!mRechargeList.isEmpty()) { +// mConfirmButton.setText("支付¥" + mRechargeList.get(mSelectedGoodPosition).getPrice()); +// } +// setResult(RESULT_OK); +// } else if (type == 6) { +// if (result.getWechat_pay_status() == 1) { +// mIweixin.setVisibility(View.GONE); +// mConfirmButton.setVisibility(View.VISIBLE); +// mRechargeGoodList.setVisibility(View.VISIBLE); +// mRechargeAdapter.setType(1); +// mRechargeAdapter.notifyDataSetChanged(); +// if (!mRechargeList.isEmpty()) { +// mConfirmButton.setText("支付¥" + mRechargeList.get(mSelectedGoodPosition).getPrice()); +// } +// setResult(RESULT_OK); +// } else if (result.getWechat_pay_status() == 0) { +// Glide.with(CaibeiRechargeActivity.this).asBitmap().load(ConstUrl.IMAGE_URL + result.getChongzhi_bg()).into(new SimpleTarget() { +// @Override +// public void onResourceReady(Bitmap resource, Transition transition) { +// mResource = resource; +// ViewGroup.LayoutParams layoutParams = mIweixin.getLayoutParams(); +// if (layoutParams == null) +// layoutParams = new ViewGroup.LayoutParams(ScreenUtil.getDisplayWidth(), ScreenUtil.getDisplayWidth()); +// else { +// layoutParams.width = ScreenUtil.getDisplayWidth(); +// layoutParams.height = ScreenUtil.getDisplayWidth(); +// } +// mIweixin.setLayoutParams(layoutParams); +// mIweixin.setImageBitmap(mResource); +// } +// }); +// mIweixin.setVisibility(View.VISIBLE); +// mConfirmButton.setVisibility(View.GONE); +// mRechargeGoodList.setVisibility(View.GONE); +// } +// } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + + private void confirmToPay() { + if (mRechargeList.size() == 0) { + return; + } + + final RechargeBean rechargeBean = mRechargeList.get(mSelectedGoodPosition); + if (isWXHF && mSelectedPayMethod.equals("wechat")) { + PayUtils.wxminiPay(this, rechargeBean.getId(), 0, ghOriId, mini_program_type); + return; + } + SettingManager.payToRecharge(this, mSelectedPayMethod, + rechargeBean.getId() + "", 0, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayBean result, String message) { + if ("alipay".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + Thread payThread = new Thread(mPayRunnable); + payThread.start(); + } + } else if (result.getPay_platform_type() == 2) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + PayUtils.ailWeb(mOrderInfo, CaibeiRechargeActivity.this); + } + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(CaibeiRechargeActivity.this, PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(CaibeiRechargeActivity.this, result.getPayinfo()); + } else { + PayTypeSdk.getInstance().cashierPay(CaibeiRechargeActivity.this, result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + getRechargeInfo(mSelectedPayMethod); + } + } + }); + } + } else if ("wechat".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + IWXAPI wxapi = WXAPIFactory.createWXAPI(CaibeiRechargeActivity.this, Constant.WECHAT_APP_ID, false); + WeChatPayInfoBean wechatpayinfo = result.getWechatpayinfo(); + PayReq req = new PayReq(); + req.appId = Constant.WECHAT_APP_ID; + req.partnerId = wechatpayinfo.getMch_id(); //商户号 + req.prepayId = wechatpayinfo.getPrepay_id(); //预付款id + req.nonceStr = wechatpayinfo.getNonce_str(); + req.timeStamp = wechatpayinfo.getTimestamp() + ""; + req.packageValue = "Sign=WXPay"; //固定值 + req.sign = wechatpayinfo.getPaySign(); + boolean isWXAppInstalledAndSupported = wxapi.isWXAppInstalled(); + if (isWXAppInstalledAndSupported) { + wxapi.registerApp(Constant.WECHAT_APP_ID); + wxapi.sendReq(req); + } else { + MaleToast.showMessage(CaibeiRechargeActivity.this, "未安装微信,不能支付"); + } + } else if (result.getPay_platform_type() == 2) { + PayTypeSdk.getInstance().cashierPay(CaibeiRechargeActivity.this, result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + getRechargeInfo(mSelectedPayMethod); + } + } + }); + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(CaibeiRechargeActivity.this, PayWebViewActivity.class); + intent.putExtra("type", 4); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(CaibeiRechargeActivity.this, result.getPayinfo()); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + Toast.makeText(activity, tip, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + Toast.makeText(activity, "支付出错", Toast.LENGTH_SHORT).show(); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + getRechargeInfo(mSelectedPayMethod); + } + + //微信支付成功后回调 + public void onEventMainThread(PayEvent event) { + int errCode = event.getErrCode(); + if (errCode == 0) { + MaleToast.showSuccessMsg(CaibeiRechargeActivity.this, "充值成功"); + getRechargeInfo(mSelectedPayMethod); + } else if (errCode == -2) { + MaleToast.showFailureMsg(CaibeiRechargeActivity.this, "充值取消"); + } else { + MaleToast.showFailureMsg(CaibeiRechargeActivity.this, "充值失败"); + } + } + + private void initTitle() { + setTitleName("购买金币"); + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + TextView rightText = title.findViewById(R.id.right_text); + rightText.setText("充值记录"); + rightText.setVisibility(View.VISIBLE); + rightText.setTextColor(Color.BLACK); + ImageView left = title.findViewById(R.id.left_image); + TextView titleText = title.findViewById(R.id.center_text); + left.setImageResource(R.drawable.ic_return); + left.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + setResult(RESULT_CANCELED); + finish(); + } + }); + + titleText.setTextColor(Color.BLACK); + rightText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(CaibeiRechargeActivity.this, BillActivity.class); + intent.putExtra("type", 2); + startActivity(intent); + } + }); + } + + @Override + public void onClick(View view) { + if (mConfirmButton == view) { + if (mSelectedPayMethod.equals("wechat")) { + getWXPayType(); + } else { + confirmToPay(); + } + } else if (mLlRechargeAlipay == view) { //支付宝支付 + mRechargeAdapter.setWXRecharge(false); + mRechargeAdapter.setSelectedPosition(mSelectedGoodPosition); + mRechargeAdapter.notifyDataSetChanged(); + mTvRechargeAlipay.setTextColor(mSelectedWay); + mTvRechargeWinxin.setTextColor(mSelectWay); + mIvAlipay.setVisibility(View.VISIBLE); + mIvWinxin.setVisibility(View.INVISIBLE); + mIvAlipayImage.getBackground().setAlpha(255); + mIvWinxinImage.getBackground().setAlpha(100); + mSelectedPayMethod = "alipay"; + getRechargeInfo(mSelectedPayMethod); + } else if (mLlRechargeWinxin == view) { //微信支付 + mRechargeAdapter.setWXRecharge(false); + mRechargeAdapter.setSelectedPosition(mSelectedGoodPosition); + mRechargeAdapter.notifyDataSetChanged(); + mTvRechargeAlipay.setTextColor(mSelectWay); + mTvRechargeWinxin.setTextColor(mSelectedWay); + mIvAlipay.setVisibility(View.INVISIBLE); + mIvWinxin.setVisibility(View.VISIBLE); + mIvAlipayImage.getBackground().setAlpha(100); + mIvWinxinImage.getBackground().setAlpha(255); + mSelectedPayMethod = "wechat"; + getRechargeInfo(mSelectedPayMethod); + } + } + + @Override + public void onDestroy() { + EventBus.getDefault().unregister(this); + mResource = null; + System.gc(); + super.onDestroy(); + } + + public boolean saveImageToGallery(Bitmap bmp) { // 首先保存图片 +// String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + System.currentTimeMillis() + ""; + String storePath = ConstUrl.DEFAULT_PATH + File.separator + "私语"; + File appDir = new File(storePath); + if (!appDir.exists()) { + appDir.mkdir(); + } + String fileName = System.currentTimeMillis() + ".jpg"; + File file = new File(appDir, fileName); + try { + FileOutputStream fos = new FileOutputStream(file); + //通过io流的方式来压缩保存图片 + boolean isSuccess = bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos); + fos.flush(); + fos.close(); + //把文件插入到系统图库 + MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), fileName, null); + //保存图片后发送广播通知更新数据库 + Uri uri = Uri.fromFile(file); + sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); + if (isSuccess) { + return true; + } else { + return false; + } + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/CancellationActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CancellationActivity.kt new file mode 100644 index 0000000..70f80f3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CancellationActivity.kt @@ -0,0 +1,178 @@ +package com.fengliyan.tianlesue.view.settings +import android.graphics.Color +import android.os.Build +import android.os.Bundle +import android.view.View +import android.webkit.WebChromeClient +import android.webkit.WebSettings +import android.webkit.WebView +import android.webkit.WebViewClient +import com.fengliyan.storage.StorageManager +import com.fengliyan.uikit.toast.MaleToast +import com.fengliyan.tianlesue.controller.constant.ConstUrl +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager +import com.fengliyan.tianlesue.controller.user.manager.UserManager +import com.fengliyan.tianlesue.databinding.ActivityCancellationBinding +import com.fengliyan.tianlesue.model.settings.CancellationBean +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog +import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.Disposable +import java.util.concurrent.TimeUnit + +class CancellationActivity :BaseActivity(){ + lateinit var binding:ActivityCancellationBinding + var status = 0; + var disposable:Disposable? = null + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityCancellationBinding.inflate(layoutInflater) + setContentView(binding.root) + setDefaultTitle() + setTitleName("注销账号") + val url = ConstUrl.CANCALLATION_URL + val webView = binding.webviewView + customTitle.dismissBottomLine() + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW + } + webView.settings.blockNetworkImage = false + webView.webChromeClient = object : WebChromeClient() { + override fun onProgressChanged(view: WebView, newProgress: Int) { + super.onProgressChanged(view, newProgress) + binding.webviewProgress.progress = newProgress + if (newProgress == 100) { + binding.webviewProgress.visibility = View.GONE + } + } + } + webView.webViewClient = object : WebViewClient() { + override fun onPageFinished(view: WebView, url: String) { + super.onPageFinished(view, url) +// setTitleName(webView.title) + } + } + webView.settings.javaScriptEnabled = true + webView.loadUrl(url) + refresh() + binding.cancellationBtn.setOnClickListener { + if (status==0){ + //申请注销 + tipCancellation() + }else if (status==1){ + //放弃注销 + updateStatus("2") + }else{ + //注销 + cancellation() + } + } + } + fun tipCancellation(){ + val customAlertDialog = CustomAlertDialog(this@CancellationActivity) + customAlertDialog.setTitle("确认申请注销吗?"); + customAlertDialog.setContent("注销账号将清理所有数据不可恢复\n该操作不可撤销,请谨慎对待") + customAlertDialog.setRightBtnText("确认") + customAlertDialog.setLeftBtnText("取消") + customAlertDialog.setCanceledOnTouchOutside(false) + customAlertDialog.show() + customAlertDialog.setOnDialogClickListener({ customAlertDialog.dismiss() }) { + // deleteAccount(); + updateStatus("1") + } + } +// 1申请注销 2放弃注销 + fun updateStatus(type:String){ + SettingManager.uptlogout(this,type,object :HttpUiCallBack{ + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + if (type.equals("2")){ + finish() + return + } + refresh() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"操作失败") + } + + }) + } + + + fun cancellation(){ + SettingManager.deleteAccount(this,object :HttpUiCallBack{ + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + //logout + UserManager.getInstance().notifyUserInfoChanged(BaseUserInfo()) + StorageManager.getInstance(this@CancellationActivity).clear() + finish() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"注销失败") + } + }) + } + fun refresh(){ + SettingManager.getlogout(this,object :HttpUiCallBack{ + override fun onSuccess(activity: BaseActivity?, result: CancellationBean, tips: String?) { + status = result.status + when(result.status){ + 0->{ + //倒计时 + disposable?.dispose() + binding.cancellationBtn.isEnabled = false + disposable = Observable.interval(0,1,TimeUnit.SECONDS,AndroidSchedulers.mainThread()) + .subscribe { + if (it>15){ + disposable?.dispose() + binding.cancellationBtn.isEnabled = true + binding.cancellationBtn.setText("申请注销") + return@subscribe + } + binding.cancellationBtn.setText("请阅读注销协议${15-it}秒") + } + + binding.cancellationBtn.setText("申请注销") + } + 1->{ + binding.cancellationBtn.setText("放弃注销") + } + 2->{ + binding.cancellationBtn.setBackgroundColor(Color.WHITE) + binding.cancellationBtn.background = null + binding.cancellationBtn.setText("确认注销") + binding.cancellationBtn.setTextColor((Color.parseColor("#DF4138"))) + } + } + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"获取注销状态失败") + } + + }) + } + + override fun onDestroy() { + super.onDestroy() + disposable?.dispose() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/CertificationActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CertificationActivity.java new file mode 100644 index 0000000..6b98fac --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CertificationActivity.java @@ -0,0 +1,126 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.SelfieExampleBean; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +public class CertificationActivity extends BaseActivity implements View.OnClickListener { + public static int REQUEST_SELFIE = 201; + private ConstraintLayout cl_verify2; + private TextView tv_verify_hint1, tv_verify_hint2; + private TextView tv_certification_btn1, tv_certification_btn2; + private ImageView iv_verify_status1, iv_verify_status2; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_verify_certification); + setDefaultTitle(); + setTitleName("真人认证"); + initView(); + getSelfieExample(); + } + + private void initView() { + cl_verify2 = findViewById(R.id.cl_verify2); + tv_verify_hint1 = findViewById(R.id.tv_verify_hint1); + tv_verify_hint2 = findViewById(R.id.tv_verify_hint2); + tv_certification_btn1 = findViewById(R.id.tv_certification_btn1); + tv_certification_btn2 = findViewById(R.id.tv_certification_btn2); + iv_verify_status1 = findViewById(R.id.iv_verify_status1); + iv_verify_status2 = findViewById(R.id.iv_verify_status2); + tv_certification_btn1.setOnClickListener(this); + tv_certification_btn2.setOnClickListener(this); + + if (NoClearSPUtils.getInt(this, ConsUser.RISK_FACE_STATUS) == 1) { + cl_verify2.setVisibility(View.VISIBLE); + } else { + cl_verify2.setVisibility(View.GONE); + } + } + + private void getSelfieExample() { + SettingManager.getSelfieExample(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SelfieExampleBean result, String message) { + //自拍认证审核状态 0未提交 1审核中 2 审核通过 3 审核不通过 + if (1 == result.getAudit_status()) { + tv_certification_btn1.setVisibility(View.GONE); + iv_verify_status1.setVisibility(View.VISIBLE); + tv_verify_hint1.setVisibility(View.GONE); + iv_verify_status1.setImageResource(R.drawable.ic_verify_status1); + } else if (2 == result.getAudit_status()) { + tv_certification_btn1.setVisibility(View.GONE); + iv_verify_status1.setVisibility(View.VISIBLE); + tv_verify_hint1.setVisibility(View.GONE); + iv_verify_status1.setImageResource(R.drawable.ic_verify_status2); + } else { + tv_certification_btn1.setVisibility(View.VISIBLE); + tv_verify_hint1.setVisibility(View.VISIBLE); + iv_verify_status1.setVisibility(View.GONE); + } + + //人脸认证-1未认证0认证中1认证成功2认证失败 + if (StrU.equals("0", result.getFace_status())) { + tv_certification_btn2.setVisibility(View.GONE); + tv_verify_hint2.setVisibility(View.GONE); + iv_verify_status2.setVisibility(View.VISIBLE); + iv_verify_status2.setImageResource(R.drawable.ic_verify_status1); + } else if (StrU.equals("1", result.getFace_status())) { + tv_certification_btn2.setVisibility(View.GONE); + tv_verify_hint2.setVisibility(View.GONE); + iv_verify_status2.setVisibility(View.VISIBLE); + iv_verify_status2.setImageResource(R.drawable.ic_verify_status2); + } else { + tv_certification_btn2.setVisibility(View.VISIBLE); + tv_verify_hint2.setVisibility(View.VISIBLE); + iv_verify_status2.setVisibility(View.GONE); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + if (view == tv_certification_btn1) { + Intent intentApplyBigCast = new Intent(this, PreSelfieActivity.class); + startActivity(intentApplyBigCast); + } else if (view == tv_certification_btn2) { + Intent intentApplyBigCast = new Intent(this, EditVerifyInfoActivity.class); + startActivityForResult(intentApplyBigCast, REQUEST_SELFIE); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_SELFIE) { + if (200 == resultCode) { + getSelfieExample(); + } + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/ChangeMobileActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ChangeMobileActivity.java new file mode 100644 index 0000000..1297b80 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ChangeMobileActivity.java @@ -0,0 +1,144 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.graphics.Color; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +public class ChangeMobileActivity extends BaseActivity implements View.OnClickListener { + private EditText et_mobile; + private EditText et_code; + private TextView tv_send_code; + private TextView tv_change_submit; + private String mobile; + private boolean isCodeSend; + private CountDownTimer mTimer; + private String oldCode; + + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName(""); + setContentView(R.layout.activity_change_mobile); + initView(); + oldCode = getIntent().getStringExtra("code"); + } + + private void initView() { + et_mobile = findViewById(R.id.et_mobile); + et_code = findViewById(R.id.et_code); + tv_send_code = findViewById(R.id.tv_send_code); + tv_change_submit = findViewById(R.id.tv_change_submit); + tv_send_code.setOnClickListener(this); + tv_change_submit.setOnClickListener(this); + + mTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + tv_send_code.setText("重新获取验证码(" + (l / 1000) + "s)"); + } + + //test + @Override + public void onFinish() { + tv_send_code.setEnabled(true); + tv_send_code.setTextColor(Color.BLACK); + isCodeSend = false; + tv_send_code.setText("发送验证码"); + } + }; + + et_mobile.addTextChangedListener(mTextWatcher); + et_code.addTextChangedListener(mTextWatcher); + } + + private final TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + tv_change_submit.setEnabled(!TextUtils.isEmpty(et_mobile.getText().toString()) && !TextUtils.isEmpty(et_code.getText().toString())); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }; + + //手机验证码登录 + public void sendCode(String number) { + RegisterManager.sendAuthCode(this, number, "", "submit_change_mobile", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + mTimer.start(); + tv_send_code.setEnabled(false); + tv_send_code.setTextColor(Color.parseColor("#DDDDDD")); + isCodeSend = true; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + private void submitChangeMobile(String code, String mobile) { + RegisterManager.submitChangeMobile(this, oldCode, code, mobile, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + startMainActivity(BindPhoneActivity.class); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onClick(View view) { + if (view == tv_send_code) { + if (!TextUtils.isEmpty(et_mobile.getText().toString())) { + sendCode(et_mobile.getText().toString()); + } + } else if (view == tv_change_submit) { + submitChangeMobile(et_code.getText().toString(), et_mobile.getText().toString()); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mTimer) { + mTimer.cancel(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/ChangePasswordActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ChangePasswordActivity.java new file mode 100644 index 0000000..43b90c8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ChangePasswordActivity.java @@ -0,0 +1,137 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +public class ChangePasswordActivity extends BaseActivity implements View.OnClickListener { + private TextView tv_change_password_title; + private LinearLayout lin_old_password; + private EditText et_old_password; + private ImageView iv_old_password; + private EditText et_new_password; + private ImageView iv_new_password; + private EditText et_sure_password; + private ImageView iv_sure_password; + private TextView tv_change_password_submit; + private String type; + private boolean isShow1; + private boolean isShow2; + private boolean isShow3; + + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName(""); + setContentView(R.layout.activity_change_password); + type = getIntent().getStringExtra("type"); + initView(); + } + + private void initView() { + tv_change_password_title = findViewById(R.id.tv_change_password_title); + lin_old_password = findViewById(R.id.lin_old_password); + et_old_password = findViewById(R.id.et_old_password); + iv_old_password = findViewById(R.id.iv_old_password); + et_new_password = findViewById(R.id.et_new_password); + iv_new_password = findViewById(R.id.iv_new_password); + et_sure_password = findViewById(R.id.et_sure_password); + iv_sure_password = findViewById(R.id.iv_sure_password); + tv_change_password_submit = findViewById(R.id.tv_change_password_submit); + iv_old_password.setOnClickListener(this); + iv_new_password.setOnClickListener(this); + iv_sure_password.setOnClickListener(this); + tv_change_password_submit.setOnClickListener(this); + et_old_password.addTextChangedListener(mTextWatcher); + et_new_password.addTextChangedListener(mTextWatcher); + et_sure_password.addTextChangedListener(mTextWatcher); + if (TextUtils.equals("1", type)) { + lin_old_password.setVisibility(View.VISIBLE); + tv_change_password_title.setText("修改密码"); + } else { + lin_old_password.setVisibility(View.GONE); + tv_change_password_title.setText("设置密码"); + } + } + + private final TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (TextUtils.equals("1", type)) { + tv_change_password_submit.setEnabled(!TextUtils.isEmpty(et_old_password.getText().toString()) && !TextUtils.isEmpty(et_new_password.getText().toString()) && !TextUtils.isEmpty(et_sure_password.getText().toString())); + } else { + tv_change_password_submit.setEnabled(!TextUtils.isEmpty(et_new_password.getText().toString()) && !TextUtils.isEmpty(et_sure_password.getText().toString())); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }; + + private void submitChangeMobile(String password, String surePassword, String oldPassword) { + RegisterManager.editUserPwd(this, password, surePassword, oldPassword, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + startMainActivity(BindPhoneActivity.class); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onClick(View view) { + if (view == iv_old_password) { + isShow1 = !isShow1; + changePasswordHint(et_old_password, iv_old_password, isShow1); + } else if (view == iv_new_password) { + isShow2 = !isShow2; + changePasswordHint(et_new_password, iv_new_password, isShow2); + } else if (view == iv_sure_password) { + isShow3 = !isShow3; + changePasswordHint(et_sure_password, iv_sure_password, isShow3); + } else if (view == tv_change_password_submit) { + submitChangeMobile(et_new_password.getText().toString(), et_sure_password.getText().toString(), et_old_password.getText().toString()); + } + } + + private void changePasswordHint(EditText editText, ImageView imageView, boolean isShow) { + if (isShow) { + imageView.setImageResource(R.drawable.ic_sign_input3); + editText.setTransformationMethod(PasswordTransformationMethod.getInstance()); + } else { + imageView.setImageResource(R.drawable.ic_sign_input2); + editText.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + } + editText.setSelection(editText.getText().length()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/ContractActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ContractActivity.java new file mode 100644 index 0000000..67f93f4 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ContractActivity.java @@ -0,0 +1,72 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.webkit.WebView; +import android.widget.Button; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +public class ContractActivity extends BaseActivity implements View.OnClickListener{ + + private WebView mContractWebView; + private Button mAgreeButton; + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_anchor_contract); + initView(); + } + + private void initView(){ + + Intent intent = getIntent(); + int agree = intent.getIntExtra("agree", 0); + + mContractWebView = findViewById(R.id.anchor_contract_webview); + mAgreeButton = findViewById(R.id.anchor_contract_agree_button); + + if (1 == agree) { + mAgreeButton.setVisibility(View.GONE); + }else { + mAgreeButton.setVisibility(View.VISIBLE); + } + + mAgreeButton.setOnClickListener(this); + mContractWebView.loadUrl(ConstUrl.CONTRACT_URL); + } + + @Override + public void onClick(View view) { + if(view == mAgreeButton){ + agreeContract(); + } + } + + public void agreeContract(){ + SettingManager.agreeContract(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Boolean result, String message) { + setResult(RESULT_OK); + MaleToast.showMessage(ContractActivity.this, "已同意女神服务协议"); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/CopyBoardActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CopyBoardActivity.java new file mode 100644 index 0000000..f58bfa2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/CopyBoardActivity.java @@ -0,0 +1,150 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.Manifest; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.provider.MediaStore; +import android.view.View; +import android.widget.Button; +import android.widget.RelativeLayout; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.base.base.permission.AbsPermissionResultCallBack; +import com.fengliyan.base.base.permission.PermissionHelper; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.uikit.toast.MaleToast; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +public class CopyBoardActivity extends BaseActivity { + private SimpleDraweeView mImage; + private Button mCopyButton; + private String mImageUrl; + private String mNewImageUrl; + private SimpleDraweeView mSvAvatar; + private RelativeLayout mRlAll; + + public void onCreate(Bundle savedInstance) { + super.onCreate(savedInstance); + setContentView(R.layout.activity_copy_board); + setDefaultTitle(); + setTitleName("复制二维码"); + Intent intent = getIntent(); + mNewImageUrl = intent.getStringExtra("imageUrl"); + initView(); + } + + private void initView() { + mImage = findViewById(R.id.copy_board_image); + mSvAvatar = findViewById(R.id.sv_avatar); + mCopyButton = findViewById(R.id.copy_board_download); + mRlAll = findViewById(R.id.rl_all); + mRlAll.setDrawingCacheEnabled(true); + mImage.setImageURI(mNewImageUrl); + mSvAvatar.setImageURI(ConstUrl.IMAGE_URL + UserManager.getUserInfo().getAvatar()); + mCopyButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + PermissionHelper.request(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, + new AbsPermissionResultCallBack() { + @Override + public void onPermissionGranted() { + new SaveImage().execute(); +// saveImageToGallery(getCacheBitmapFromView(mRlAll)); + } + + @Override + public void onPermissionDenied(String... permissions) { + super.onPermissionDenied(permissions); + MaleToast.showMessage(CopyBoardActivity.this, "没有授予存储权限"); + } + }); + } + }); + } + + /*** + * 功能:用线程保存图片 + * + * @author wangyp + */ + private class SaveImage extends AsyncTask { + @Override + protected Boolean doInBackground(Boolean... params) { + boolean result = false; + Bitmap bitmap = getCacheBitmapFromView(mRlAll); + if (bitmap != null) { + result = saveImageToGallery(getCacheBitmapFromView(mRlAll)); + } + return result; + } + + @Override + protected void onPostExecute(Boolean result) { + if (result) { + MaleToast.showMessage(CopyBoardActivity.this, "二维码保存成功"); + } else { + MaleToast.showMessage(CopyBoardActivity.this, "二维码保存失败"); + } + + } + } + + /** + * 获取一个 View 的缓存视图 * (前提是这个View已经渲染完成显示在页面上) * @param view * @return + */ + public static Bitmap getCacheBitmapFromView(RelativeLayout view) { + final boolean drawingCacheEnabled = true; + view.setDrawingCacheEnabled(drawingCacheEnabled); + view.buildDrawingCache(drawingCacheEnabled); + final Bitmap drawingCache = view.getDrawingCache(); + Bitmap bitmap; + if (drawingCache != null) { + bitmap = Bitmap.createBitmap(drawingCache); + view.setDrawingCacheEnabled(false); + } else { + bitmap = null; + } + return bitmap; + } + + public boolean saveImageToGallery(Bitmap bmp) { // 首先保存图片 + String storePath = ConstUrl.DEFAULT_PATH + File.separator + System.currentTimeMillis() + ""; + File appDir = new File(storePath); + if (!appDir.exists()) { + appDir.mkdir(); + } + String fileName = System.currentTimeMillis() + ".jpg"; + File file = new File(appDir, fileName); + try { + FileOutputStream fos = new FileOutputStream(file); + //通过io流的方式来压缩保存图片 + boolean isSuccess = bmp.compress(Bitmap.CompressFormat.JPEG, 60, fos); + fos.flush(); + fos.close(); + //把文件插入到系统图库 + MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), fileName, null); + //保存图片后发送广播通知更新数据库 + Uri uri = Uri.fromFile(file); + sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); + if (isSuccess) { + return true; + } else { + return false; + } + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/EditVerifyInfoActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/EditVerifyInfoActivity.java new file mode 100644 index 0000000..18315c7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/EditVerifyInfoActivity.java @@ -0,0 +1,124 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.alipay.face.api.ZIMCallback; +import com.alipay.face.api.ZIMFacade; +import com.alipay.face.api.ZIMFacadeBuilder; +import com.alipay.face.api.ZIMResponse; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.SelfieExampleBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.HashMap; + +public class EditVerifyInfoActivity extends BaseActivity implements View.OnClickListener { + private EditText et_verify_name, et_verify_number; + private TextView tv_verify_sure; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_edit_verify_info); + setDefaultTitle(); + setTitleName("实名认证"); + initView(); + } + + private void initView() { + et_verify_name = findViewById(R.id.et_verify_name); + et_verify_number = findViewById(R.id.et_verify_number); + tv_verify_sure = findViewById(R.id.tv_verify_sure); + tv_verify_sure.setOnClickListener(this); + } + + private void getFaceCertifyId(String meta_info, String cert_name, String cert_no) { + SettingManager.getFaceCertifyId(this, meta_info, cert_name, cert_no, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SelfieExampleBean result, String message) { + if (result != null) { + if (!StrU.isEmpty(result.getCertify_id())) { + ZIMFacade zimFacade = ZIMFacadeBuilder.create(activity); + HashMap extParams = new HashMap<>(); + //如需指定活体检测UI界面方向(横屏),请指定这一项。 + // extParams.put(ZIMFacade.ZIM_EXT_PARAMS_KEY_SCREEN_ORIENTATION, ZIMFacade.ZIM_EXT_PARAMS_VAL_SCREEN_LAND); + //如需支持活体视频返回,请指定这一项,并在response.videoFilePath中获取视频本地路径。 + extParams.put(ZIMFacade.ZIM_EXT_PARAMS_KEY_USE_VIDEO, ZIMFacade.ZIM_EXT_PARAMS_VAL_USE_VIDEO_TRUE); + //如需自定义活体检测页面的进度条颜色(默认可不设置),请设置此项,如红色 #FF0000。 + extParams.put(ZIMFacade.ZIM_EXT_PARAMS_KEY_FACE_PROGRESS_COLOR, "#FF0000"); + Log.i("TAG", "response: -------->" + result.getCertify_id()); + zimFacade.verify(result.getCertify_id(), true, extParams, new ZIMCallback() { + @Override + public boolean response(final ZIMResponse response) { + Log.i("TAG", "response: -------->" + response); + if (1000 == response.code) { + Log.i("TAG", "response: 刷脸通过------>"); + MaleToast.showMessage(activity, "刷脸通过"); + setResult(200); + finish(); + } else { + MaleToast.showMessage(activity, "刷脸失败"); + Log.i("TAG", "response: 刷脸失败([" + response.code + "]" + response.reason + ")"); + faceStatusError(response.reason, meta_info); + } + return true; + } + }); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, e.toString()); + } + }); + } + + private void faceStatusError(String note, String certify_id) { + SettingManager.faceStatusError(this, note, certify_id, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SelfieExampleBean result, String message) { + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, e.toString()); + } + }); + } + + @Override + public void onClick(View view) { + if (view == tv_verify_sure) { + if (StrU.isEmpty(et_verify_name.getText().toString())) { + MaleToast.showMessage(this, "请输入本人真实姓名"); + return; + } + if (StrU.isEmpty(et_verify_number.getText().toString())) { + MaleToast.showMessage(this, "请输入本人真实身份证号"); + return; + } + String metaInfos = ZIMFacade.getMetaInfos(this); + getFaceCertifyId(metaInfos, et_verify_name.getText().toString(), et_verify_number.getText().toString()); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/ExchangeActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ExchangeActivity.java new file mode 100644 index 0000000..4b916e6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ExchangeActivity.java @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.uikit.title.Title; + +import static com.fengliyan.uikit.title.Title.POSTION_CENTER; + +public class ExchangeActivity extends BaseActivity implements View.OnClickListener { + + private View mTitleView; + private View mTitleTag1; + private View mTitleTag2; + private View mTitleBottom1; + private View mTitleBottom2; + private View mBack; + private TextView mTitleText1; + private TextView mTitleText2; + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_exchange); + initTitle(); + initView(); + } + + private void initView(){ + + } + + private void initTitle(){ + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundResource(android.R.color.white); + title.dismissBottomLine(); + title.dimissRight(); + title.dismissLeft(); + title.setTitle(""); + mTitleView = View.inflate(this, R.layout.item_exchange_title, null); + mTitleTag1 = mTitleView.findViewById(R.id.exchange_title_view_1); + mTitleTag2 = mTitleView.findViewById(R.id.exchange_title_view_2); + mTitleText1 = mTitleView.findViewById(R.id.exchange_title_name_1); + mTitleText2 = mTitleView.findViewById(R.id.exchange_title_name_2); + mTitleBottom1 = mTitleView.findViewById(R.id.exchange_title_bottom_line_1); + mTitleBottom2 = mTitleView.findViewById(R.id.exchange_title_bottom_line_2); + mBack = mTitleView.findViewById(R.id.exchange_title_back); + mBack.setOnClickListener(this); + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + title.addViewTo(mTitleView, POSTION_CENTER); + + } + + private void changeTag(int index){ + switch (index){ + case 1: + mTitleText1.setTextColor(Color.BLACK); + mTitleBottom1.setVisibility(View.VISIBLE); + mTitleText2.setTextColor(getResources().getColor(R.color.loginText2)); + mTitleBottom2.setVisibility(View.GONE); + break; + case 2: + mTitleText2.setTextColor(Color.BLACK); + mTitleBottom2.setVisibility(View.VISIBLE); + mTitleText1.setTextColor(getResources().getColor(R.color.loginText2)); + mTitleBottom1.setVisibility(View.GONE); + break; + } + } + + @Override + public void onClick(View view) { + if(view == mTitleTag1){ + changeTag(1); + }else if(view == mTitleTag2){ + changeTag(2); + }else if(mBack == view){ + finish(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/GeneralMemberFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/GeneralMemberFragment.java new file mode 100644 index 0000000..f035df9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/GeneralMemberFragment.java @@ -0,0 +1,552 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.graphics.Paint; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.widget.NestedScrollView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.alipay.sdk.app.PayTask; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.eventBus.PayEvent; +import com.fengliyan.tianlesue.controller.settings.adapter.GeneralOptionsRecyclerAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.MemberBean; +import com.fengliyan.tianlesue.model.settings.MemberInfoList; +import com.fengliyan.tianlesue.model.settings.MemberPrivilegesInfo; +import com.fengliyan.tianlesue.model.settings.PayBean; +import com.fengliyan.tianlesue.model.settings.PayConfigBean; +import com.fengliyan.tianlesue.model.settings.WXPayTypeBean; +import com.fengliyan.tianlesue.model.settings.WeChatPayInfoBean; +import com.fengliyan.tianlesue.utils.PayUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.PayWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.MemberPayDialog; +import com.fengliyan.uikit.toast.MaleToast; +import com.sand.qzf.paytypesdk.base.CallBack; +import com.sand.qzf.paytypesdk.base.PayTypeSdk; +import com.sand.qzf.paytypesdk.base.Resp; +import com.tencent.mm.opensdk.modelpay.PayReq; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/5/14. + */ + +public class GeneralMemberFragment extends Fragment implements View.OnClickListener { + + private NestedScrollView sv_general_member; + private TextView tv_member_time; + private ConstraintLayout lin_vip_shift1, lin_vip_shift2, lin_vip_shift3; + private TextView tv_vip_shift_name1, tv_vip_shift_name2, tv_vip_shift_name3; + private TextView tv_vip_unit1, tv_vip_unit2; + private TextView tv_vip_price1, tv_vip_price2, tv_vip_price3; + private TextView tv_vip_price_hint1, tv_vip_price_hint2, tv_vip_price_hint3; + private ImageView iv_vip_shift1, iv_vip_shift2; + private RecyclerView mOptionView; + private TextView tv_member_setting; + private LinearLayout lin_member_bottom_btn; + private TextView tv_member_open; + private TextView tv_member_sure; + private GeneralOptionsRecyclerAdapter mAdapter; + private int type = 6; + + private List mPrivileges = new ArrayList<>(); + private Boolean isVip = false; + private String mSelectedPayMethod = "alipay"; //默认微信 + + private MemberPayDialog mPayDialog; + boolean isWXHF;//微信支付是否是走汇付的微信小程序 + private String ghOriId; + private int mini_program_type; + private int goodsId; + private int goodsId1; + private int goodsId2; + private int goodsId3; + private String price; + private String price1; + private String price2; + private String price3; + private int defaultType = 0;//默认选中会员类型 + private OnScrollChange onScrollChange; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_general_member, container, false); + EventBus.getDefault().register(this); + initView(v); +// getData(type); + getWXPayType(); + return v; + } + + private void initView(View v) { + sv_general_member = v.findViewById(R.id.sv_general_member); + tv_member_time = v.findViewById(R.id.tv_member_time); + lin_vip_shift1 = v.findViewById(R.id.lin_vip_shift1); + tv_vip_shift_name1 = v.findViewById(R.id.tv_vip_shift_name1); + tv_vip_unit1 = v.findViewById(R.id.tv_vip_unit1); + tv_vip_price1 = v.findViewById(R.id.tv_vip_price1); + tv_vip_price_hint1 = v.findViewById(R.id.tv_vip_price_hint1); + lin_vip_shift2 = v.findViewById(R.id.lin_vip_shift2); + tv_vip_shift_name2 = v.findViewById(R.id.tv_vip_shift_name2); + tv_vip_unit2 = v.findViewById(R.id.tv_vip_unit2); + tv_vip_price2 = v.findViewById(R.id.tv_vip_price2); + tv_vip_price_hint2 = v.findViewById(R.id.tv_vip_price_hint2); + lin_vip_shift3 = v.findViewById(R.id.lin_vip_shift3); + tv_vip_shift_name3 = v.findViewById(R.id.tv_vip_shift_name3); + tv_vip_price3 = v.findViewById(R.id.tv_vip_price3); + tv_vip_price_hint3 = v.findViewById(R.id.tv_vip_price_hint3); + iv_vip_shift1 = v.findViewById(R.id.iv_vip_shift1); + iv_vip_shift2 = v.findViewById(R.id.iv_vip_shift2); + tv_member_setting = v.findViewById(R.id.tv_member_setting); + lin_member_bottom_btn = v.findViewById(R.id.lin_member_bottom_btn); + tv_member_open = v.findViewById(R.id.tv_member_open); + tv_member_sure = v.findViewById(R.id.tv_member_sure); + mOptionView = v.findViewById(R.id.general_recycler_view); + + mOptionView.setLayoutManager(new GridLayoutManager(requireContext(), 3)); + + if (null == mAdapter) { + mAdapter = new GeneralOptionsRecyclerAdapter(getActivity(), 0); + mAdapter.setOptions(mPrivileges); + mOptionView.setAdapter(mAdapter); + mOptionView.setNestedScrollingEnabled(true); + } + tv_vip_price_hint1.setPaintFlags(tv_vip_price_hint1.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + tv_vip_price_hint2.setPaintFlags(tv_vip_price_hint2.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + tv_vip_price_hint3.setPaintFlags(tv_vip_price_hint3.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + lin_vip_shift1.setOnClickListener(this); + lin_vip_shift2.setOnClickListener(this); + lin_vip_shift3.setOnClickListener(this); + tv_member_setting.setOnClickListener(this); + tv_member_sure.setOnClickListener(this); + tv_member_open.setOnClickListener(this); + + sv_general_member.setNestedScrollingEnabled(true); +// sv_general_member.setOnScrollChangeListener(new View.OnScrollChangeListener() { +// @Override +// public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { +// if (onScrollChange != null) { +// onScrollChange.scrollChange(scrollY); +// } +// } +// }); + } + + private void getData(int type) { + SettingManager.getMemberInfo((BaseActivity) getActivity(), type, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MemberBean result, String message) { + if (result.getInfo() != null) { + if (!TextUtils.isEmpty(result.getInfo().getExpire_date_new())) { + tv_member_time.setText("有效期至:" + result.getInfo().getExpire_date_new()); + isVip = true; + lin_member_bottom_btn.setVisibility(View.VISIBLE); + tv_member_open.setVisibility(View.GONE); + } else { + tv_member_time.setText("1000+用户已开通"); + isVip = false; + lin_member_bottom_btn.setVisibility(View.GONE); + tv_member_open.setVisibility(View.VISIBLE); + tv_member_open.setText("立即开通"); + } + SPUtils.saveBoolean(getActivity(), ConsUser.USER_VIP, isVip); + + if (SPUtils.getInt(getActivity(), ConsUser.GENDER) == 1) { + lin_member_bottom_btn.setVisibility(View.GONE); + tv_member_open.setVisibility(View.VISIBLE); + tv_member_open.setText("邀请好友开通"); + } + + List list = result.getInfo().getList(); + if (list != null && list.size() > 0) { + price1 = (int) Double.parseDouble(list.get(0).getPrice()) + list.get(0).getExpires_title(); + tv_vip_shift_name1.setText(list.get(0).getName()); + tv_vip_price1.setText((int) Double.parseDouble(list.get(0).getPrice()) + ""); + tv_vip_price_hint1.setText("原价¥" + list.get(0).getOrigin_price()); + + price2 = (int) Double.parseDouble(list.get(1).getPrice()) + list.get(1).getExpires_title(); + tv_vip_shift_name2.setText(list.get(1).getName()); + tv_vip_price2.setText((int) Double.parseDouble(list.get(1).getPrice()) + ""); + tv_vip_price_hint2.setText("原价¥" + list.get(1).getOrigin_price()); + + price3 = (int) Double.parseDouble(list.get(2).getPrice()) + list.get(2).getExpires_title(); + tv_vip_shift_name3.setText(list.get(2).getName()); + tv_vip_price3.setText((int) Double.parseDouble(list.get(2).getPrice()) + ""); + tv_vip_price_hint3.setText("原价¥" + list.get(2).getOrigin_price()); + + goodsId1 = list.get(0).getId(); + goodsId2 = list.get(1).getId(); + goodsId3 = list.get(2).getId(); + } + mAdapter.setVip_day_free_send(result.getInfo().getVip_day_free_send()); + } + mPrivileges.clear(); + for (int i = 0; i < 6; i++) { + MemberPrivilegesInfo info = new MemberPrivilegesInfo(); + info.setId(i); + if (i == 0) { + info.setDesc("半价无限畅聊"); + } + if (i == 1) { + info.setDesc("每日可享1次免费视频,单次最长1分钟"); + } +// if (i == 2 && isVip) { +// info.setName("VISIBLE"); +// } + mPrivileges.add(info); + } + mAdapter.setOptions(mPrivileges); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View v) { + if (v == tv_member_setting) { + Intent intent = new Intent(getContext(), PrivilegeSettingActivity.class); + intent.putExtra("isVip", isVip); + startActivity(intent); + } else if (v == lin_vip_shift1) { + lin_vip_shift1.setBackgroundResource(R.drawable.vip_select_bg2); + lin_vip_shift2.setBackgroundResource(R.drawable.vip_select_bg1); + lin_vip_shift3.setBackgroundResource(R.drawable.vip_select_bg1); + defaultType = 0; + if (goodsId1 == 1011) { + List list = mAdapter.getmOptions(); + list.get(0).setDesc("半价无限畅聊"); + list.get(1).setDesc("每日可享1次免费视频,单次最长1分钟"); + mAdapter.setOptions(list); + } + } else if (v == lin_vip_shift2) { + lin_vip_shift1.setBackgroundResource(R.drawable.vip_select_bg1); + lin_vip_shift2.setBackgroundResource(R.drawable.vip_select_bg2); + lin_vip_shift3.setBackgroundResource(R.drawable.vip_select_bg1); + defaultType = 1; + if (goodsId2 == 1012) { + List list = mAdapter.getmOptions(); + list.get(0).setDesc("半价无限畅聊"); + list.get(1).setDesc("每日可享2次免费视频,单次最长1分钟"); + mAdapter.setOptions(list); + } + } else if (v == lin_vip_shift3) { + lin_vip_shift1.setBackgroundResource(R.drawable.vip_select_bg1); + lin_vip_shift2.setBackgroundResource(R.drawable.vip_select_bg1); + lin_vip_shift3.setBackgroundResource(R.drawable.vip_select_bg2); + defaultType = 2; + if (goodsId3 == 1013) { + List list = mAdapter.getmOptions(); + list.get(0).setDesc("尊享无限文字畅聊"); + list.get(1).setDesc("每日可享3次免费视频,单次最长1分钟"); + mAdapter.setOptions(list); + } + } else if (v == tv_member_sure) { + if (defaultType == 1) { + goodsId = goodsId2; + price = price2; + } else if (defaultType == 2) { + goodsId = goodsId3; + price = price3; + } else { + goodsId = goodsId1; + price = price1; + } + showPay(goodsId); + } else if (v == tv_member_open) { + if (SPUtils.getInt(getActivity(), ConsUser.GENDER) == 1) { + Intent intent = new Intent(getContext(), InvitationActivity.class); + startActivity(intent); + } else { + if (defaultType == 1) { + goodsId = goodsId2; + price = price2; + } else if (defaultType == 2) { + goodsId = goodsId3; + price = price3; + } else { + goodsId = goodsId1; + price = price1; + } + showPay(goodsId); + } + } + } + + /** + * 支付方式 + */ + private void showPay(final int id) { + SettingManager.payConfig((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayConfigBean result, String tips) { + mPayDialog = new MemberPayDialog(getActivity(), result, "VIP " + price); + mPayDialog.setOnClickPayListener(new MemberPayDialog.OnClickPayListener() { + @Override + public void onClickPayListener(String selectedPayMethod) { + mSelectedPayMethod = selectedPayMethod; + confirmToPay(id); + mPayDialog.dismiss(); + } + }); + mPayDialog.show(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "获取支付信息失败"); + } + }); + } + + private String mOrderInfo; + + public static int SDK_PAY_FLAG = 101; + + private Runnable mPayRunnable = new Runnable() { + + @Override + public void run() { + PayTask alipay = new PayTask(getActivity()); + Map result = alipay.payV2(mOrderInfo, true); + String code = result.get("resultStatus"); + if (!TextUtils.isEmpty(code)) { + if ("9000".equals(code)) { + Message msg = new Message(); + msg.what = SDK_PAY_FLAG; + msg.obj = result; + mHandler.sendMessage(msg); + } + } + } + }; + + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + if (msg.what == SDK_PAY_FLAG) { + getData(type); + } + } + }; + + void getWXPayType() { + SettingManager.getWechatPaySite((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WXPayTypeBean result, String tips) { + isWXHF = result.getWechat_type() == 3; + ghOriId = result.getGh_ori_id(); + mini_program_type = result.getMini_program_type(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void confirmToPay(int id) { + if (isWXHF && mSelectedPayMethod.equals("wechat")) { + PayUtils.wxminiPay(getActivity(), id, 1, ghOriId, mini_program_type); + return; + } + SettingManager.payToRecharge((BaseActivity) getActivity(), mSelectedPayMethod, + id + "", 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayBean result, String message) { + if ("alipay".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + Thread payThread = new Thread(mPayRunnable); + payThread.start(); + } + } else if (result.getPay_platform_type() == 2) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + PayUtils.ailWeb(mOrderInfo, getActivity()); + } + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(getActivity(), PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + getActivity().startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(getActivity(), result.getPayinfo()); + } else { + PayTypeSdk.getInstance().cashierPay(getActivity(), result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + getData(type); + } + } + }); + } + } else if ("wechat".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + IWXAPI wxapi = WXAPIFactory.createWXAPI(getActivity(), Constant.WECHAT_APP_ID, false); + WeChatPayInfoBean wechatpayinfo = result.getWechatpayinfo(); + //调起微信支付 + PayReq req = new PayReq(); + req.appId = Constant.WECHAT_APP_ID; + req.partnerId = wechatpayinfo.getMch_id(); //商户号 + req.prepayId = wechatpayinfo.getPrepay_id(); //预付款id + req.nonceStr = wechatpayinfo.getNonce_str(); + req.timeStamp = wechatpayinfo.getTimestamp() + ""; + req.packageValue = "Sign=WXPay"; //固定值 + req.sign = wechatpayinfo.getPaySign(); + //先检测是否安装了微信 + boolean isWXAppInstalledAndSupported = wxapi.isWXAppInstalled(); + if (isWXAppInstalledAndSupported) { + wxapi.registerApp(Constant.WECHAT_APP_ID); + wxapi.sendReq(req); + } else { + MaleToast.showMessage(getActivity(), "未安装微信,不能支付"); + } + } else if (result.getPay_platform_type() == 2) { + PayTypeSdk.getInstance().cashierPay(getActivity(), result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + } + } + }); + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(getContext(), PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + getActivity().startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(getActivity(), result.getPayinfo()); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + Log.e("", ""); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + Log.e("", ""); + } + }); + } + + private void memberAuthority(final String type, final int value) { + SettingManager.memberAuthority((BaseActivity) getActivity(), type, value, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + //微信支付成功后回调 + public void onEventMainThread(PayEvent event) { + int errCode = event.getErrCode(); + if (errCode == 0) { + MaleToast.showSuccessMsg(getActivity(), "充值成功"); + getData(type); + } else if (errCode == -2) { + MaleToast.showFailureMsg(getActivity(), "充值取消"); + } else { + MaleToast.showFailureMsg(getActivity(), "充值失败"); + } + } + + @Override + public void onResume() { + super.onResume(); + getData(type); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + + if (null != mPayDialog && mPayDialog.isShowing()) { + mPayDialog.dismiss(); + } + } + + public void scrollTop() { +// if (sv_general_member != null) { +// sv_general_member.post(new Runnable() { +// @Override +// public void run() { +// sv_general_member.smoothScrollTo(0, 0); +// } +// }); +// } + } + + public interface OnScrollChange { + void scrollChange(int i); + } + + public void setOnScrollChange(OnScrollChange onScrollChange) { + this.onScrollChange = onScrollChange; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/GoddessPrivilegeActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/GoddessPrivilegeActivity.kt new file mode 100644 index 0000000..3b55dab --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/GoddessPrivilegeActivity.kt @@ -0,0 +1,367 @@ +package com.fengliyan.tianlesue.view.settings + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.text.TextUtils +import android.view.View +import android.widget.Toast +import androidx.recyclerview.widget.LinearLayoutManager +import com.alipay.sdk.app.PayTask +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.ConstUrl +import com.fengliyan.tianlesue.controller.constant.Constant +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager +import com.fengliyan.tianlesue.controller.user.manager.UserManager +import com.fengliyan.tianlesue.databinding.ActivityGirlPrivilegeBinding +import com.fengliyan.tianlesue.model.settings.* +import com.fengliyan.tianlesue.utils.PayUtils +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity +import com.fengliyan.tianlesue.view.base.PayWebViewActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBackBase +import com.fengliyan.tianlesue.view.base.utils.view.PayDialog +import com.fengliyan.tianlesue.view.base.utils.view.PayDialog.OnClickPayListener +import com.fengliyan.uikit.toast.MaleToast +import com.sand.qzf.paytypesdk.base.PayTypeSdk +import com.sand.qzf.paytypesdk.base.Resp +import com.tencent.mm.opensdk.modelpay.PayReq +import com.tencent.mm.opensdk.openapi.WXAPIFactory + +class GoddessPrivilegeActivity : BaseActivity() { + + lateinit var binding: ActivityGirlPrivilegeBinding + lateinit var adapater: BaseQuickAdapter + var datas = mutableListOf() + var isVip = false + lateinit var mPayDialog: PayDialog + private var mOrderInfo: String? = null + var monthPayId = -1 + var foreverPayId = -1 + var mSelectedPayMethod = "" + var isWXHF = false //微信支付是否是走汇付的微信小程序 + var ghOriId = "" + var mini_program_type = 0 + + + fun getWXPayType() { + SettingManager.getWechatPaySite(this, object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: WXPayTypeBean?, tips: String?) { + isWXHF = result?.wechat_type == 3 + ghOriId = result!!.gh_ori_id + mini_program_type = result.mini_program_type + } + + override fun onFailure(activity: BaseActivity, tip: String) {} + override fun onException(activity: BaseActivity, e: Throwable) {} + }) + } + + private val mPayRunnable = Runnable { + val alipay = PayTask(this@GoddessPrivilegeActivity) + val result = alipay.payV2(mOrderInfo, true) + val code = result["resultStatus"] + if (!TextUtils.isEmpty(code)) { + if ("9000" == code) { + val msg = Message() + msg.what = SuperMemberFragment.SDK_PAY_FLAG + msg.obj = result + mHandler.sendMessage(msg) + } + } + } + private val mHandler: Handler = object : Handler() { + override fun handleMessage(msg: Message) { + if (msg.what == SuperMemberFragment.SDK_PAY_FLAG) { + refresh() + } + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityGirlPrivilegeBinding.inflate(layoutInflater) + setContentView(binding.root) + initViews() + refresh() + getWXPayType() + } + + fun fill(result: GoddessPrivilegeBean) { + isVip = result.longX > 0 + if (isVip) { + datas[0].status = result.anchor!!.hide_chat + datas[1].status = result.anchor!!.hide_avatar + datas[2].status = result.anchor!!.hide_greet + datas[3].status = result.anchor!!.hide_read_msg + datas[4].status = result.anchor!!.hide_rank + datas[5].status = result.anchor!!.hide_dynamic + datas[6].status = result.anchor!!.hide_gift + datas[7].status = result.anchor!!.hide_guard + datas[8].status = result.anchor!!.hide_fans + datas[9].status = 1 - result.anchor?.hide_service_num!! + adapater.notifyDataSetChanged() + } + monthPayId = result.memberPrice[1].id + foreverPayId = result.memberPrice[0].id + binding.firstNameLabel.text = result.memberPrice[0].name + binding.secondNameLabel.text = result.memberPrice[1].name + binding.firstPriceLabel.text = "${result.memberPrice[0].price.toFloat().toInt()}" + binding.secondPriceLabel.text = "${result.memberPrice[1].price.toFloat().toInt()}" + binding.firstDateLabel.text = "立即享受" + binding.secondDateLabel.text = "立即享受" + binding.topStatusLabel.text = "你还没有特权哦~" + if (result.longX == 1) { +// binding.monthBtn.isClickable = false + binding.topStatusLabel.text = "你已拥有特权~" + binding.secondDateLabel.text = "${result.member_time}到期" + } else if (result.longX == 2) { + binding.foreverBtn.isClickable = false + binding.firstDateLabel.text = "已拥有特权" + binding.topStatusLabel.text = "你已拥有特权~" + } + } + + fun refresh() { + SettingManager.privilege_info(this, object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: GoddessPrivilegeBean?, + tips: String? + ) { + fill(result!!) + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + } + + }) + } + + fun update(menuBean: MenuBean) { + var value = 1 - menuBean.status + SettingManager.privilege_setting( + this, + menuBean.type, + "$value", + object : HttpUiCallBackBase() { + override fun onSuccessBase(activity: BaseActivity, result: Any?, tips: String) { + menuBean.status = 1 - menuBean.status; + adapater.notifyDataSetChanged() + } + }) + } + + fun initViews() { + setDefaultTitle() + setTitleName("女神特权") + UserManager.getUserInfo().avatar + binding.idLabel.text = "ID:${UserManager.getUserInfo().usercode}" + binding.avatarBorderImageView.visibility = View.INVISIBLE + binding.avatarImageView.setImageURI(ConstUrl.IMAGE_URL + UserManager.getUserInfo().avatar) + binding.nameLabel.setText(UserManager.getUserInfo().nickname) + datas.addAll(MenuBean.girlPrivileges()) + binding.recyclerView.layoutManager = LinearLayoutManager(this) + binding.tvVipContent.setOnClickListener { + val intent = Intent( + this, + BaseWebViewActivity::class.java + ) + intent.putExtra("ClickUrl", ConstUrl.VIP_AGREEMENT_URL) + startActivity(intent) + } + adapater = object : + BaseQuickAdapter(R.layout.item_girl_privilege, datas) { + override fun convert(helper: BaseViewHolder, item: MenuBean) { + helper.setImageResource(R.id.iconImageview, item.image) + helper.setText(R.id.nameLabel, item.name) + helper.setText(R.id.descLabel, item.desc) + helper.setImageResource( + R.id.switchImageView, + if (item.status == 1) R.mipmap.privilege_on else R.mipmap.privilege_off + ) + } + } + adapater.setOnItemClickListener { adapter, view, position -> + if (!isVip) { + MaleToast.showMessage(GoddessPrivilegeActivity@ this, "您还不是会员") + return@setOnItemClickListener + } + update(datas[position]) + } + binding.recyclerView.adapter = adapater + binding.foreverBtn.setOnClickListener { + if (foreverPayId == -1) { + return@setOnClickListener + } + showPay(foreverPayId) + } + binding.monthBtn.setOnClickListener { + if (monthPayId == -1) { + return@setOnClickListener + } + showPay(monthPayId) + } + + } + + private fun showPay(id: Int) { + if (binding.cbVipCheck.isChecked) { + SettingManager.payConfig( + GoddessPrivilegeActivity@ this, + object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: PayConfigBean?, + tips: String? + ) { + mPayDialog = + PayDialog( + this@GoddessPrivilegeActivity, + R.style.SelectiveDialog, + result + ) + mPayDialog.setOnClickPayListener(object : OnClickPayListener { + override fun onClickWeixinPayListener() { + mSelectedPayMethod = "wechat" + confirmToPay(id) + mPayDialog.dismiss() + } + + override fun onClickAliPayListener() { + mSelectedPayMethod = "alipay" + confirmToPay(id) + mPayDialog.dismiss() + } + }) + mPayDialog.show() + } + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(activity, "获取支付信息失败") + } + }) + } else { + MaleToast.showMessage(this, "请先同意会员服务协议") + } + } + + private fun confirmToPay(id: Int) { + if (isWXHF && mSelectedPayMethod == "wechat") { + PayUtils.wxminiPay(this, id, 1, ghOriId, mini_program_type) + return + } + + SettingManager.payToRecharge( + this, + mSelectedPayMethod, + "${id}", + 1, + object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: PayBean?, + message: String? + ) { + if ("alipay" == mSelectedPayMethod) { + if (result!!.pay_platform_type == 1) { + if (null != result!!.payinfo) { + mOrderInfo = result!!.payinfo + val payThread = Thread(mPayRunnable) + payThread.start() + } + } else if (result.pay_platform_type == 2) { + if (null != result!!.payinfo) { + mOrderInfo = result!!.payinfo + PayUtils.ailWeb(mOrderInfo, this@GoddessPrivilegeActivity) + } + } else if (result.pay_platform_type == 4) { + val intent = Intent( + this@GoddessPrivilegeActivity, + PayWebViewActivity::class.java + ) + intent.putExtra("ClickUrl", result.kqPayInfo) + startActivity(intent) + } else if (result.pay_platform_type == 5) { + PayUtils.SFTPay(this@GoddessPrivilegeActivity, result.payinfo) + } else { + PayTypeSdk.getInstance().cashierPay( + this@GoddessPrivilegeActivity, result.sandpayinfo.cashierUrl + ) { resp -> + if (resp.status == Resp.SUCCESS || resp.status == Resp.FINISH) { + refresh() + } + } + + } + } else if ("wechat" == mSelectedPayMethod) { + if (result!!.pay_platform_type == 1) { + val wxapi = WXAPIFactory.createWXAPI( + this@GoddessPrivilegeActivity, + Constant.WECHAT_APP_ID, + false + ) + val wechatpayinfo = result!!.wechatpayinfo + val req = PayReq() + req.appId = Constant.WECHAT_APP_ID + req.partnerId = wechatpayinfo.mch_id //商户号 + req.prepayId = wechatpayinfo.prepay_id //预付款id + req.nonceStr = wechatpayinfo.nonce_str + req.timeStamp = wechatpayinfo.timestamp.toString() + "" + req.packageValue = "Sign=WXPay" //固定值 + req.sign = wechatpayinfo.paySign + val isWXAppInstalledAndSupported = wxapi.isWXAppInstalled + if (isWXAppInstalledAndSupported) { + wxapi.registerApp(Constant.WECHAT_APP_ID) + wxapi.sendReq(req) + } else { + MaleToast.showMessage(this@GoddessPrivilegeActivity, "未安装微信,不能支付") + } + } else if (result!!.pay_platform_type == 2) { + PayTypeSdk.getInstance().cashierPay( + this@GoddessPrivilegeActivity, result.sandpayinfo.cashierUrl + ) { resp -> + if (resp.status == Resp.SUCCESS || resp.status == Resp.FINISH) { + refresh() + } + } + } else if (result.pay_platform_type == 4) { + val intent = Intent( + this@GoddessPrivilegeActivity, + PayWebViewActivity::class.java + ) + intent.putExtra("ClickUrl", result.kqPayInfo) + startActivity(intent) + } else if (result.pay_platform_type == 5) { + PayUtils.SFTPay(this@GoddessPrivilegeActivity, result.payinfo) + } + } + } + + override fun onFailure(activity: BaseActivity, tip: String) { + Toast.makeText(activity, tip, Toast.LENGTH_SHORT).show() + } + + override fun onException(activity: BaseActivity, e: Throwable) { + + } + }) + } + + override fun onResume() { + super.onResume() + refresh() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/InfoEditActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InfoEditActivity.java new file mode 100644 index 0000000..c7ea1c7 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InfoEditActivity.java @@ -0,0 +1,1164 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.Manifest; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.media.ThumbnailUtils; +import android.net.Uri; +import android.os.Bundle; +import android.provider.MediaStore; +import android.text.Html; +import android.text.TextUtils; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + +import com.bigkoo.pickerview.builder.OptionsPickerBuilder; +import com.bigkoo.pickerview.builder.TimePickerBuilder; +import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener; +import com.bigkoo.pickerview.listener.OnOptionsSelectListener; +import com.bigkoo.pickerview.listener.OnTimeSelectListener; +import com.bigkoo.pickerview.view.OptionsPickerView; +import com.bigkoo.pickerview.view.TimePickerView; +import com.facebook.drawee.view.SimpleDraweeView; +import com.google.gson.Gson; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.main.manager.GlobalManager; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.controller.settings.adapter.InfoEditPhotoRecyclerAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.settings.manager.UserAvatarManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.im.uikit.common.util.file.AttachmentStore; +import com.fengliyan.tianlesue.im.uikit.common.util.file.FileUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageType; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.StorageUtil; +import com.fengliyan.tianlesue.im.uikit.common.util.storage.SysSPUtils; +import com.fengliyan.tianlesue.im.uikit.common.util.string.MD5; +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.main.GlobalConfigBean; +import com.fengliyan.tianlesue.model.settings.UserHomeBean; +import com.fengliyan.tianlesue.model.settings.UserInfoBean; +import com.fengliyan.tianlesue.utils.PermissionUtil; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.SimpleItemTouchCallBack; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.utils.camera2.BitmapUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.ImageUtils; +import com.fengliyan.tianlesue.view.diooto.Diooto; +import com.fengliyan.tianlesue.view.diooto.config.DiootoConfig; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; +import com.fengliyan.tianlesue.view.dynamics.activity.QYPreviewVideoActivity; +import com.fengliyan.tianlesue.view.main.CityPickerActivity; +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog; +import com.fengliyan.tianlesue.view.main.dialog.PermissionDialog; +import com.fengliyan.tianlesue.view.settings.dialog.WQTipsDialog; +import com.fengliyan.tianlesue.view.settings.video.VideoSelectActivity; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.sketch.SketchImageView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import io.reactivex.disposables.Disposable; +import kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; + + +public class InfoEditActivity extends BaseActivity implements View.OnClickListener, UserAvatarManager.UserImgListener { + private static final String TAG = "InfoEditActivity"; + public static final String IMAGE_CACHE_DIR = ConstUrl.DEFAULT_PATH + "/cache"; + private String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; + public static final int VIDEO_COVER_REQUEST = 501;//封面视频 + public static final int SIGNATURE_REQUEST = 502;//个性签名 + public static final int MULTI_SELECTOR_REQUEST = 200; + public static final int PERMISSION_REQUEST_CODE = 101; + public static final int REQUEST_EDIT_NICKNAME = 210; + public static final int MAX_IMAGE_COUNT = 6; + private RecyclerView mPhotoListView; + private InfoEditPhotoRecyclerAdapter mPhotoAdapter; + private View mNickNameLayout; + private View mBirthDayLayout; + private RelativeLayout mJobLayout; + private View mCityLayout; + private RelativeLayout mSignLayout; + private TextView mNickName; + private TextView mBirthDay; + private TextView mJob; + private TextView mCity; + private TextView mSign; + private RelativeLayout settings_info_edit_ip_city_layout; + private TextView settings_info_edit_ip_city; + private View ip_city_line; + private MultiImageSelector mSelector; + private TimePickerView mAgePicker; + private String mCityId; + private boolean isAllPermissionsGranted; + private Disposable mDisposable; + private StringBuilder mImages; + private UserInfoBean mUserInfo; + private Button mConfirmButton; + private List mRequestArray = new ArrayList<>(); + private int mRequestCount = 0; + private HashMap photoListIndexMap; + private SimpleDraweeView avatarImageView; + private SimpleDraweeView videoCoverImageView; + private ImageView info_video_delete; + private List mPhotoDataList = new ArrayList() { + { + add("selector"); + add(""); + add(""); + add(""); + add(""); + add(""); + } + }; + + private List mOldPhotoDataList = new ArrayList() { + { + add("selector"); + add(""); + add(""); + add(""); + add(""); + add(""); + } + }; + private UserAvatarManager mManager; + private File mOrgFile; + private String mFilePath; + private String mOldNickName = ""; + private String mOldBirthday = ""; + private String mOldCity = ""; + private String mOldJob = ""; + private WQTipsDialog mWQTipsDialog; + private String mEdit_nickname_tip; + private String mNickname_tip; + // private VideoMessageHelper helper; + private File videoFile; + private boolean isChooseAvatar = false; + String avatarPath; + String avatarUrl; + boolean isChooseVideo = false; + String videoCoverPath; + String videoCoverUrl; + String videoUrl; + TextView videoStatusLabel; + View videoBtn; + private String del_video = "0"; + private String job = "自由职业-自由职业"; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setTitleName("编辑资料"); + setContentView(R.layout.activity_settings_info_edit); + mWQTipsDialog = new WQTipsDialog(this); + initView(); + initAgePicker(); + getUserInfo(); + mManager = new UserAvatarManager(this); + } + + private void initView() { + videoStatusLabel = findViewById(R.id.videoStatusLabel); + avatarImageView = findViewById(R.id.avatarImageView); + videoCoverImageView = findViewById(R.id.videoCoverImageView); + info_video_delete = findViewById(R.id.info_video_delete); + videoCoverImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(InfoEditActivity.this, QYPreviewVideoActivity.class); + if (videoFile != null) { + intent.putExtra("videoUrl", videoFile.getAbsolutePath()); + startActivity(intent); + return; + } + if (videoUrl != null) { + intent.putExtra("videoUrl", Constans.IMAGE_URL + videoUrl); + startActivity(intent); + return; + } + + } + }); + mPhotoListView = findViewById(R.id.settings_info_edit_photos); + mNickNameLayout = findViewById(R.id.settings_info_edit_nick_name_layout); + mBirthDayLayout = findViewById(R.id.settings_info_edit_birthday_layout); + mJobLayout = findViewById(R.id.settings_info_edit_job_layout); + mCityLayout = findViewById(R.id.settings_info_edit_city_layout); + mSignLayout = findViewById(R.id.settings_info_edit_sign_layout); + mNickName = findViewById(R.id.settings_info_edit_nick_name); + mBirthDay = findViewById(R.id.settings_info_edit_birthday); + mJob = findViewById(R.id.settings_info_edit_job); + mCity = findViewById(R.id.settings_info_edit_city); + mSign = findViewById(R.id.settings_info_edit_sign); + settings_info_edit_ip_city_layout = findViewById(R.id.settings_info_edit_ip_city_layout); + settings_info_edit_ip_city = findViewById(R.id.settings_info_edit_ip_city); + ip_city_line = findViewById(R.id.ip_city_line); + mConfirmButton = findViewById(R.id.settings_info_edit_button_confirm); + TextView zhushi_content = findViewById(R.id.zhushi_content); + String str = "上传图片需审核通过后才能更新展示"; + zhushi_content.setText(Html.fromHtml(str)); + mSelector = MultiImageSelector.create().multi().count(MAX_IMAGE_COUNT); + mNickNameLayout.setOnClickListener(this); + mBirthDayLayout.setOnClickListener(this); + mJobLayout.setOnClickListener(this); + mCityLayout.setOnClickListener(this); + mSignLayout.setOnClickListener(this); + mConfirmButton.setOnClickListener(this); + info_video_delete.setOnClickListener(this); + videoBtn = findViewById(R.id.videoBtn); + if (UserManager.getUserInfo().isWomen()) { + videoBtn.setVisibility(View.VISIBLE); + } else { + videoBtn.setVisibility(View.GONE); + } + videoBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isChooseVideo = true; +// if (userDetailInfo.getVideo_audit() != 2) { + checkPermission(0); +// } else { +// MaleToast.showMessage(this, "封面视频审核中"); +// } + +// helper.chooseVideoFromLocal(); + } + }); + findViewById(R.id.avatarBtn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + checkPermission(1); + } + }); + mPhotoListView.setLayoutManager(new GridLayoutManager(this, 3)); + mPhotoListView.setNestedScrollingEnabled(false); + ViewGroup.LayoutParams layoutParams = mPhotoListView.getLayoutParams(); + layoutParams.height = Utils.dip2px(this, 240); + mPhotoListView.setLayoutParams(layoutParams); + + mPhotoAdapter = new InfoEditPhotoRecyclerAdapter(this); + mPhotoAdapter.setPhotoList(mPhotoDataList); + mPhotoAdapter.setOnSelectorClickedListener(new InfoEditPhotoRecyclerAdapter + .OnSelectorClickedListener() { + @Override + public void onSelectorClicked() { + checkPermission(2); + } + + @Override + public void onClickImage(List mPhotoList, int position) { + if (null != mPhotoList && mPhotoList.size() != 0) { + List imageUrl = new ArrayList<>(); + for (String imagePath : mPhotoList) { + if (!TextUtils.isEmpty(imagePath) && !imagePath.equals("selector")) { + if (imagePath.contains("uploads/")) { + imageUrl.add(StrU.getResourcePath(imagePath, InfoEditActivity.this)); + } else { + imageUrl.add("file://" + imagePath); + } + } + } + clickImage((ArrayList) imageUrl, position); + } + } + }); + mPhotoListView.setAdapter(mPhotoAdapter); + // 拖拽移动和左滑删除 + SimpleItemTouchCallBack simpleItemTouchCallBack = new SimpleItemTouchCallBack(mPhotoAdapter); + ItemTouchHelper helper = new ItemTouchHelper(simpleItemTouchCallBack); + helper.attachToRecyclerView(mPhotoListView); + + File file = new File(IMAGE_CACHE_DIR); + + if (!file.exists()) { + file.mkdirs(); + } + } + + private PermissionDialog permissionDialog; + + /** + * @param type 0.封面视频 1.头像 2.相册 + */ + private void checkPermission(int type) { + permissionDialog = new PermissionDialog(InfoEditActivity.this, permissions); + permissionDialog.show(); + XXPermissions.with(InfoEditActivity.this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + if (type == 0) { + VideoSelectActivity.launchForResult(InfoEditActivity.this, VideoSelectActivity.TYPE_VIDEO_CUT, VIDEO_COVER_REQUEST); + } else { + startImageSelector(type == 1); + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(InfoEditActivity.this); + customAlertDialog.setTitle("私语需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(InfoEditActivity.this); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + /** + * 跳到图片展示页 + * + * @param pathList + * @param innerCount + */ + private void clickImage(ArrayList pathList, int innerCount) { + String[] strings = new String[pathList.size()]; + for (int i = 0; i < pathList.size(); i++) { + strings[i] = pathList.get(i); + } + Diooto diooto = new Diooto(this) + .urls(strings) + .type(DiootoConfig.PHOTO) + .immersive(true) + .position(innerCount, 0) + .views(mPhotoListView, R.id.info_edit_photo_normal, pathList.size()) + .loadPhotoBeforeShowBigImage(new Diooto.OnLoadPhotoBeforeShowBigImageListener() { + @Override + public void loadView(SketchImageView sketchImageView, int position) { + sketchImageView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + return false; + } + }); + } + }) + .start(); + } + + private void compressAndUpload() { + List photoList = mPhotoAdapter.getmPhotoList(); + Iterator i = photoList.iterator(); + int realSize = 0; + int currentListCount = 6; + photoListIndexMap = new HashMap<>(); + for (int index = 0; index < photoList.size(); index++) { + String path = photoList.get(index); + if ("selector".equals(path)) { + currentListCount = index; + } + if ("".equals(path) || "selector".equals(path) || path.contains("uploads/")) { + continue; + } + photoListIndexMap.put(realSize, index); + realSize++; + } + + final UploadFile[] uploadFiles = new UploadFile[realSize]; + int count = 0; + while (i.hasNext()) { + String path = i.next(); + if ("".equals(path) || "selector".equals(path) || path.contains("uploads/")) { + continue; + } + path = ImageUtils.compressImage(this, path, Constant.IMAGE_MEMORY_SIZE, true); + File file = new File(path); + UploadFile uploadFile = new UploadFile("file[" + count + "]", file); + uploadFiles[count] = uploadFile; + count++; + } + + if (null != uploadFiles) { + if (uploadFiles.length != 0) { + if (uploadFiles[0].getFile().exists()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + uploadImage(uploadFiles); + } + }); + } + } else { + final StringBuilder stringBuilder = new StringBuilder(); + for (int i1 = 0; i1 < currentListCount; i1++) { + String str = photoList.get(i1); + if (TextUtils.isEmpty(str) || "selector".equals(str)) { + continue; + } + stringBuilder.append(str); + if (i1 < currentListCount - 1) { + stringBuilder.append(","); + } + } + runOnUiThread(new Runnable() { + @Override + public void run() { + editProfile(stringBuilder.toString()); + } + }); + } + } + } + + private void uploadImage(final UploadFile[] uploadFiles) { + DynamicsManager.uploadImage(this, uploadFiles, "album", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + mImages = new StringBuilder(); + List photoList = mPhotoAdapter.getmPhotoList(); + for (int i = 0; i < result.size(); i++) { + Integer integer = photoListIndexMap.get(i); + photoList.set(integer, result.get(i).getUrl()); + } + + for (int i = 0; i < photoList.size(); i++) { + String str = photoList.get(i); + if (TextUtils.isEmpty(str) || "selector".equals(str)) { + continue; + } + mImages.append(str); + if (i < photoList.size() - 1) { + mImages.append(","); + } + } + + editProfile(mImages.toString()); + photoListIndexMap.clear(); + + //上传成功后删掉本地图片 + new Thread(new Runnable() { + @Override + public void run() { + for (UploadFile uploadFile : uploadFiles) { + File file = uploadFile.getFile(); + if (file.exists()) { + file.delete(); + } + } + } + }).start(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "图片上传失败"); + } + }); + } + + // 最后一步之前检测视频和头像是否有变化 + private void editProfile(String albums) { + if (videoFile != null && videoUrl == null && videoCoverUrl == null) { + uploadVideo(albums); + return; + } + if (avatarPath != null && avatarUrl == null) { + //uploadAvatar + uploadAvatar(albums); + return; + } + if (mUserInfo == null) { + return; + } + if (null == mCityId) { + mCityId = "110100"; + } + + Map map = new HashMap<>(); + + map.put("nickname", mNickName.getText().toString()); + map.put("gender", mUserInfo.getGender() + ""); + map.put("avatar", avatarUrl); + map.put("city", mCityId); + map.put("job", job); + map.put("birthday", mBirthDay.getText().toString()); + map.put("del_video", del_video); + if (videoUrl != null) { + map.put("video_url", videoUrl); + map.put("video_img", videoCoverUrl); + } + if (null != albums) { + map.put("albums", albums); + } + map.put("signature", mSign.getText().toString()); + + RegisterManager.completeProfile(this, map, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final LoginBean result, String message) { + MaleToast.showMessage(InfoEditActivity.this, "更新成功,头像和视频通过审核后才能展示"); + + new Thread(new Runnable() { + @Override + public void run() { + //修改后本地要进行储存更新 + StorageManager.getInstance(InfoEditActivity.this).putBean("loginBean", result); + } + }).start(); + + + UserManager.getInstance().notifyUserInfoChanged(result.getUserinfo()); + UserManager.setUserInfo(result.getUserinfo()); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(InfoEditActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(InfoEditActivity.this, "更新失败"); + } + }); + } + + @Override + public void onClick(View view) { + if (view == mNickNameLayout) { + if (TextUtils.isEmpty(mNickname_tip)) { + Intent intent = new Intent(this, NickNameEditActivity.class); + intent.putExtra("nickName", mNickName.getText()); + intent.putExtra("nickNameTips", mEdit_nickname_tip); + startActivityForResult(intent, REQUEST_EDIT_NICKNAME); + } else mWQTipsDialog.show(mNickname_tip); + } else if (view == mBirthDayLayout) { + mAgePicker.show(); + } else if (view == mCityLayout) { + Intent intent = new Intent(this, CityPickerActivity.class); + startActivityForResult(intent, 1001); + } else if (view == info_video_delete) { + videoCoverImageView.setVisibility(View.GONE); + info_video_delete.setVisibility(View.GONE); + videoStatusLabel.setVisibility(View.VISIBLE); + videoBtn.setClickable(true); + videoFile = null; + videoUrl = ""; + videoCoverUrl = ""; + del_video = "1"; + } else if (view == mConfirmButton) { + submit(); + } else if (view == mJobLayout) { + pvOptions.show(); + } else if (view == mSignLayout) { + Intent intent = new Intent(this, PersonalSignatureActivity.class); + intent.putExtra("signature", mSign.getText()); + startActivityForResult(intent, SIGNATURE_REQUEST); + } + } + + private ProgressDialog progressDialog; + + void uploadVideoCover() { + UploadFile uploadFile = new UploadFile(System.currentTimeMillis() + ".jpg", videoCoverPath); + UploadFile[] files = new UploadFile[]{uploadFile}; + DynamicsManager.uploadImage(this, files, "cover_video", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + videoCoverUrl = result.get(0).getUrl(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "图片上传失败"); + } + }); + } + + void uploadAvatar(String albums) { + UploadFile uploadFile = new UploadFile(System.currentTimeMillis() + ".jpg", avatarPath); + UploadFile[] files = new UploadFile[]{uploadFile}; + DynamicsManager.uploadImage(this, files, "album", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + avatarUrl = result.get(0).getUrl(); + editProfile(albums); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "图片上传失败"); + } + }); + } + + void uploadVideo(String albums) { + uploadVideoCover(); + progressDialog = ProgressDialog.show(this, "正在上传视频", "请稍后..."); + UploadFile uploadFile = new UploadFile(System.currentTimeMillis() + ".mp4", videoFile); + UploadFile[] files = new UploadFile[]{uploadFile}; + DynamicsManager.uploadImage(this, files, "cover_video", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + progressDialog.dismiss(); + if (result.size() > 0) { + videoUrl = result.get(0).getUrl(); + editProfile(albums); + } + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + progressDialog.dismiss(); + MaleToast.showMessage(activity, "视频上传失败"); + } + }); + } + + + void submit() { + boolean avatarChange = !TextUtils.isEmpty(avatarPath); + boolean isName = mOldNickName.equals(mNickName.getText()); + boolean isBirthday = mOldBirthday.equals(mBirthDay.getText()); + boolean isCity = mOldCity.equals(mCity.getText()); + boolean photoChange = photoChange(mPhotoDataList, mOldPhotoDataList); + +// if (isName && isBirthday && isCity && !avatarChange && !photoChange && videoFile == null && !del_video.equals("1")) { //姓名,生日,城市都没有改变 +// finish(); +// } else { + updateData(); +// } + } + + private boolean photoChange(List list1, List list2) { + boolean photoChange = false; + if (list1.containsAll(list2) && list2.containsAll(list1)) { + for (int i = 0; i < list1.size(); i++) { //判断元素顺序是不是一致 + photoChange = !(list1.get(i).equals(list2.get(i))); + if (photoChange) { + break; + } + } + } else { + photoChange = true; + } + return photoChange; + } + + /** + * 更新数据 + */ + private void updateData() { + boolean hasPhoto = false; + for (String path : mPhotoDataList) { + if (path.equals("") || path.equals("selector")) { + continue; + } + + hasPhoto = true; + } + + if (!hasPhoto) { + editProfile(null); + } else { + new Thread(new Runnable() { + @Override + public void run() { + compressAndUpload(); + } + }).start(); + + } + } + + public void removeImage(String path) { + path = path.replace("file:", ""); + mPhotoDataList.remove(path); + } + + public void startImageSelector(boolean isChooseAvatar) { + isChooseVideo = false; + this.isChooseAvatar = isChooseAvatar; + mSelector.multi(); + mSelector.count(1); + mSelector.start(this, MULTI_SELECTOR_REQUEST); + } + + public int pathCount() { + Iterator iterator = mPhotoDataList.iterator(); + int count = 0; + while (iterator.hasNext()) { + String path = iterator.next(); + if (!path.equals("") && !path.equals("selector")) { + count++; + } + } + + return count; + } + + private void initAgePicker() { + Calendar endCalendar = Calendar.getInstance(); + endCalendar.set(endCalendar.get(Calendar.YEAR) - 18 + , endCalendar.get(Calendar.MONTH) + , endCalendar.get(Calendar.DAY_OF_MONTH)); + + Calendar startCalendar = Calendar.getInstance(); + startCalendar.set(1940, 1, 1); + + mAgePicker = new TimePickerBuilder(this, new OnTimeSelectListener() { + @Override + public void onTimeSelect(Date date, View v) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int month = calendar.get(Calendar.MONTH) + 1; + int day = calendar.get(Calendar.DATE); + int year = calendar.get(Calendar.YEAR); + mBirthDay.setText(year + "-" + month + "-" + day + " "); + } + }).setRangDate(startCalendar, endCalendar).build(); + + mAgePicker.setDate(endCalendar); + initOptionPicker(); + } + + public void getUserInfo() { + SettingManager.getHomeUser(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, UserHomeBean result, String message) { + if (result.getUserinfo() != null) { +// videoBtn.setClickable(result.getUserinfo().getVideo_status() != 1); +// if (result.getUserinfo().getVideo_status() == 1) { + if (!TextUtils.isEmpty(result.getUserinfo().getVideo_url())) { + videoBtn.setClickable(false); + del_video = "0"; + videoCoverImageView.setVisibility(View.VISIBLE); + info_video_delete.setVisibility(View.VISIBLE); + videoStatusLabel.setVisibility(View.GONE); + videoCoverImageView.setImageURI(Constans.IMAGE_URL + result.getUserinfo().getVideo_cover_url()); + videoCoverUrl = result.getUserinfo().getVideo_cover_url(); + videoUrl = result.getUserinfo().getVideo_url(); + } +// } + //旧昵称初始化 + mOldNickName = result.getUserinfo().getNickname(); + mNickName.setText(result.getUserinfo().getNickname()); + //旧生日初始化 + mOldBirthday = result.getUserinfo().getBirthday(); + mBirthDay.setText(result.getUserinfo().getBirthday()); + //旧城市初始化 + mOldCity = result.getUserinfo().getCity(); + mCity.setText(result.getUserinfo().getCity()); + mCityId = GlobalManager.getCityMap().get(result.getUserinfo().getCity()); + mUserInfo = result.getUserinfo(); + avatarUrl = mUserInfo.getAvatar(); + avatarImageView.setImageURI(StrU.getResourcePath(mUserInfo.getAvatar(), activity)); + mOldJob = result.getUserinfo().getJob(); + mSign.setText(result.getUserinfo().getSignature()); + //提示语 + mNickname_tip = result.getUserinfo().getNickname_tip(); + mEdit_nickname_tip = result.getUserinfo().getEdit_nickname_tip(); + + List album_list = result.getUserinfo().getAlbum_list(); + mRequestArray.addAll(album_list); + int size = album_list.size(); + if (size > 0) { + for (int i = 0; i < size; i++) { + mPhotoDataList.set(i, album_list.get(i)); + mOldPhotoDataList.set(i, album_list.get(i)); + + } + if (size < 6) { + mPhotoDataList.set(size, "selector"); + mOldPhotoDataList.set(size, "selector"); + } + mPhotoAdapter.setPhotoList(mPhotoDataList); + mPhotoAdapter.notifyDataSetChanged(); + } + } + //职业 + if (!TextUtils.isEmpty(result.getUserinfo().getJob())) { + job = result.getUserinfo().getJob(); + } else { + job = "自由职业-自由职业"; + } + List jobList = Arrays.asList(job.split("-")); + if (jobList.size() > 0) { + mJob.setText(jobList.get(jobList.size() - 1)); + } + + if (result.getIp_info() != null) { + settings_info_edit_ip_city_layout.setVisibility(View.VISIBLE); + ip_city_line.setVisibility(View.VISIBLE); + settings_info_edit_ip_city.setText(!TextUtils.isEmpty(result.getIp_info().getProvince()) ? result.getIp_info().getProvince() : !TextUtils.isEmpty(result.getIp_info().getCity()) ? result.getIp_info().getCity() : "未知"); + if (mCityId == null) { + if (!TextUtils.isEmpty(result.getIp_info().getCity())) { + mCityId = GlobalManager.getCityMap().get(result.getIp_info().getCity()); + } + } + if (TextUtils.isEmpty(mCity.getText())) { + mCity.setText(!TextUtils.isEmpty(result.getIp_info().getProvince()) ? result.getIp_info().getProvince() : !TextUtils.isEmpty(result.getIp_info().getCity()) ? result.getIp_info().getCity() : "未知"); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + public void onDestroy() { + super.onDestroy(); + if (null != mAgePicker && mAgePicker.isShowing()) { + mAgePicker.dismiss(); + } + + if (null != mDisposable && !mDisposable.isDisposed()) { + mDisposable.dispose(); + } + + //销毁时删除所有图片 + new Thread(new Runnable() { + @Override + public void run() { + delFiles(IMAGE_CACHE_DIR); + } + }).start(); + } + + public static void delFiles(String filePath) { + File file = new File(filePath); + if (!file.exists()) { + return; + } + String[] list = file.list(); + if (list == null) { + return; + } + File temp = null; + String path = null; + for (String item : list) { + path = filePath + File.separator + item; + temp = new File(path); + if (temp.isFile()) { + temp.delete(); + } + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { +// if (isChooseVideo) { +// helper.onGetLocalVideoResult(data); +// return; +// } + super.onActivityResult(requestCode, resultCode, data); + if (mManager != null) { + mManager.onActivityResult(requestCode, resultCode, data); + } + if (requestCode == MULTI_SELECTOR_REQUEST && resultCode == RESULT_OK) { + List albumList = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + String s = "file://" + albumList.get(0); + mManager.whoStartCropWithUi(Uri.parse(s)); + } else if (requestCode == REQUEST_EDIT_NICKNAME && RESULT_OK == resultCode) { + String newName = data.getStringExtra("newName"); + mNickName.setText(newName); + } else if (requestCode == 1001 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(this, ConsUser.PICKER_CITY + "", city); + mCity.setText(city); + if (!TextUtils.isEmpty(city)) { + mCityId = GlobalManager.getCityMap().get(city); + } + } + } else if (requestCode == VIDEO_COVER_REQUEST) {//封面视频 + if (data != null) { + String videoPath = data.getStringExtra("VideoPath"); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onActivityResult: videoPath----------->" + videoPath); + + String md5 = MD5.getStreamMD5(videoPath); + String filename = md5 + "." + FileUtil.getExtensionName(videoPath); + String md5Path = StorageUtil.getWritePath(filename, StorageType.TYPE_VIDEO); + + if (AttachmentStore.copy(videoPath, md5Path) != -1) { + videoFile = new File(md5Path); + } + Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(videoFile.getAbsolutePath(), MediaStore.Video.Thumbnails.FULL_SCREEN_KIND); + BitmapUtils.savePicNoRotate(BitmapUtils.toByteArray(bitmap), "video_cover", + new Function2() { + @Override + public Unit invoke(String s, String s2) { + bitmap.recycle(); + runOnUiThread(new Runnable() { + @Override + public void run() { + List paths = new ArrayList<>(); + paths.add(s); + videoUrl = null; + videoCoverUrl = null; + videoCoverPath = s; + del_video = "0"; + videoCoverImageView.setVisibility(View.VISIBLE); + info_video_delete.setVisibility(View.VISIBLE); + videoStatusLabel.setVisibility(View.GONE); + videoCoverImageView.setImageURI("file://" + videoCoverPath); + videoBtn.setClickable(false); + } + }); + return null; + } + }, new Function1() { + @Override + public Unit invoke(String s) { + runOnUiThread(new Runnable() { + @Override + public void run() { + MaleToast.showMessage(InfoEditActivity.this, "获取视频缩略图失败"); + + } + }); + return null; + } + }); + } + } else if (requestCode == SIGNATURE_REQUEST && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("signature"); + isSignature = true; + mSign.setText(city); + } + } + } + + @Override + public void getUserImg(@Nullable final String path) { + if (isChooseAvatar) { + this.avatarPath = path; + avatarUrl = null; + avatarImageView.setImageURI("file://" + this.avatarPath); + return; + } + if (null != path && !TextUtils.isEmpty(path)) { + List albumList = new ArrayList<>(); + + albumList.add(path); + + for (int i = 0; i < albumList.size(); i++) { + if (5 - i >= 0) { + mPhotoDataList.remove(5 - i); + } + } + + int realSize = 0; + for (int i = 0; i < mPhotoDataList.size(); i++) { + if (!"".equals(mPhotoDataList.get(i)) && !"selector".equals(mPhotoDataList.get(i))) { + realSize++; + } + } + + mPhotoDataList.addAll(realSize, albumList); + mPhotoAdapter.notifyDataSetChanged(); + } + } + + @Override + public void finishActivity() { +// super.finishActivity(); + //判断图片选择器是否有改变 + isChange(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + isChange(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + private boolean isSignature = false; + + private void isChange() { + boolean isPhoto = photoChange(mPhotoDataList, mOldPhotoDataList); + boolean isName = mOldNickName.equals(mNickName.getText()); + boolean isBirthday = mOldBirthday.equals(mBirthDay.getText()); + boolean isCity = mOldCity.equals(mCity.getText()); + boolean avatarChange = TextUtils.isEmpty(avatarPath); + boolean isJob = TextUtils.equals(mOldJob, job); + if (isName && isBirthday && isCity && avatarChange && isJob && videoFile == null && !isSignature) { //没有改变 + if (!isPhoto) { + finish(); + } else { + saveDialog(false); + } + } else { //有改变 + saveDialog(isPhoto); + } + } + + private BaseMessageDialog saveDialog; + + /** + * 是否删除 + */ + public void saveDialog(final boolean isPhoto) { + saveDialog = new BaseMessageDialog.Builder(this).setMessage("是否更新?") + .setCancelable(true) + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + saveDialog.dismiss(); + if (isPhoto) { + editProfile(null); + } else { + updateData(); + } + + } + }).setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + saveDialog.dismiss(); + finish(); + + } + }).build(); + + saveDialog.show(); + } + + private OptionsPickerView pvOptions; + private List options1Items = new ArrayList<>(); + private ArrayList> options2Items = new ArrayList<>(); + + private void initOptionPicker() {//条件选择器初始化 + options1Items.clear(); + options2Items.clear(); + String s = SysSPUtils.getString(this, ConsUser.PROFILE); + Gson gson = new Gson(); + GlobalConfigBean.ProfileBean bean = gson.fromJson(s, GlobalConfigBean.ProfileBean.class); + for (int i = 0; i < bean.getJob_list().size(); i++) { + options1Items.add(bean.getJob_list().get(i).getName()); + options2Items.add(bean.getJob_list().get(i).getMenu()); + } + /** + * 注意 :如果是三级联动的数据(省市区等),请参照 JsonDataActivity 类里面的写法。 + */ + pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { + @Override + public void onOptionsSelect(int options1, int options2, int options3, View v) { + //返回的分别是三个级别的选中位置 + if (options2Items.size() > 0 && options2Items.size() >= options1 && options2Items.get(options1).size() >= options2) { + String occupation = options2Items.get(options1).get(options2); + mJob.setText(occupation); + job = options1Items.get(options1) + "-" + options2Items.get(options1).get(options2); + if (ConstUrl.LOGDEBUG) Log.i(TAG, "onOptionsSelect: ----------->" + job); + } + } + }) + .setTitleText("职业") + .setSelectOptions(0, 0)//默认选中项 + .setTitleBgColor(Color.WHITE) + .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 + .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 + .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { + @Override + public void onOptionsSelectChanged(int options1, int options2, int options3) { + String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; + //Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); + } + }) + .build(); + + if (options1Items.size() > 0 && options2Items.size() > 0) { + pvOptions.setPicker(options1Items, options2Items);//二级选择器 + } + } +} + + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationActivity.java new file mode 100644 index 0000000..40c0fd6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationActivity.java @@ -0,0 +1,344 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.Manifest; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.TextView; + +import com.fengliyan.base.base.AnyCallback; +import com.fengliyan.base.base.permission.AbsPermissionResultCallBack; +import com.fengliyan.base.base.permission.PermissionHelper; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.databinding.ActivityInvitationBinding; +import com.fengliyan.tianlesue.model.settings.InvitationBean; +import com.fengliyan.tianlesue.model.settings.InvitationShare; +import com.fengliyan.tianlesue.utils.SaveImageUtil; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.settings.dialog.PosterDialog; +import com.fengliyan.uikit.dialog.BottomShareDialog; +import com.fengliyan.uikit.toast.MaleToast; +import com.xinlingwu.share.ShareManager; + +import java.util.List; + +public class InvitationActivity extends BaseActivity implements + BottomShareDialog.OnButtonSelectListener { + private InvitationShare mShareData; + private BottomShareDialog mShareDialog; + private String qrImageUrl; + ActivityInvitationBinding binding; + private List posterList; + + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + binding = ActivityInvitationBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setDefaultTitle(); + setTitleName("邀请好友"); +// View lin = binding.holderView; +// ImageView bgImageView = findViewById(R.id.bgImageView); +// lin.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { +// @Override +// public void onGlobalLayout() { +// double height = bgImageView.getHeight() * 0.6; +// ViewGroup.LayoutParams param = lin.getLayoutParams(); +// param.height = (int) height; +// lin.setLayoutParams(param); +// lin.getViewTreeObserver().removeOnGlobalLayoutListener(this); +// } +// }); +// binding.container.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { +// @Override +// public void onGlobalLayout() { +// ViewGroup.LayoutParams containerParam = binding.container.getLayoutParams(); +// if (UserManager.getUserInfo().getGender() == 2) { +// containerParam.height = (int) (getResources().getDisplayMetrics().widthPixels * 0.84); +// } else { +// containerParam.height = (int) (getResources().getDisplayMetrics().widthPixels * 1.02); +// } +// binding.container.setLayoutParams(containerParam); +// binding.container.getViewTreeObserver().removeOnGlobalLayoutListener(this); +// } +// }); + + + mShareDialog = new BottomShareDialog(this, R.style.SelectiveDialog); + mShareDialog.setOnButtonSelectListener(this); + binding.ruleBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(InvitationActivity.this, BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.RULE_URL); + startActivity(intent); + } + }); + binding.invitedBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(InvitationActivity.this, InviteListActivity.class); + startActivity(intent); + } + }); + binding.shareLinkBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mShareDialog.show(); + } + }); + if (UserManager.getUserInfo().getGender() == 2) { + binding.tvManTip.setVisibility(View.GONE); + binding.menTip1.setVisibility(View.GONE); + } + binding.sharePosterBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showPoster(); + } + }); + binding.invitedDataBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(InvitationActivity.this, InvitationDataActivity.class); + startActivity(intent); + } + }); + initPosterLayout(); + getInvitationData(); + // initView(); +// getInvitationData(); + + binding.tvCopy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + clipUrlData(UserManager.getUserInfo().getUsercode()); + MaleToast.showMessage(InvitationActivity.this, "复制成功"); + } + }); + } + + void initPosterLayout() { + binding.posterContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + double ratio = 196.0 / 310.0; + ViewGroup.LayoutParams containerParam = binding.posterContainer.getLayoutParams(); + containerParam.height = (int) (getResources().getDisplayMetrics().widthPixels / ratio); + binding.posterContainer.setLayoutParams(containerParam); + binding.posterContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + }); + binding.qrImageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + ViewGroup.LayoutParams containerParam = binding.qrImageView.getLayoutParams(); + containerParam.height = (int) (getResources().getDisplayMetrics().widthPixels / 4); + containerParam.height = (int) (getResources().getDisplayMetrics().widthPixels / 4); + binding.qrImageView.setLayoutParams(containerParam); + binding.qrImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + }); + } + + void showPoster() { + if (posterList == null) { + MaleToast.showMessage(this, "海报列表为空"); + return; + } + + PosterDialog dialog = new PosterDialog(this, new AnyCallback() { + @Override + public void callback(PosterDialog.PosterBean bean) { + binding.bannerImage.setImageURI(bean.getPoster()); + binding.qrImageView.setImageURI(bean.getQr()); + + PermissionHelper.request(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, + new AbsPermissionResultCallBack() { + @Override + public void onPermissionGranted() { + new SaveImageUtil(binding.posterContainer, InvitationActivity.this).start(); + } + + @Override + public void onPermissionDenied(String... permissions) { + super.onPermissionDenied(permissions); + MaleToast.showMessage(InvitationActivity.this, "没有授予存储权限"); + } + }); + } + }, posterList, qrImageUrl); + dialog.show(); + } + + + private void getInvitationData() { + binding.tvMyInvitationCode.setText("我的邀请码" + UserManager.getUserInfo().getUsercode()); + SettingManager.getInvitationData(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, InvitationBean result, String message) { +// mPhoto.setImageURI(ConstUrl.IMAGE_URL + result.getTop().getAvatar()); +// mName.setText(result.getTop().getNickname() + "邀 请赚取"); + +// mFirst.setText(result.getReward().getFirst()); +// mSecond.setText(result.getReward().getSecond()); +// mThird.setText(result.getReward().getThird()); +// mFourth.setText(result.getReward().getFour()); + binding.firstLabel.setText(result.getReward().getFirst()); + binding.secondLabel.setText(result.getReward().getSecond()); + binding.thirdLabel.setText(result.getReward().getThird()); + binding.fourLabel.setText(result.getReward().getFour() + ""); + posterList = result.getAvatar_list(); + binding.totalPeopleLabel.setText(result.getTotal().getTotal_invite() + ""); + binding.totalRewardLabel.setText(result.getTotal().getRecharge_count() + ""); + binding.totalTiChengLabel.setText(result.getTotal().getAuth_count() + ""); + mShareData = result.getShare(); + qrImageUrl = ConstUrl.IMAGE_URL + result.getQrcode(); + if (result.getShow_invite_list() == 1) { + binding.invitedDataBtn.setVisibility(View.VISIBLE); + } else { + binding.invitedDataBtn.setVisibility(View.GONE); + } + + if (result.getReward_desc() != null && result.getReward_desc().size() > 0) { + addLabel(result.getReward_desc()); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + public void addLabel(List list) { + binding.linLabel.removeAllViews(); + for (int i = 0; i < list.size(); i++) { + View view = LayoutInflater.from(this).inflate(R.layout.item_invitation_view, null); + TextView tv_invite_title = view.findViewById(R.id.tv_invite_title); + TextView tv_invite_content = view.findViewById(R.id.tv_invite_content); + tv_invite_title.setText(list.get(i).getTitle()); + String s = list.get(i).getContent(); + StrU.setSpanTextColor(s, s.indexOf(list.get(i).getFont_colour()), (s.indexOf(list.get(i).getFont_colour()) + list.get(i).getFont_colour().length()), tv_invite_content, R.color.invitation_text_color, this); + binding.linLabel.addView(view); + } + } + + public void onDestroy() { + super.onDestroy(); + if (null != mShareDialog && mShareDialog.isShowing()) { + mShareDialog.dismiss(); + } + } + + + @Override + public void onClicked(View view, int index) { + mShareDialog.dismiss(); + if (null != mShareData) { + switch (index) { + case 0: + Intent intent = new Intent(this, CopyBoardActivity.class); + intent.putExtra("imageUrl", qrImageUrl); + startActivity(intent); + break; + case 1: + if (mShareData != null) { + String wxShareConfig = mShareData.getWxShareConfig(); + if (wxShareConfig.equals("1")) { + clipUrlData(mShareData.getUrl()); + MaleToast.showMessage(InvitationActivity.this, "复制链接成功,快去微信粘贴给好友"); + } else { + ShareManager.getInstance().shareToPlatform(1, + mShareData.getUrl(), + mShareData.getImage_url(), + mShareData.getTitle(), + mShareData.getContent(), this); + } + } + + break; + + case 2: + if (mShareData != null) { + String wxShareConfig = mShareData.getWxShareConfig(); + if (wxShareConfig.equals("1")) { + clipUrlData(mShareData.getUrl()); + MaleToast.showMessage(InvitationActivity.this, "复制链接成功,快去朋友圈粘贴给好友"); + } else { + ShareManager.getInstance().shareToPlatform(2, + mShareData.getUrl(), + mShareData.getImage_url(), + mShareData.getTitle(), + mShareData.getContent(), this); + } + } + + break; + + case 3: + ShareManager.getInstance().shareToPlatform(3, + mShareData.getUrl(), + mShareData.getImage_url(), + mShareData.getTitle(), + mShareData.getContent(), this); + break; + case 4: + ShareManager.getInstance().shareToPlatform(4, + mShareData.getUrl(), + mShareData.getImage_url(), + mShareData.getTitle(), + mShareData.getContent(), this); + break; + case 5: + ShareManager.getInstance().shareToPlatform(5, + mShareData.getUrl(), + mShareData.getImage_url(), + mShareData.getTitle(), + mShareData.getContent(), this); + break; + case 6: + ClipboardManager cm = (ClipboardManager) + getSystemService(Context.CLIPBOARD_SERVICE); + + cm.setPrimaryClip(ClipData.newPlainText(null, mShareData.getUrl_wechat())); + MaleToast.showMessage(this, "链接复制成功,快去粘贴吧!"); + break; + } + } + + } + + /** + * 将分享链接地址复制到剪切板 + */ + public void clipUrlData(String content) { + //获取剪贴板管理器: + ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + // 创建普通字符型ClipData + ClipData mClipData = ClipData.newPlainText("Label", content); + // 将ClipData内容放到系统剪贴板里。 + cm.setPrimaryClip(mClipData); + + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationDataActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationDataActivity.java new file mode 100644 index 0000000..5436c2d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationDataActivity.java @@ -0,0 +1,246 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.eventBus.InviteTypeEvent; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.settings.dialog.InviteSelectTypeDialog; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import de.greenrobot.event.EventBus; + +public class InvitationDataActivity extends BaseActivity implements View.OnClickListener, InviteSelectTypeDialog.OnSelectListener { + private TextView mTitleText1; + private TextView mTitleText2; + private TextView mTitleText3; + private TextView mTitleText4; + private TextView mTitleText5; + private TextView mTitleText6; + private View mTitleBottom1; + private View mTitleBottom2; + private View mTitleBottom3; + private View mTitleBottom4; + private View mTitleBottom5; + private View mTitleBottom6; + private View mTitleTag1; + private View mTitleTag2; + private View mTitleTag3; + private View mTitleTag4; + private View mTitleTag5; + private View mTitleTag6; + private ImageView iv_back; + private ImageView iv_invite_select; + private ViewPager mInvitationViewPager; + private List mRankFragments = new ArrayList<>(); + private MainViewPagerAdapter mViewPagerAdapter; + private InviteSelectTypeDialog inviteSelectTypeDialog; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_invitation_data); + hideTitleBar(); + initView(); + } + + private void initView() { + mTitleTag1 = findViewById(R.id.dynamic_title_view_1); + mTitleTag2 = findViewById(R.id.dynamic_title_view_2); + mTitleTag3 = findViewById(R.id.dynamic_title_view_3); + mTitleTag4 = findViewById(R.id.dynamic_title_view_4); + mTitleTag5 = findViewById(R.id.dynamic_title_view_5); + mTitleTag6 = findViewById(R.id.dynamic_title_view_6); + mTitleText1 = findViewById(R.id.dynamic_title_name_1); + mTitleText2 = findViewById(R.id.dynamic_title_name_2); + mTitleText3 = findViewById(R.id.dynamic_title_name_3); + mTitleText4 = findViewById(R.id.dynamic_title_name_4); + mTitleText5 = findViewById(R.id.dynamic_title_name_5); + mTitleText6 = findViewById(R.id.dynamic_title_name_6); + mTitleBottom1 = findViewById(R.id.dynamic_title_bottom_line_1); + mTitleBottom2 = findViewById(R.id.dynamic_title_bottom_line_2); + mTitleBottom3 = findViewById(R.id.dynamic_title_bottom_line_3); + mTitleBottom4 = findViewById(R.id.dynamic_title_bottom_line_4); + mTitleBottom5 = findViewById(R.id.dynamic_title_bottom_line_5); + mTitleBottom6 = findViewById(R.id.dynamic_title_bottom_line_6); + iv_back = findViewById(R.id.iv_back); + iv_invite_select = findViewById(R.id.iv_invite_select); + mTitleTag1.setOnClickListener(this); + mTitleTag2.setOnClickListener(this); + mTitleTag3.setOnClickListener(this); + mTitleTag4.setOnClickListener(this); + mTitleTag5.setOnClickListener(this); + mTitleTag6.setOnClickListener(this); + iv_back.setOnClickListener(this); + iv_invite_select.setOnClickListener(this); + mInvitationViewPager = findViewById(R.id.invitation_view_pager); + mInvitationViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + + } + + @Override + public void onPageSelected(int position) { + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPagerAdapter = new MainViewPagerAdapter(getSupportFragmentManager(), mRankFragments); + + String[] types = {"1", "2", "3", "4", "5", "6"}; + Arrays.asList(types).forEach(type -> mRankFragments.add(createFragment(type))); + + mInvitationViewPager.setAdapter(mViewPagerAdapter); + mInvitationViewPager.setCurrentItem(0, false); + viewPagerChange(0); + + } + + private InvitationDataFragment createFragment(String list_type) { + InvitationDataFragment fragment = new InvitationDataFragment(); + Bundle bundle = new Bundle(); + bundle.putString("list_type", list_type); + fragment.setArguments(bundle); + return fragment; + } + + private void viewPagerChange(int index) { + switch (index) { + case 0: + mTitleText1.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + mTitleBottom1.setVisibility(View.VISIBLE); + mTitleText2.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom2.setVisibility(View.INVISIBLE); + mTitleText3.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom3.setVisibility(View.INVISIBLE); + mTitleText4.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom4.setVisibility(View.INVISIBLE); + mTitleText5.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom5.setVisibility(View.INVISIBLE); + mTitleText6.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom6.setVisibility(View.INVISIBLE); + break; + case 1: + mTitleText2.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + mTitleBottom2.setVisibility(View.VISIBLE); + mTitleText1.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom1.setVisibility(View.INVISIBLE); + mTitleText3.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom3.setVisibility(View.INVISIBLE); + mTitleText4.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom4.setVisibility(View.INVISIBLE); + mTitleText5.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom5.setVisibility(View.INVISIBLE); + mTitleText6.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom6.setVisibility(View.INVISIBLE); + break; + case 2: + mTitleText3.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + mTitleBottom3.setVisibility(View.VISIBLE); + mTitleText4.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom4.setVisibility(View.INVISIBLE); + mTitleText2.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom2.setVisibility(View.INVISIBLE); + mTitleText1.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom1.setVisibility(View.INVISIBLE); + mTitleText5.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom5.setVisibility(View.INVISIBLE); + mTitleText6.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom6.setVisibility(View.INVISIBLE); + break; + case 3: + mTitleText4.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + mTitleBottom4.setVisibility(View.VISIBLE); + mTitleText2.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom2.setVisibility(View.INVISIBLE); + mTitleText1.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom1.setVisibility(View.INVISIBLE); + mTitleText3.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom3.setVisibility(View.INVISIBLE); + mTitleText5.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom5.setVisibility(View.INVISIBLE); + mTitleText6.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom6.setVisibility(View.INVISIBLE); + break; + case 4: + mTitleText5.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + mTitleBottom5.setVisibility(View.VISIBLE); + mTitleText1.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom1.setVisibility(View.INVISIBLE); + mTitleText2.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom2.setVisibility(View.INVISIBLE); + mTitleText3.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom3.setVisibility(View.INVISIBLE); + mTitleText4.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom4.setVisibility(View.INVISIBLE); + mTitleText6.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom6.setVisibility(View.INVISIBLE); + break; + case 5: + mTitleText6.setTextColor(ContextCompat.getColor(this, R.color.one_text)); + mTitleBottom6.setVisibility(View.VISIBLE); + mTitleText1.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom1.setVisibility(View.INVISIBLE); + mTitleText2.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom2.setVisibility(View.INVISIBLE); + mTitleText3.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom3.setVisibility(View.INVISIBLE); + mTitleText4.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom4.setVisibility(View.INVISIBLE); + mTitleText5.setTextColor(ContextCompat.getColor(this, R.color.three_text)); + mTitleBottom5.setVisibility(View.INVISIBLE); + break; + } + } + + @Override + public void onClick(View view) { + if (view == mTitleTag1) { + mInvitationViewPager.setCurrentItem(0); + } else if (view == mTitleTag2) { + mInvitationViewPager.setCurrentItem(1); + } else if (view == mTitleTag3) { + mInvitationViewPager.setCurrentItem(2); + } else if (view == mTitleTag4) { + mInvitationViewPager.setCurrentItem(3); + } else if (view == mTitleTag5) { + mInvitationViewPager.setCurrentItem(4); + } else if (view == mTitleTag6) { + mInvitationViewPager.setCurrentItem(5); + } else if (view == iv_back) { + finish(); + } else if (view == iv_invite_select) { + if (inviteSelectTypeDialog == null) { + inviteSelectTypeDialog = new InviteSelectTypeDialog(this); + inviteSelectTypeDialog.setSelectListener(this); + } + inviteSelectTypeDialog.show(); + } + } + + public String type = "1"; + + @Override + public void selectType(String type) { + this.type = type; + EventBus.getDefault().post(new InviteTypeEvent(type)); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationDataFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationDataFragment.java new file mode 100644 index 0000000..f3a8f34 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InvitationDataFragment.java @@ -0,0 +1,276 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.eventBus.InviteTypeEvent; +import com.fengliyan.tianlesue.controller.settings.adapter.InviteRechargeAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.InviteDataListBean; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener; +import com.scwang.smart.refresh.layout.listener.OnRefreshListener; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/4/26. + */ + +public class InvitationDataFragment extends Fragment implements View.OnClickListener { + private SmartRefreshLayout channel_refresh; + private EditText et_invitation_code; + private TextView tv_search; + private ConstraintLayout cl_all_income; + private TextView tv_all_income; + private TextView tv_gold_amount1, tv_vip_amount1, tv_divide_amount1, tv_count1; + private TextView tv_gold_amount2, tv_vip_amount2, tv_divide_amount2, tv_count2; + private LinearLayout lin_main_title; + private TextView tv_0, tv_1; + private RecyclerView rv_invite_list; + private TextView tv_no_data; + + private InviteRechargeAdapter mAdapter; + private List mRankDataList = new ArrayList<>(); + private int mPage = 1; + private String list_type = "1"; + private String invite_type = "1"; + private String user_code = ""; + private String type = "1"; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_invitation_data, container, false); + if (getArguments() != null) { + list_type = getArguments().getString("list_type"); + } + if (getActivity() != null) { + type = ((InvitationDataActivity) getActivity()).type; + } + EventBus.getDefault().register(this); + initView(v); + mPage = 1; + getInvitationRechargeList(mPage); + return v; + } + + private void initView(View v) { + channel_refresh = v.findViewById(R.id.channel_refresh); + et_invitation_code = v.findViewById(R.id.et_invitation_code); + tv_search = v.findViewById(R.id.tv_search); + cl_all_income = v.findViewById(R.id.cl_all_income); + tv_all_income = v.findViewById(R.id.tv_all_income); + tv_gold_amount1 = v.findViewById(R.id.tv_gold_amount1); + tv_vip_amount1 = v.findViewById(R.id.tv_vip_amount1); + tv_divide_amount1 = v.findViewById(R.id.tv_divide_amount1); + tv_count1 = v.findViewById(R.id.tv_count1); + tv_gold_amount2 = v.findViewById(R.id.tv_gold_amount2); + tv_vip_amount2 = v.findViewById(R.id.tv_vip_amount2); + tv_divide_amount2 = v.findViewById(R.id.tv_divide_amount2); + tv_count2 = v.findViewById(R.id.tv_count2); + lin_main_title = v.findViewById(R.id.lin_main_title); + tv_0 = v.findViewById(R.id.tv_0); + tv_1 = v.findViewById(R.id.tv_1); + rv_invite_list = v.findViewById(R.id.rv_invite_list); + tv_no_data = v.findViewById(R.id.tv_no_data); + + mAdapter = new InviteRechargeAdapter(getActivity()); + LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); + rv_invite_list.setLayoutManager(layoutManager); + mAdapter.setRechargeList(mRankDataList); + rv_invite_list.setAdapter(mAdapter); + + tv_search.setOnClickListener(this); + tv_0.setOnClickListener(this); + tv_1.setOnClickListener(this); + + channel_refresh.setOnRefreshListener(new OnRefreshListener() { + @Override + public void onRefresh(@NonNull RefreshLayout refreshLayout) { + mPage = 1; + getInvitationRechargeList(mPage); + } + }); + channel_refresh.setEnableAutoLoadMore(true); + channel_refresh.setEnableFooterTranslationContent(false); + channel_refresh.setOnLoadMoreListener(new OnLoadMoreListener() { + @Override + public void onLoadMore(@NonNull RefreshLayout refreshLayout) { + mPage++; + getInvitationRechargeList(mPage); + } + }); + } + + public void getInvitationRechargeList(final int page) { + SettingManager.getInvitationRechargeList((BaseActivity) getActivity(), list_type, invite_type, page + "", user_code, type, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, InviteDataListBean result, String message) { + if (result != null) { + InviteDataListBean.IncomeListBean income = result.getIncome(); + if (income != null && !StrU.isEmpty(income.getAll_income())) { + if (!StrU.isEmpty(user_code)) { + cl_all_income.setVisibility(View.GONE); + } else { + cl_all_income.setVisibility(View.VISIBLE); + } + String all_income = "累计收入:" + income.getAll_income() + "元"; + StrU.setSpanTextSizeStyle(all_income, 5, all_income.length(), tv_all_income, 22); + InviteDataListBean.IncomeBean direct = income.getDirect(); + if (direct != null) { + tv_count1.setText("直接邀请用户" + direct.getUser_count() + "人"); + switch (type) { + case "1": + tv_gold_amount1.setText("用户充值:" + direct.getGold_amount() + "元"); + tv_vip_amount1.setVisibility(View.VISIBLE); + tv_vip_amount1.setText("充值会员:" + direct.getVip_amount() + "元"); + tv_divide_amount1.setText("充值分成:" + direct.getDivide_amount() + "元"); + break; + case "2": + tv_gold_amount1.setText("通话收益:" + direct.getRevenue_amount() + "元"); + tv_vip_amount1.setVisibility(View.GONE); + tv_divide_amount1.setText("收益分成:" + direct.getDivide_amount() + "元"); + break; + case "3": + tv_gold_amount1.setText("礼物收益:" + direct.getRevenue_amount() + "元"); + tv_vip_amount1.setVisibility(View.GONE); + tv_divide_amount1.setText("收益分成:" + direct.getDivide_amount() + "元"); + break; + } + } + InviteDataListBean.IncomeBean indirect = income.getIndirect(); + if (indirect != null) { + tv_count2.setText("间接邀请用户" + indirect.getUser_count() + "人"); + switch (type) { + case "1": + tv_gold_amount2.setText("用户充值:" + indirect.getGold_amount() + "元"); + tv_vip_amount2.setText("充值会员:" + indirect.getVip_amount() + "元"); + tv_divide_amount2.setText("充值分成:" + indirect.getDivide_amount() + "元"); + tv_vip_amount2.setVisibility(View.VISIBLE); + break; + case "2": + tv_gold_amount2.setText("通话收益:" + indirect.getRevenue_amount() + "元"); + tv_vip_amount2.setVisibility(View.GONE); + tv_divide_amount2.setText("收益分成:" + indirect.getDivide_amount() + "元"); + break; + case "3": + tv_gold_amount2.setText("礼物收益:" + indirect.getRevenue_amount() + "元"); + tv_vip_amount2.setVisibility(View.GONE); + tv_divide_amount2.setText("收益分成:" + indirect.getDivide_amount() + "元"); + break; + } + } + } else { + cl_all_income.setVisibility(View.GONE); + } + + if (mPage == 1) { + channel_refresh.finishRefresh(); + channel_refresh.setEnableLoadMore(true); + mRankDataList.clear(); + } else { + channel_refresh.finishLoadMore(); + if (result.getList() != null && result.getList().size() > 0) { + channel_refresh.setEnableLoadMore(true); + } else { + channel_refresh.setEnableLoadMore(false); + } + } + mRankDataList.addAll(result.getList()); + mAdapter.notifyDataSetChanged(); + + if (mRankDataList != null && mRankDataList.size() > 0) { + rv_invite_list.setVisibility(View.VISIBLE); + tv_no_data.setVisibility(View.GONE); + } else { + rv_invite_list.setVisibility(View.GONE); + tv_no_data.setVisibility(View.VISIBLE); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + if (mPage == 1) { + channel_refresh.finishRefresh(false); + } else { + channel_refresh.finishLoadMore(false); + } + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + if (mPage == 1) { + channel_refresh.finishRefresh(false); + } else { + channel_refresh.finishLoadMore(false); + } + } + }); + } + + public void onEventMainThread(InviteTypeEvent event) { + type = event.getType(); + mPage = 1; + getInvitationRechargeList(mPage); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.tv_search: + user_code = et_invitation_code.getText().toString().trim(); + mPage = 1; + getInvitationRechargeList(mPage); + break; + case R.id.tv_0: + tv_0.setBackgroundResource(R.drawable.shape_invitation_select_bg); + tv_1.setBackgroundResource(0); + tv_0.setTextColor(ContextCompat.getColor(getActivity(), R.color.white)); + tv_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.two_text)); + invite_type = "1"; + mPage = 1; + mAdapter.setmItemType(1); + getInvitationRechargeList(mPage); + break; + case R.id.tv_1: + tv_1.setBackgroundResource(R.drawable.shape_invitation_select_bg); + tv_0.setBackgroundResource(0); + tv_1.setTextColor(ContextCompat.getColor(getActivity(), R.color.white)); + tv_0.setTextColor(ContextCompat.getColor(getActivity(), R.color.two_text)); + invite_type = "2"; + mPage = 1; + mAdapter.setmItemType(2); + getInvitationRechargeList(mPage); + break; + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/InviteListActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InviteListActivity.java new file mode 100644 index 0000000..4bf2260 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/InviteListActivity.java @@ -0,0 +1,134 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.InviteAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.SocialBean; +import com.fengliyan.tianlesue.model.settings.SocialListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2018/11/23. + * 用户邀请列表 + */ + +public class InviteListActivity extends BaseActivity { + + private EditText et_invitation_code; + private TextView tv_search; + private TextView tv_no_data; + private LoadMoreListView mListView; + private InviteAdapter mAdapter; + private int mPage = 1; + private boolean mPageLoad; + private List mBeanList = new ArrayList<>(); + private String mKeyWord; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_invite_list); + setDefaultTitle(); + setTitleName("邀请列表"); + + initView(); + getData(mPage, mKeyWord); + } + + /** + * 请求数据 + * + * @param page + */ + private void getData(int page, String keyWord) { + + SettingManager.getInviteList(this, page, keyWord, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SocialListBean result, String message) { + if (page == 1) { + mBeanList.clear(); + } + mBeanList.addAll(result.getList()); + mAdapter.notifyDataSetChanged(); + mPage++; + if (mBeanList.size() > 0) { + mListView.setVisibility(View.VISIBLE); + tv_no_data.setVisibility(View.GONE); + } else { + mListView.setVisibility(View.GONE); + tv_no_data.setVisibility(View.VISIBLE); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + private void initView() { + et_invitation_code = findViewById(R.id.et_invitation_code); + tv_search = findViewById(R.id.tv_search); + tv_no_data = findViewById(R.id.tv_no_data); + mListView = findViewById(R.id.invite_list); + + mAdapter = new InviteAdapter(this); + mAdapter.setUserList(mBeanList); + mListView.setAdapter(mAdapter); + + mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + Intent intent = new Intent(InviteListActivity.this, MainPageActivity.class); + intent.putExtra("userId", mBeanList.get(i).getUserid()); + startActivity(intent); + } + }); + + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (mBeanList.size() != 0 && mBeanList.size() % 10 == 0 && !mPageLoad + && mListView.getLastVisiblePosition() > mBeanList.size() - 2) { + getData(mPage, mKeyWord); + mPageLoad = true; + } else if (mListView.getLastVisiblePosition() <= mBeanList.size() - 2) { + mPageLoad = false; + } + } + }); + + tv_search.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mKeyWord = et_invitation_code.getText().toString(); + getData(1, mKeyWord); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/LongImageActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/LongImageActivity.java new file mode 100644 index 0000000..4a04da0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/LongImageActivity.java @@ -0,0 +1,131 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapRegionDecoder; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Bundle; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class LongImageActivity extends BaseActivity { + + private Rect mRect; + private ImageView mImageView1; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.long_image_activity); + setTitleName("来电提醒"); + + mImageView1 = findViewById(R.id.iv_big); + + Intent intent = getIntent(); + String url = intent.getStringExtra("url"); + +// String url = "http://bmob-cdn-15177.b0.upaiyun.com/2018/08/23/8fa7f1c2404bafbd808bde10ff072ceb.jpg"; + mRect = new Rect(); + + Glide.with(this).asBitmap().load(url).into(new SimpleTarget() { + @Override + public void onResourceReady(Bitmap resource, Transition transition) { + setBitmapToImg(resource); + } + }); + } + + private void setBitmapToImg(Bitmap resource) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + resource.compress(Bitmap.CompressFormat.PNG, 100, baos); + + InputStream isBm = new ByteArrayInputStream(baos.toByteArray()); + + //BitmapRegionDecoder newInstance(InputStream is, boolean isShareable) + //用于创建BitmapRegionDecoder,isBm表示输入流,只有jpeg和png图片才支持这种方式, + // isShareable如果为true,那BitmapRegionDecoder会对输入流保持一个表面的引用, + // 如果为false,那么它将会创建一个输入流的复制,并且一直使用它。即使为true,程序也有可能会创建一个输入流的深度复制。 + // 如果图片是逐步解码的,那么为true会降低图片的解码速度。如果路径下的图片不是支持的格式,那就会抛出异常 + BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(isBm, true); + + + final int imgWidth = decoder.getWidth(); + final int imgHeight = decoder.getHeight(); + + BitmapFactory.Options opts = new BitmapFactory.Options(); + + //计算图片要被切分成几个整块, + // 如果sum=0 说明图片的长度不足3000px,不进行切分 直接添加 + // 如果sum>0 先添加整图,再添加多余的部分,否则多余的部分不足3000时底部会有空白 + int sum = imgHeight/3000; + + int redundant = imgHeight%3000; + + List bitmapList = new ArrayList<>(); + + //说明图片的长度 < 3000 + if (sum == 0){ + //直接加载 + bitmapList.add(resource); + }else { + //说明需要切分图片 + for (int i = 0; i < sum; i++) { + //需要注意:mRect.set(left, top, right, bottom)的第四个参数, + //也就是图片的高不能大于这里的4096 + + mRect.set(0, i*3000, imgWidth, (i+1) * 3000); + Bitmap bm = decoder.decodeRegion(mRect, opts); + bitmapList.add(bm); + } + + //将多余的不足3000的部分作为尾部拼接 + if (redundant > 0){ + mRect.set(0, sum*3000, imgWidth, imgHeight); + Bitmap bm = decoder.decodeRegion(mRect, opts); + bitmapList.add(bm); + } + + } + + Bitmap bigbitmap = Bitmap.createBitmap(imgWidth, imgHeight, Bitmap.Config.ARGB_8888); + Canvas bigcanvas = new Canvas(bigbitmap); + + Paint paint = new Paint(); + int iHeight = 0; + + //将之前的bitmap取出来拼接成一个bitmap + for (int i = 0; i < bitmapList.size(); i++) { + Bitmap bmp = bitmapList.get(i); + bigcanvas.drawBitmap(bmp, 0, iHeight, paint); + iHeight += bmp.getHeight(); + + bmp.recycle(); + bmp = null; + } + + mImageView1.setImageBitmap(bigbitmap); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/MemberActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MemberActivity.java new file mode 100644 index 0000000..8a5dcc3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MemberActivity.java @@ -0,0 +1,176 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Created by zhangbin on 2019/5/14. + * 会员 + */ + +public class MemberActivity extends BaseActivity implements View.OnClickListener, SuperMemberFragment.OnScrollChange, GeneralMemberFragment.OnScrollChange { + + private TextView tv_member_title_bg; + private ImageView iv_member_back; + private TextView tv_member_title; + private LinearLayout title_view_1; + private TextView title_name_1; + private View title_bottom_line_1; + private LinearLayout title_view_2; + private TextView title_name_2; + private View title_bottom_line_2; + + private ViewPager mMainViewPager; + + private GeneralMemberFragment mGeneralMemberFragment; + private SuperMemberFragment mSuperMemberFragment; + + private List mChannelFragments = new ArrayList<>(); + private MainViewPagerAdapter mViewPagerAdapter; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_member); + hideTitleBar(); + initView(); + } + + private void initView() { + tv_member_title_bg = findViewById(R.id.tv_member_title_bg); + tv_member_title = findViewById(R.id.tv_member_title); + iv_member_back = findViewById(R.id.iv_member_back); + title_view_1 = findViewById(R.id.title_view_1); + title_name_1 = findViewById(R.id.title_name_1); + title_bottom_line_1 = findViewById(R.id.title_bottom_line_1); + title_view_2 = findViewById(R.id.title_view_2); + title_name_2 = findViewById(R.id.title_name_2); + title_bottom_line_2 = findViewById(R.id.title_bottom_line_2); + mMainViewPager = findViewById(R.id.view_pager); + + title_view_1.setOnClickListener(this); + title_view_2.setOnClickListener(this); + iv_member_back.setOnClickListener(this); + + mGeneralMemberFragment = new GeneralMemberFragment(); + mGeneralMemberFragment.setOnScrollChange(this); + mSuperMemberFragment = new SuperMemberFragment(); + mSuperMemberFragment.setOnScrollChange(this); + + mChannelFragments.add(mGeneralMemberFragment); +// mChannelFragments.add(mSuperMemberFragment); + + mViewPagerAdapter = new MainViewPagerAdapter(getSupportFragmentManager(), + mChannelFragments); + + mMainViewPager.setAdapter(mViewPagerAdapter); + + mMainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + viewPagerChange(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + viewPagerChange(0); + mViewPagerAdapter.notifyDataSetChanged(); + int index = getIntent().getIntExtra("index", 0); +// mMainViewPager.setCurrentItem(index); + } + + private void viewPagerChange(int index) { + switch (index) { + case 0: + title_name_1.setTextColor(Color.parseColor("#643406")); + title_name_1.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗 + title_bottom_line_1.setVisibility(View.VISIBLE); + + title_name_2.setTextColor(Color.parseColor("#9C8D76")); + title_name_2.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + title_bottom_line_2.setVisibility(View.INVISIBLE); + +// tv_member_title.setTextColor(Color.BLACK); +// iv_member_back.setImageResource(R.drawable.ic_return); + mGeneralMemberFragment.scrollTop(); + tv_member_title_bg.setAlpha(0); + break; + case 1: + title_name_2.setTextColor(Color.parseColor("#FFE5C2")); + title_name_2.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + title_bottom_line_2.setVisibility(View.VISIBLE); + + title_name_1.setTextColor(Color.parseColor("#9E94B0")); + title_name_1.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));//加粗 + title_bottom_line_1.setVisibility(View.INVISIBLE); + + tv_member_title.setTextColor(Color.parseColor("#F3E9F9")); + iv_member_back.setImageResource(R.drawable.ic_return_white); + mSuperMemberFragment.scrollTop(); + tv_member_title_bg.setAlpha(0); + break; + + } + } + + @Override + public void onClick(View view) { + if (view == iv_member_back) { + finish(); + } else if (view == title_view_1) { + mMainViewPager.setCurrentItem(0); + } else if (view == title_view_2) { + mMainViewPager.setCurrentItem(1); + } + } + + /** + * 跳到超级会员页面 + */ + public void toSuperMemberFragment() { + if (null != mMainViewPager) { + mMainViewPager.setCurrentItem(1); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void scrollChange(int scrollY) { +// int maxDistance = tv_member_title_bg.getMeasuredHeight(); +// float progress = (float) scrollY / maxDistance; +// if (progress < 0) { +// progress = 0; +// } else if (progress >= 0.5f) { +// progress = 0.5f; +// } +// tv_member_title_bg.setAlpha(progress); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/MissionActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MissionActivity.java new file mode 100644 index 0000000..9256b1d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MissionActivity.java @@ -0,0 +1,241 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Shader; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.blankj.utilcode.util.ConvertUtils; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.eventBus.PayEvent; +import com.fengliyan.tianlesue.controller.settings.adapter.SignInListAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.settings.SignDataListBean; +import com.fengliyan.tianlesue.utils.GridDecoration; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.SignInRewardsDialog; +import com.fengliyan.tianlesue.view.main.MainActivity; +import com.fengliyan.uikit.toast.MaleToast; + +import de.greenrobot.event.EventBus; + +public class MissionActivity extends BaseActivity implements View.OnClickListener { + private ImageView iv_sign_finish; + private ConstraintLayout iv_mission_bg; + private TextView tv_sign_day; + private RecyclerView recyclerView; + private TextView tv_sign; + private LinearLayout lin_mission; + private TextView tv_mission_text; + private TextView tv_go_dy; + private TextView tv_go_invite; + private ConstraintLayout cl_mission_invite; + private SignInListAdapter mAdapter; + private int status; + private String coin; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_mission); + hideTitleBar(); + initView(); + iv_mission_bg.setVisibility(View.GONE); + tv_mission_text.setVisibility(View.GONE); + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) lin_mission.getLayoutParams(); + lp.topMargin = ConvertUtils.dp2px(120); + lin_mission.setLayoutParams(lp); + EventBus.getDefault().register(this); + if (!UserManager.getUserInfo().isWomen()) { + signData(); + } + } + + private void initView() { + iv_sign_finish = findViewById(R.id.iv_sign_finish); + iv_mission_bg = findViewById(R.id.iv_mission_bg); + recyclerView = findViewById(R.id.recyclerView); + tv_sign_day = findViewById(R.id.tv_sign_day); + tv_sign = findViewById(R.id.tv_sign); + lin_mission = findViewById(R.id.lin_mission); + tv_mission_text = findViewById(R.id.tv_mission_text); + tv_go_dy = findViewById(R.id.tv_go_dy); + tv_go_invite = findViewById(R.id.tv_go_invite); + cl_mission_invite = findViewById(R.id.cl_mission_invite); + + if (NoClearSPUtils.getInt(this, Constans.MARKET_STATUS) == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { + cl_mission_invite.setVisibility(View.GONE); + } else { + if (!UserManager.getUserInfo().isWomen()) { + if (UserManager.getUserInfo().getReal_name_status() == 1) { + cl_mission_invite.setVisibility(View.VISIBLE); + } else { + cl_mission_invite.setVisibility(View.GONE); + } + } else { + if (UserManager.getUserInfo().getIs_anchor() == 1 && UserManager.getUserInfo().getIs_face_status() == 1) { + cl_mission_invite.setVisibility(View.VISIBLE); + } else { + cl_mission_invite.setVisibility(View.GONE); + } + } + } + + iv_sign_finish.setOnClickListener(this); + tv_sign.setOnClickListener(this); + tv_go_dy.setOnClickListener(this); + tv_go_invite.setOnClickListener(this); + + mAdapter = new SignInListAdapter(this); + GridLayoutManager layoutManager = new GridLayoutManager(this, 4); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(mAdapter); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (position == 6) { + return 2; + } else { + return 1; + } + } + }); + recyclerView.addItemDecoration(new GridDecoration().setSizeDp(12f, 10f)); + int[] color = new int[]{Color.parseColor("#4A46FF"), Color.parseColor("#CD32BE")}; + Shader textShader = new LinearGradient(0, 0, tv_sign_day.getTextSize(), 0, color, null, Shader.TileMode.CLAMP); + tv_sign_day.getPaint().setShader(textShader); + } + + public void signData() { + SettingManager.signData(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SignDataListBean result, String message) { + if (result != null && !StrU.isEmpty(result.getSign_day()) && result.getSign_info() != null && result.getSign_info().size() > 0) { + iv_mission_bg.setVisibility(View.VISIBLE); + tv_mission_text.setVisibility(View.VISIBLE); + tv_sign_day.setText("已连续签到" + result.getSign_day() + "天"); + //按钮状态0去充值1立即签到2已签到 + status = result.getButton_status(); + switch (status) { + case 0: + tv_sign.setText("去充值"); + break; + case 1: + tv_sign.setText("立即签到"); + break; + case 2: + tv_sign.setText("已签到"); + break; + } + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) lin_mission.getLayoutParams(); + lp.topMargin = ConvertUtils.dp2px(16); + lin_mission.setLayoutParams(lp); + if (result.getSign_info() != null && result.getSign_info().size() > 0) { + mAdapter.setList(result.getSign_info()); + for (int i = 0; i < result.getSign_info().size(); i++) { + if (result.getSign_info().get(i).getIs_selected() == 1) { + coin = result.getSign_info().get(i).getGold_coin(); + } + } + } + } else { + iv_mission_bg.setVisibility(View.GONE); + tv_mission_text.setVisibility(View.GONE); + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) lin_mission.getLayoutParams(); + lp.topMargin = ConvertUtils.dp2px(120); + lin_mission.setLayoutParams(lp); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + public void signIn() { + SettingManager.signIn(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + SignInRewardsDialog dialog = new SignInRewardsDialog(activity, coin); + dialog.show(); + signData(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + } + }); + } + + @Override + public void onClick(View view) { + if (view == iv_sign_finish) { + finish(); + } else if (view == tv_go_dy) { + Intent intent = new Intent(this, MainActivity.class); + intent.putExtra("isFormTask", true); + startActivity(intent); + finish(); + } else if (view == tv_go_invite) { + startActivity(new Intent(this, InvitationActivity.class)); + } else if (view == tv_sign) { + switch (status) { + case 0: + BaseApplication.getInstance().getRechargeInfo(this, 0); + break; + case 1: + signIn(); + break; + case 2: + break; + } + } + } + + //微信支付成功后回调 + public void onEventMainThread(PayEvent event) { + int errCode = event.getErrCode(); + if (errCode == 0 || errCode == 101) { + MaleToast.showSuccessMsg(this, "充值成功"); + signData(); + } else if (errCode == -2) { + MaleToast.showFailureMsg(this, "充值取消"); + } else { + MaleToast.showFailureMsg(this, "充值失败"); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/MyCoverFlowAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MyCoverFlowAdapter.java new file mode 100644 index 0000000..5a09fcf --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MyCoverFlowAdapter.java @@ -0,0 +1,75 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.model.main.AnchorBean; +import com.fengliyan.uikit.mzbanner.ICoverFlowAdapter; + +import java.util.List; + +/** + * + */ +public class MyCoverFlowAdapter implements ICoverFlowAdapter { + private List mArray; + private Context context; + + public MyCoverFlowAdapter(Context context) { + this.context = context; + } + + public MyCoverFlowAdapter(Context context, List mArray) { + this.context = context; + this.mArray = mArray; + } + + @Override + public int getCount() { + return mArray.size(); + } + + @Override + public Object getItem(int position) { + return mArray.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + Holder holder = null; + if (convertView == null) { + holder = new Holder(); + convertView = View.inflate(context, R.layout.activity_image, null); + holder.ivChannelImg = convertView.findViewById(R.id.iv_cover_flow); +// holder.tv = (TextView) convertView.findViewById(R.id.tv); + } else { + holder = (Holder) convertView.getTag(); + } + + convertView.setTag(holder); + return convertView; + } + + @Override + public void getData(View view, int position) { + if (view != null) { + Holder holder = (Holder) view.getTag(); + AnchorBean channelBean = mArray.get(position); + holder.ivChannelImg.setImageURI(ConstUrl.IMAGE_URL + channelBean.getCover()); +// holder.ivChannelImg.setActualImageResource(channelBean.getImg()); + } + } + + public static class Holder { + SimpleDraweeView ivChannelImg; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/MyItemsActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MyItemsActivity.java new file mode 100644 index 0000000..58ae3e0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/MyItemsActivity.java @@ -0,0 +1,105 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.AbsListView; + +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.MyItemsAdapter; +import com.fengliyan.tianlesue.model.settings.BackPackListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import java.util.ArrayList; +import java.util.List; + +public class MyItemsActivity extends BaseActivity implements View.OnClickListener { + private LoadMoreListView mItemsListView; + private MyItemsAdapter mItemsAdapter; + private List mItemsList = new ArrayList<>(); + private int mPage = 1; + private boolean mPageLoad; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_social_list); + setDefaultTitle(); + setTitleName("红包卡券"); + initView(); + getItemsData(); + } + + private void initView() { + mItemsListView = findViewById(R.id.social_list); + mItemsAdapter = new MyItemsAdapter(this); + mItemsAdapter.setItemsBeans(mItemsList); + mItemsListView.setAdapter(mItemsAdapter); + mItemsAdapter.setOnButtonClickedListener(new MyItemsAdapter.OnButtonClickedListener() { + @Override + public void onCliked(int position) { + Intent intent = new Intent(MyItemsActivity.this, CaibeiRechargeActivity.class); + startActivity(intent); + } + }); + + mItemsAdapter.setOnItemClickedListener(new MyItemsAdapter.OnItemClickedListener() { + @Override + public void onClicked(int position) { + + } + }); + + mItemsListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if (mItemsList.size() != 0 && mItemsList.size() % 10 == 0 && !mPageLoad + && mItemsListView.getLastVisiblePosition() > mItemsList.size() - 2) { + getItemsData(); + mPageLoad = true; + } else if (mItemsListView.getLastVisiblePosition() <= mItemsList.size() - 2) { + mPageLoad = false; + } + } + }); + } + + private void getItemsData() { + MainManager.turntableWinningRecord(this, mPage, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BackPackListBean result, String message) { + if (mPage == 1) { + mItemsList.clear(); + } + mItemsList.addAll(result.getList()); + mItemsAdapter.notifyDataSetChanged(); + mPage++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + + @Override + public void onClick(View view) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/NewMessageNoticeActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/NewMessageNoticeActivity.java new file mode 100644 index 0000000..35ccff8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/NewMessageNoticeActivity.java @@ -0,0 +1,149 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.widget.CompoundButton; +import android.widget.Switch; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.im.uikit.common.ToastHelper; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.StatusBarNotificationConfig; +import com.netease.nimlib.sdk.mixpush.MixPushService; + +/** + * Created by zhangbin on 2019/2/21. + * 新消息通知 + */ + +public class NewMessageNoticeActivity extends BaseActivity { + + private Switch mRl_notice_switch; + private Switch mRl_voice_switch; + private Switch mRl_shake_switch; + private Switch mRl_flutter_switch; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_message_notice); + setTitleName("新消息通知"); + initView(); + } + + private void initView() { + mRl_notice_switch = findViewById(R.id.rl_notice_switch); + mRl_voice_switch = findViewById(R.id.rl_voice_switch); + mRl_shake_switch = findViewById(R.id.rl_shake_switch); + mRl_flutter_switch = findViewById(R.id.rl_flutter_switch); + + + //默认是打开的 + mRl_notice_switch.setChecked(NoClearSPUtils.getBoolean(this, Constant.NEW_MESSAGE_NOTICE, true)); + mRl_voice_switch.setChecked(NoClearSPUtils.getBoolean(this, Constant.RING_NOTICE, true)); + mRl_shake_switch.setChecked(NoClearSPUtils.getBoolean(this, Constant.SHAKE_NOTICE, true)); + mRl_flutter_switch.setChecked(NoClearSPUtils.getBoolean(this, Constant.FLUTTER_NOTICE, true)); + + mRl_shake_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.isPressed()) { + setVibrate(isChecked); + } + } + }); + + mRl_voice_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.isPressed()) { + setRing(isChecked); + } + } + }); + + mRl_notice_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.isPressed()) { + setMessageNotify(isChecked); + } + } + }); + + mRl_flutter_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.isPressed()) { + NoClearSPUtils.saveBoolean(NewMessageNoticeActivity.this, Constant.FLUTTER_NOTICE, isChecked); + } + } + }); + } + + + private void setRing(boolean ring) { + NoClearSPUtils.saveBoolean(this, Constant.RING_NOTICE, ring); + StatusBarNotificationConfig config = BaseApplication.getInstance().getStatusConfig(ring, NoClearSPUtils.getBoolean(this, Constant.SHAKE_NOTICE, true)); + NIMClient.updateStatusBarNotificationConfig(config); + } + + private void setVibrate(boolean vibrate) { + NoClearSPUtils.saveBoolean(this, Constant.SHAKE_NOTICE, vibrate); + StatusBarNotificationConfig config = BaseApplication.getInstance().getStatusConfig(NoClearSPUtils.getBoolean(this, Constant.RING_NOTICE, true), vibrate); + NIMClient.updateStatusBarNotificationConfig(config); + } + + private void setMessageNotify(final boolean checkState) { + // 如果接入第三方推送(小米),则同样应该设置开、关推送提醒 + // 如果关闭消息提醒,则第三方推送消息提醒也应该关闭。 + // 如果打开消息提醒,则同时打开第三方推送消息提醒。 + NIMClient.getService(MixPushService.class).enable(checkState).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { +// mRl_notice_switch.setChecked(checkState); + setToggleNotification(checkState); + } + + @Override + public void onFailed(int code) { +// mRl_notice_switch.setChecked(!checkState); + // 这种情况是客户端不支持第三方推送 + if (code == ResponseCode.RES_UNSUPPORT) { +// mRl_notice_switch.setChecked(checkState); + setToggleNotification(checkState); + } else if (code == ResponseCode.RES_EFREQUENTLY) { + mRl_notice_switch.setChecked(!checkState); + ToastHelper.showToast(NewMessageNoticeActivity.this, "操作太频繁"); + } else { + mRl_notice_switch.setChecked(!checkState); + ToastHelper.showToast(NewMessageNoticeActivity.this, "设置失败,请重试"); + } +// adapter.notifyDataSetChanged(); + } + + @Override + public void onException(Throwable exception) { + } + }); + } + + private void setToggleNotification(boolean checkState) { + try { + setNotificationToggle(checkState); + NIMClient.toggleNotification(checkState); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void setNotificationToggle(boolean on) { +// UserPreferences.setNotificationToggle(on); + NoClearSPUtils.saveBoolean(this, Constant.NEW_MESSAGE_NOTICE, on); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/NickNameEditActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/NickNameEditActivity.java new file mode 100644 index 0000000..4123dfe --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/NickNameEditActivity.java @@ -0,0 +1,124 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.settings.dialog.WQTipsDialog; + + +public class NickNameEditActivity extends BaseActivity implements View.OnClickListener{ + private EditText mNickNameEdit; + private Button mConfirmButton; + private String mName; + private WQTipsDialog mTipsDialog; + private String mTips; + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setTitleName("修改昵称"); + setDefaultTitle(); + setContentView(R.layout.activity_nickname_edit); + mName = getIntent().getStringExtra("nickName"); + mTips = getIntent().getStringExtra("nickNameTips"); + mTipsDialog=new WQTipsDialog(this); + initView(); + } + + private void initView(){ + mNickNameEdit = findViewById(R.id.nick_name_edit_input); + mConfirmButton = findViewById(R.id.nick_name_edit_button_confirm); + mNickNameEdit.setText(mName); + mConfirmButton.setOnClickListener(this); + mTipsDialog.show(mTips); + } + + @Override + public void onClick(View view) { + if(view == mConfirmButton){ + if(TextUtils.isEmpty(mNickNameEdit.getText())){ + MaleToast.showMessage(NickNameEditActivity.this, "请输入名字"); + return; + } + + Intent intent = new Intent(); + intent.putExtra("newName", mNickNameEdit.getText().toString()); + setResult(RESULT_OK, intent); +// MaleToast.showMessage(NickNameEditActivity.this, "修改成功"); + finish(); + } + } + + @Override + public void finishActivity() { +// super.finishActivity(); + if(TextUtils.isEmpty(mNickNameEdit.getText())){ + MaleToast.showMessage(NickNameEditActivity.this, "请输入名字"); + }else { + if (mName.equals(mNickNameEdit.getText().toString())) { //相等 + finish(); + }else { + saveDialog(); + } + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if(keyCode ==KeyEvent.KEYCODE_BACK){ + + if(TextUtils.isEmpty(mNickNameEdit.getText())){ + MaleToast.showMessage(NickNameEditActivity.this, "请输入名字"); + }else { + if (mName.equals(mNickNameEdit.getText().toString())) { //相等 + finish(); + }else { + saveDialog(); + } + } + + return true; + + } + return super.onKeyDown(keyCode, event); + } + + private BaseMessageDialog saveDialog; + + /** + * 是否删除 + */ + public void saveDialog() { + saveDialog = new BaseMessageDialog.Builder(this).setMessage("是否保存?") + .setCancelable(true) + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(); + intent.putExtra("newName", mNickNameEdit.getText().toString()); + setResult(RESULT_OK, intent); +// MaleToast.showMessage(NickNameEditActivity.this, "修改成功"); + saveDialog.dismiss(); + finish(); + } + }).setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + saveDialog.dismiss(); + finish(); + + } + }).build(); + + saveDialog.show(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/PersonalSignatureActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PersonalSignatureActivity.java new file mode 100644 index 0000000..322e2db --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PersonalSignatureActivity.java @@ -0,0 +1,101 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.uikit.dialog.BaseMessageDialog; + +public class PersonalSignatureActivity extends BaseActivity implements View.OnClickListener { + private TextView tv_finish; + private TextView tv_save; + private EditText et_signature; + private TextView tv_text_num; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_personal_signature); + hideTitleBar(); + initView(); + et_signature.setText(getIntent().getStringExtra("signature")); + et_signature.setSelection(et_signature.getText().length()); + } + + private void initView() { + tv_finish = findViewById(R.id.tv_finish); + tv_save = findViewById(R.id.tv_save); + et_signature = findViewById(R.id.et_signature); + tv_text_num = findViewById(R.id.tv_text_num); + + tv_finish.setOnClickListener(this); + tv_save.setOnClickListener(this); + et_signature.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + tv_text_num.setText(et_signature.getText().toString().length() + "/20"); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + @Override + public void onClick(View view) { + if (view == tv_finish) { + saveDialog(); + } else if (view == tv_save) { + String signature = et_signature.getText().toString(); + setResult(RESULT_OK, new Intent().putExtra("signature", signature)); + finish(); + } + } + + @Override + public void onBackPressed() { + saveDialog(); + } + + private BaseMessageDialog saveDialog; + + public void saveDialog() { + if (!StrU.isEmpty(et_signature.getText().toString())) { + saveDialog = new BaseMessageDialog.Builder(this).setMessage("是否保存?") + .setCancelable(true) + .setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + saveDialog.dismiss(); + String signature = et_signature.getText().toString(); + setResult(RESULT_OK, new Intent().putExtra("signature", signature)); + finish(); + } + }).setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + saveDialog.dismiss(); + finish(); + } + }).build(); + saveDialog.show(); + } else { + finish(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/PhoneUseActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PhoneUseActivity.java new file mode 100644 index 0000000..cffca83 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PhoneUseActivity.java @@ -0,0 +1,59 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.SettingBrandAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.SettingBrandBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import java.util.List; + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class PhoneUseActivity extends BaseActivity { + + private RecyclerView mRv_phone; + private SettingBrandAdapter mAdapter; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTitleName("来电提醒"); + setContentView(R.layout.phone_use_activity); + mRv_phone = findViewById(R.id.rv_phone); + + getSettingBrand(); + } + + private void getSettingBrand() { + SettingManager.getSettingBrand(this, new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, + StaggeredGridLayoutManager.VERTICAL); + + mRv_phone.setLayoutManager(staggeredGridLayoutManager); + mAdapter = new SettingBrandAdapter(PhoneUseActivity.this, result); + mRv_phone.setAdapter(mAdapter); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/PreSelfieActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PreSelfieActivity.java new file mode 100644 index 0000000..875b509 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PreSelfieActivity.java @@ -0,0 +1,166 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.settings.manager.UserAvatarManager; +import com.fengliyan.tianlesue.model.settings.SelfieExampleBean; +import com.fengliyan.tianlesue.utils.camera2.GirlCameraTakePicActivity; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +public class PreSelfieActivity extends BaseActivity implements View.OnClickListener, UserAvatarManager.UserImgListener { + public static int REQUEST_SELFIE = 207; + // private SimpleDraweeView mExampleView; + private Button mConfirmButton; + private TextView mAbnormalText; + private int mActionType; + private ProgressDialog mProgressDialog; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_verify_take_photo_ready); + setDefaultTitle(); + setTitleName("自拍认证"); + initView(); + getSelfieExample(); + } + + private void initView() { +// mExampleView = findViewById(R.id.verify_photo_upload_example); + mConfirmButton = findViewById(R.id.verify_photo_go); + mAbnormalText = findViewById(R.id.verify_abnormal_status); + mConfirmButton.setOnClickListener(this); + } + + private void getSelfieExample() { + SettingManager.getSelfieExample(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SelfieExampleBean result, String message) { +// mExampleUrl = ConstUrl.IMAGE_URL + result.getAction_image(); +// mExampleView.setImageURI(mExampleUrl); + + if (1 == result.getAudit_status() || 2 == result.getAudit_status()) { + mConfirmButton.setEnabled(false); + mConfirmButton.setText("正在审核"); + } else { + mConfirmButton.setEnabled(true); + } + + if (2 == result.getAudit_status()) { + mAbnormalText.setText(result.getAudit_remark()); + } + + mActionType = result.getAction_type(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + if (view == mConfirmButton) { +// XXPermissions.with(this) +// .permission(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE) +// .request(new OnPermissionCallback() { +// @Override +// public void onGranted(List permissions, boolean all) { +// if (all) { + startActivityForResult(new Intent(PreSelfieActivity.this, GirlCameraTakePicActivity.class), + 100); +// } +// } + +// @Override +// public void onDenied(List permissions, boolean never) { +// if (never) { +// CustomAlertDialog dialog = new CustomAlertDialog(PreSelfieActivity.this); +// dialog.setTitle("私语请求相机权限,是否允许?"); +// dialog.hideContent(true); +// dialog.setRightBtnText("去开启"); +// dialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { +// @Override +// public void rightClick() { +// PermissionUtil.jumpPermissionPage(PreSelfieActivity.this); +// } +// }); +// dialog.show(); +// } +// } +// }); + } + } + + + @Override + public void getUserImg(@Nullable final String path) { + if (!TextUtils.isEmpty(path)) { +// final String[] imagePath = {path}; + + Intent intent = new Intent(PreSelfieActivity.this, ProSelfieActivity.class); + intent.putExtra("path", path); + intent.putExtra("actionType", mActionType); + startActivityForResult(intent, REQUEST_SELFIE); + +// mProgressDialog = ProgressDialog.show(PreSelfieActivity.this, "请等待...", "图片正在加载中...", true, false); +// new Thread(new Runnable() { +// @Override +// public void run() { +// String newPath = ImageUtils.compressImage(PreSelfieActivity.this, path, Constant.IMAGE_MEMORY_SIZE); +// if (!TextUtils.isEmpty(newPath)) { +// Intent intent = new Intent(PreSelfieActivity.this, ProSelfieActivity.class); +// intent.putExtra("exampleUrl", mExampleUrl); +// intent.putExtra("path", newPath); +// intent.putExtra("actionType", mActionType); +// startActivityForResult(intent, REQUEST_SELFIE); +//// mProgressDialog.cancel(); +// mProgressDialog.dismiss(); +// } +// +// } +// }).start(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 100 && RESULT_OK == resultCode) { + Intent intent = new Intent(PreSelfieActivity.this, ProSelfieActivity.class); + intent.putExtra("path", data.getStringExtra("path")); + intent.putExtra("actionType", mActionType); + startActivityForResult(intent, REQUEST_SELFIE); + } + + if (requestCode == REQUEST_SELFIE) { + if (RESULT_CANCELED == resultCode) { + getSelfieExample(); + } else if (RESULT_OK == resultCode) { + finish(); + MaleToast.showMessage(PreSelfieActivity.this, "上传完成,请耐心等待审核结果"); + } + } + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/PrivilegeSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PrivilegeSettingActivity.java new file mode 100644 index 0000000..f351e52 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/PrivilegeSettingActivity.java @@ -0,0 +1,160 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.CompoundButton; + +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.databinding.ActivityPrivilegeSettingBinding; +import com.fengliyan.tianlesue.model.settings.MemberBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +public class PrivilegeSettingActivity extends BaseActivity implements CompoundButton.OnCheckedChangeListener { + ActivityPrivilegeSettingBinding binding; + private String type; + private int value; + private boolean isVip; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + binding = ActivityPrivilegeSettingBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setDefaultTitle(); + setTitleName("会员特权设置"); + isVip = getIntent().getBooleanExtra("isVip", false); + if (isVip) { + binding.tvOpenVip.setVisibility(View.GONE); + } else { + binding.tvOpenVip.setVisibility(View.VISIBLE); + } + binding.tvOpenVip.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(PrivilegeSettingActivity.this, MemberActivity.class); + intent.putExtra("index", 0); + startActivity(intent); + } + }); + } + + private void setListener() { + binding.stSwitch1.setOnCheckedChangeListener(this); + binding.stSwitch2.setOnCheckedChangeListener(this); + binding.stSwitch3.setOnCheckedChangeListener(this); + binding.stSwitch4.setOnCheckedChangeListener(this); + binding.stSwitch5.setOnCheckedChangeListener(this); + binding.stSwitch6.setOnCheckedChangeListener(this); + binding.stSwitch7.setOnCheckedChangeListener(this); + binding.stSwitch8.setOnCheckedChangeListener(this); + binding.stSwitch9.setOnCheckedChangeListener(this); + binding.stSwitch10.setOnCheckedChangeListener(this); + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (!isVip) { + MaleToast.showMessage(this, "用户非会员或会员过期"); + buttonView.setChecked(!isChecked); + } else { + if (buttonView == binding.stSwitch1) { + type = "login_notice_hide"; + } else if (buttonView == binding.stSwitch2) { + type = "visitor_hide"; + } else if (buttonView == binding.stSwitch3) { + type = "rank"; + } else if (buttonView == binding.stSwitch4) { + type = "login_time_hide"; + } else if (buttonView == binding.stSwitch5) { + type = "rechange"; + } else if (buttonView == binding.stSwitch6) { + type = "greet_hide"; + } else if (buttonView == binding.stSwitch7) { + type = "speed_hide"; + } else if (buttonView == binding.stSwitch8) { + type = "avatar_hide"; + } else if (buttonView == binding.stSwitch9) { + type = "read_msg"; + } else if (buttonView == binding.stSwitch10) { + type = "hide_fans"; + } + if (isChecked) { + value = 1; + } else { + value = 0; + } +// if (StrU.equals("hide_fans", type)) { +// if (isChecked) { +// value = 0; +// } else { +// value = 1; +// } +// } + memberAuthority(type, value); + } + } + + @Override + public void onResume() { + super.onResume(); + refresh(); + } + + void refresh() { + SettingManager.getMemberInfo(this, 6, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MemberBean result, String message) { + if (result.getOperation() != null) { + binding.stSwitch1.setChecked(result.getOperation().getLogin_notice_hide() > 0); + binding.stSwitch2.setChecked(result.getOperation().getVisitor_hide() > 0); + binding.stSwitch3.setChecked(result.getOperation().getRank_hide() > 0); + binding.stSwitch4.setChecked(result.getOperation().getLogin_time_hide() > 0); + binding.stSwitch5.setChecked(result.getOperation().getRechange_hide() > 0); + binding.stSwitch6.setChecked(result.getOperation().getGreet_hide() > 0); + binding.stSwitch7.setChecked(result.getOperation().getSpeed_hide() > 0); + binding.stSwitch8.setChecked(result.getOperation().getAvatar_hide() > 0); + binding.stSwitch9.setChecked(result.getOperation().getHide_read_msg() > 0); + binding.stSwitch10.setChecked(result.getOperation().getHide_fans() > 0); + setListener(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + /** + * @param type rank 隐藏排行榜 greet 消息免打扰,(新版会员增加:login_notice_hide:上线通知隐藏、login_time_hide:登录时间隐藏、greet_hide:群招呼信息免打扰、visitor_hide:访问足迹隐藏、speed_hide:速配弹窗免打扰、avatar_hide:动画效果框) + * @param value 0关闭 1开启 + */ + private void memberAuthority(final String type, final int value) { + SettingManager.memberAuthority(this, type, value, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + MaleToast.showMessage(activity, message); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/ProSelfieActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ProSelfieActivity.java new file mode 100644 index 0000000..77ca40a --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/ProSelfieActivity.java @@ -0,0 +1,161 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.Manifest; +import android.app.ProgressDialog; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; + +import com.fengliyan.tianlesue.utils.camera2.GirlCameraTakePicActivity; +import com.facebook.drawee.view.SimpleDraweeView; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.settings.manager.UserAvatarManager; +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.ImageUtils; + +import java.io.File; +import java.util.List; + +public class ProSelfieActivity extends BaseActivity implements View.OnClickListener, UserAvatarManager.UserImgListener { + private SimpleDraweeView mPhotoView; + private Button mRedo; + private Button mConfirmButton; + private String mPath; + private int mActionType; + + private ProgressDialog mProgressDialog; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_verify_photo_upload); + setDefaultTitle(); + setTitleName("自拍认证"); + mPath = getIntent().getStringExtra("path"); + mActionType = getIntent().getIntExtra("actionType", 2); + initView(); + } + + private void initView() { + mPhotoView = findViewById(R.id.verify_photo_upload_mine); + mRedo = findViewById(R.id.verify_photo_redo); + mConfirmButton = findViewById(R.id.verify_photo_upload); + mRedo.setOnClickListener(this); + mConfirmButton.setOnClickListener(this); + mPhotoView.setImageURI("file://" + mPath); + + } + + @Override + public void onClick(View view) { + if (view == mRedo) { //重拍 + XXPermissions.with(this) + .permission(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + startActivityForResult(new Intent(ProSelfieActivity.this, GirlCameraTakePicActivity.class), + 100); + } + } + }); + } else if (view == mConfirmButton) { //上传 + if (!TextUtils.isEmpty(mPath)) { + mProgressDialog = ProgressDialog.show(ProSelfieActivity.this, "请等待...", "图片正在上传中...", true, false); + new Thread(new Runnable() { + @Override + public void run() { + final String newPath = ImageUtils.compressImage(ProSelfieActivity.this, mPath, Constant.IMAGE_MEMORY_SIZE, false); + if (!TextUtils.isEmpty(newPath)) { + runOnUiThread(new Runnable() { + @Override + public void run() { + uploadImage(newPath); + } + }); + } + } + }).start(); + } + } + } + + public void uploadImage(String path) { + UploadFile[] uploadFiles = new UploadFile[1]; + File file = new File(path); + UploadFile uploadFile = new UploadFile("file", file); + uploadFiles[0] = uploadFile; + + DynamicsManager.uploadImage(this, uploadFiles, "audit", false, new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + check(result.get(0).getUrl()); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + mProgressDialog.dismiss(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + mProgressDialog.dismiss(); + } + }); + } + + public void check(String path) { + SettingManager.checkSelfie(this, mActionType, path, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Boolean result, String message) { + mProgressDialog.dismiss(); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + mProgressDialog.dismiss(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + mProgressDialog.dismiss(); + } + }); + } + + @Override + public void getUserImg(@Nullable String path) { + if (!TextUtils.isEmpty(path)) { + mPhotoView.setImageURI("file://" + path); + mPath = path; + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 100 && RESULT_OK == resultCode) { + mPath = data.getStringExtra("path"); + mPhotoView.setImageURI("file://" + mPath); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/QuickRechargeActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/QuickRechargeActivity.kt new file mode 100644 index 0000000..0b90f42 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/QuickRechargeActivity.kt @@ -0,0 +1,377 @@ +package com.fengliyan.tianlesue.view.settings + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.text.TextUtils +import android.util.DisplayMetrics +import android.view.Gravity +import android.view.View +import android.view.WindowManager +import android.widget.Toast +import androidx.recyclerview.widget.StaggeredGridLayoutManager +import com.alipay.sdk.app.PayTask +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.Constant +import com.fengliyan.tianlesue.controller.eventBus.PayEvent +import com.fengliyan.tianlesue.controller.settings.adapter.RechargeAdapter +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager +import com.fengliyan.tianlesue.controller.user.manager.UserManager +import com.fengliyan.tianlesue.databinding.ActivityQuickrechargeBinding +import com.fengliyan.tianlesue.im.uikit.common.Constans +import com.fengliyan.tianlesue.model.settings.PayBean +import com.fengliyan.tianlesue.model.settings.RechargeBean +import com.fengliyan.tianlesue.model.settings.RechargeListBean +import com.fengliyan.tianlesue.model.settings.WXPayTypeBean +import com.fengliyan.tianlesue.utils.PayUtils +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.PayWebViewActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.diooto.tools.Utils +import com.fengliyan.storage.StorageManager +import com.fengliyan.uikit.toast.MaleToast +import com.sand.qzf.paytypesdk.base.PayTypeSdk +import com.sand.qzf.paytypesdk.base.Resp +import com.tencent.mm.opensdk.modelpay.PayReq +import com.tencent.mm.opensdk.openapi.WXAPIFactory +import de.greenrobot.event.EventBus + +private const val TAG = "QuickRechargeActivity" + +class QuickRechargeActivity : BaseActivity() { + + lateinit var binding: ActivityQuickrechargeBinding + lateinit var mRechargeAdapter: RechargeAdapter + private val mRechargeList = mutableListOf() + var isWXHF = false + var ghOriId = "" + var mini_program_type = 0 + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityQuickrechargeBinding.inflate(layoutInflater) + setContentView(binding.root) + initViews() + val lastWX = StorageManager.getInstance(this).getInt("lastWX") + val default_pay_type = StorageManager.getInstance(this).getString(Constans.DEFAULT_PAY_TYPE) + var isWX = true; + if (lastWX == 0) { + isWX = true + } else if (lastWX == 1) { + isWX = false + } else { + isWX = !TextUtils.equals("1", default_pay_type) + } + changePayType(isWX) +// if (lastWX == 1) { +// getRechargeInfo(6) +// } else { +// getRechargeInfo(2) +// } + } + + override fun onResume() { + super.onResume() +// getRechargeInfo(2) + } + + fun initViews() { + if (UserManager.getUserInfo().gender == 1) { + binding.vipBtn.visibility = View.INVISIBLE + } + hideTitleBar() + binding.closeBtn.setOnClickListener { + finish() + } + mRechargeAdapter = RechargeAdapter(this) + mRechargeAdapter.isQuick = true + mRechargeAdapter.setRechargeList(mRechargeList) + mRechargeAdapter.setType(1) + mRechargeAdapter.setOnItemClickListener { v, position -> + if (position == mRechargeList.size - 1) { + startActivity( + Intent(QuickRechargeActivity@ this, CaibeiRechargeActivity::class.java) + ) + finish() + return@setOnItemClickListener + } + isSelected = true + mRechargeAdapter.setSelectedPosition(position) + mRechargeAdapter.notifyDataSetChanged() + mSelectedGoodPosition = position + } + binding.caibeiRechargeListview.setLayoutManager(object : StaggeredGridLayoutManager( + 3, + VERTICAL + ) { + override fun canScrollVertically(): Boolean { + return false + } + }) + binding.caibeiRechargeListview.setNestedScrollingEnabled(true) + binding.caibeiRechargeListview.setAdapter(mRechargeAdapter) + binding.confirmBtn.setOnClickListener { + if ("wechat" == mSelectedPayMethod) { + getWXPayType() + } else { + confirmToPay() + } + } + + binding.aliPayBtn.setOnClickListener { + changePayType(false) + } + binding.wxPayBtn.setOnClickListener { + changePayType(true) + } + binding.vipBtn.setOnClickListener { + startActivity(Intent(QuickRechargeActivity@ this, MemberActivity::class.java)) + } + } + + fun changePayType(isWx: Boolean) { + binding.wxPayBtn.isSelected = isWx + binding.aliPayBtn.isSelected = !isWx + if (isWx) { + //微信支付 + mRechargeAdapter.isWXRecharge = false + mRechargeAdapter.setSelectedPosition(mSelectedGoodPosition) + getRechargeInfo(6) + } else { + //支付宝支付 + mRechargeAdapter.isWXRecharge = false + mRechargeAdapter.setSelectedPosition(mSelectedGoodPosition) + getRechargeInfo(2) + } + } + + private var mSelectedGoodPosition = 0 + private var isSelected = false + private var mSelectedPayMethod = "wechat" + private var mOrderInfo: String? = null + private val mPayRunnable = Runnable { + val alipay = PayTask(this@QuickRechargeActivity) + val result = alipay.payV2(mOrderInfo, true) + val msg = Message() + msg.what = CaibeiRechargeActivity.SDK_PAY_FLAG + msg.obj = result + mHandler.sendMessage(msg) + } + + private val mHandler: Handler = object : Handler() { + override fun handleMessage(msg: Message) { + if (msg.what == CaibeiRechargeActivity.SDK_PAY_FLAG) { + EventBus.getDefault().post(PayEvent(101)) + } + } + } + + //2 支付宝 6微信 + private fun getRechargeInfo(type: Int) { + SettingManager.getRechargeInfo(this, type, object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: RechargeListBean?, + message: String? + ) { + binding.coinLabel.text = (result!!.coin + result!!.income_coin).toString() + if (!isSelected) { + mSelectedGoodPosition = result.selected_id + } + mRechargeAdapter.setSelectedPosition(mSelectedGoodPosition) + if (result.show_wx_pay_type == 0 && result.show_alipay_pay_type == 0) { + binding.tvDialogRechargeHint.visibility = View.VISIBLE + binding.confirmBtn.visibility = View.GONE + } else { + binding.tvDialogRechargeHint.visibility = View.GONE + binding.confirmBtn.visibility = View.VISIBLE + if (result.show_wx_pay_type == 0) { + binding.wxPayBtn.visibility = View.GONE + binding.wxPayBtn.isSelected = false + binding.aliPayBtn.isSelected = true + } else { + binding.wxPayBtn.visibility = View.VISIBLE + } + if (result.show_alipay_pay_type == 0) { + binding.aliPayBtn.visibility = View.GONE + binding.wxPayBtn.isSelected = true + binding.aliPayBtn.isSelected = false + } else { + binding.aliPayBtn.visibility = View.VISIBLE + } + } + mRechargeList.clear() + while (result.list.size > 6) { + result.list.removeAt(result.list.size - 1) + } + if (type == 2) { + mRechargeAdapter.setType(1) + } + mRechargeList.addAll(result.list) + mRechargeAdapter.notifyDataSetChanged() + + } + + override fun onFailure(activity: BaseActivity, tip: String) {} + override fun onException(activity: BaseActivity, e: Throwable) {} + }) + } + + private fun getWXPayType() { + SettingManager.getWechatPaySite(this, object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: WXPayTypeBean?, tips: String?) { + isWXHF = result!!.wechat_type == 3 + ghOriId = result.gh_ori_id + mini_program_type = result.mini_program_type + confirmToPay() + } + + override fun onFailure(activity: BaseActivity, tip: String) {} + override fun onException(activity: BaseActivity, e: Throwable) {} + }) + } + + private fun confirmToPay() { + if (mRechargeList.size == 0) { + return + } + val rechargeBean = mRechargeList[mSelectedGoodPosition] + if (binding.aliPayBtn.isSelected) { + mSelectedPayMethod = "alipay"; + StorageManager.getInstance(this).putInt("lastWX", 1); + } else { + mSelectedPayMethod = "wechat"; + StorageManager.getInstance(this).putInt("lastWX", 0); + } + if (isWXHF && mSelectedPayMethod == "wechat") { + PayUtils.wxminiPay(this, rechargeBean.id, 0, ghOriId, mini_program_type) + return + } + + SettingManager.payToRecharge(this, mSelectedPayMethod, rechargeBean.id.toString() + "", 0, + object : HttpUiCallBack { + override fun onSuccess( + activity: BaseActivity?, + result: PayBean?, + message: String? + ) { + if ("alipay" == mSelectedPayMethod) { + if (result!!.pay_platform_type == 1) { + if (null != result.payinfo) { + mOrderInfo = result.payinfo + val payThread = Thread(mPayRunnable) + payThread.start() + } + } else if (result.pay_platform_type == 2) { + if (null != result.payinfo) { + mOrderInfo = result.payinfo + PayUtils.ailWeb(mOrderInfo, this@QuickRechargeActivity) + } + } else if (result.pay_platform_type == 4) { + val intent = Intent( + this@QuickRechargeActivity, + PayWebViewActivity::class.java + ) + intent.putExtra("ClickUrl", result.kqPayInfo) + startActivity(intent) + } else if (result.pay_platform_type == 5) { + PayUtils.SFTPay(this@QuickRechargeActivity, result.payinfo) + } else { + PayTypeSdk.getInstance().cashierPay( + this@QuickRechargeActivity, result.sandpayinfo.cashierUrl + ) { resp -> + if (resp.status == Resp.SUCCESS || resp.status == Resp.FINISH) { + getRechargeInfo(6) + } + } + } + } else if ("wechat" == mSelectedPayMethod) { + if (result!!.pay_platform_type == 1) { + val wxapi = WXAPIFactory.createWXAPI( + this@QuickRechargeActivity, + Constant.WECHAT_APP_ID, + false + ) + val wechatpayinfo = result.wechatpayinfo + val req = PayReq() + req.appId = Constant.WECHAT_APP_ID + req.partnerId = wechatpayinfo.mch_id //商户号 + req.prepayId = wechatpayinfo.prepay_id //预付款id + req.nonceStr = wechatpayinfo.nonce_str + req.timeStamp = wechatpayinfo.timestamp.toString() + "" + req.packageValue = "Sign=WXPay" //固定值 + req.sign = wechatpayinfo.paySign + val isWXAppInstalledAndSupported = wxapi.isWXAppInstalled + if (isWXAppInstalledAndSupported) { + wxapi.registerApp(Constant.WECHAT_APP_ID) + wxapi.sendReq(req) + } else { + MaleToast.showMessage(this@QuickRechargeActivity, "未安装微信,不能支付") + } + } else if (result.pay_platform_type == 4) { + val intent = Intent( + this@QuickRechargeActivity, + PayWebViewActivity::class.java + ) + intent.putExtra("ClickUrl", result.kqPayInfo) + startActivity(intent) + } else if (result.pay_platform_type == 5) { + PayUtils.SFTPay(this@QuickRechargeActivity, result.payinfo) + } else { + PayTypeSdk.getInstance().cashierPay( + this@QuickRechargeActivity, result.sandpayinfo.cashierUrl + ) { resp -> + if (resp.status == Resp.SUCCESS || resp.status == Resp.FINISH) { + } + } + } + } + } + + override fun onFailure(activity: BaseActivity, tip: String) { + Toast.makeText(activity, tip, Toast.LENGTH_SHORT).show() + } + + override fun onException(activity: BaseActivity, e: Throwable) { + Toast.makeText(activity, "支付出错", Toast.LENGTH_SHORT).show() + } + }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + val dm = DisplayMetrics() + windowManager.defaultDisplay.getMetrics(dm) + val view: View = window.decorView + val lp: WindowManager.LayoutParams = view.getLayoutParams() as WindowManager.LayoutParams + lp.gravity = Gravity.BOTTOM + lp.width = dm.widthPixels + lp.height = Utils.dip2px(this, 460f) + windowManager.updateViewLayout(view, lp) + view.setBackgroundResource(R.drawable.bg_quick_recharge) //圆角背景 + } + + fun onEventMainThread(event: PayEvent) { + val errCode = event.errCode + when (errCode) { + 0 -> { + MaleToast.showSuccessMsg(this@QuickRechargeActivity, "充值成功") + getRechargeInfo(6) + } + -2 -> { + MaleToast.showFailureMsg(this@QuickRechargeActivity, "充值取消") + } + 101 -> { + getRechargeInfo(2) + } + else -> { + MaleToast.showFailureMsg(this@QuickRechargeActivity, "充值失败") + } + } + } + + override fun onDestroy() { + super.onDestroy() + StorageManager.getInstance(this).putBoolean(Constans.IS_SHOW_DIALOG, false) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/RankActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/RankActivity.java new file mode 100644 index 0000000..840ca78 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/RankActivity.java @@ -0,0 +1,378 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.githang.statusbar.StatusBarCompat; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.main.adapter.MainViewPagerAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.dialog.BottomSelectiveDialog; + +import java.util.ArrayList; +import java.util.List; + +public class RankActivity extends BaseActivity implements View.OnClickListener { + private ViewPager mMainViewPager; + private MainViewPagerAdapter mViewPagerAdapter; + private List mChannelFragments = new ArrayList<>(); + private SimpleDraweeView mMyPhoto; + private TextView mMyName; + private TextView mMyCost; + private TextView mMyNumber; + private View mMyRankView; + private RankFragment mWeeklyFragment; + private RankFragment mMonthlyFragment; + private RankFragment mTotalFragment; + private TextView mWeeklyView; + private TextView mMonthlyView; + private TextView mTotalView; + private int mRankType; //0 魅力榜 1富豪榜 2礼物榜 //3消费榜 + private int mRangeType; //1 周榜 2 月榜 3 年榜 + private BottomSelectiveDialog mRankSelectDialog; + private RelativeLayout mRlBack; + private TextView mTvSelect; + private TextView mTvList; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_daka_rank); + StatusBarCompat.setTranslucent(getWindow(), true); + StatusBarCompat.resetActionBarContainerTopMargin(getWindow()); + StatusBarCompat.setLightStatusBar(getWindow(), false); + mRankType = getIntent().getIntExtra("rankType", 0); + initView(); + +// if(0 == mRankType){ +// setRightCustomTextTitle("魅力榜", "筛选", new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// mRankSelectDialog.show(); +// } +// }); +// +// }else if(1 == mRankType){ +// setRightCustomTextTitle("财富榜", "筛选", new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// mRankSelectDialog.show(); +// } +// }); +// +// }else if(2 == mRankType){ +// setRightCustomTextTitle("礼物榜", "筛选", new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// mRankSelectDialog.show(); +// } +// }); +// } + //chooseMonthData(); + } + + private void initView() { + + hideTitleBar(); + mMainViewPager = (ViewPager) findViewById(R.id.main_view_pager); + mMyPhoto = findViewById(R.id.daka_rank_my_photo); + mMyName = findViewById(R.id.daka_rank_my_name); + mMyNumber = findViewById(R.id.daka_rank_my_number); + mMyCost = findViewById(R.id.daka_rank_my_cost); + mWeeklyView = findViewById(R.id.daka_rank_header_week); + mMonthlyView = findViewById(R.id.daka_rank_header_month); + mTotalView = findViewById(R.id.daka_rank_header_total); + mMyRankView = findViewById(R.id.daka_rank_my_view); + mRlBack = findViewById(R.id.rl_back); //箭头返回键 + mTvSelect = findViewById(R.id.tv_select); //筛选 + mTvList = findViewById(R.id.tv_list); //榜单标题 + + mWeeklyView.setOnClickListener(this); + mMonthlyView.setOnClickListener(this); + mTotalView.setOnClickListener(this); + + mRlBack.setOnClickListener(this); + mTvSelect.setOnClickListener(this); + + if (0 == mRankType) { +// setRightCustomTextTitle("魅力榜", "筛选", new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// +// } +// }); + mTvList.setText("魅力榜"); + } else if (1 == mRankType) { + mTvList.setText("金币榜"); + } else if (2 == mRankType) { + mTvList.setText("礼物榜"); + } else if (3 == mRankType) { + mTvList.setText("消费榜"); + } + + mMainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if (0 == position) { + chooseWeekData(); + } else if (1 == position) { + chooseMonthData(); + } else if (2 == position) { + chooseTotalData(); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + mViewPagerAdapter = new MainViewPagerAdapter(getSupportFragmentManager(), + mChannelFragments); + + mWeeklyFragment = new RankFragment(); + mMonthlyFragment = new RankFragment(); + mTotalFragment = new RankFragment(); + mChannelFragments.add(mWeeklyFragment); + mChannelFragments.add(mMonthlyFragment); + mChannelFragments.add(mTotalFragment); + mMainViewPager.setAdapter(mViewPagerAdapter); + mMainViewPager.setCurrentItem(1, true); + mRankSelectDialog = new BottomSelectiveDialog(this, R.style.SelectiveDialog); + mRankSelectDialog.addSelectButton("魅力榜", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mRankType = 0; + chooseMonthData(); + mMainViewPager.setCurrentItem(1, false); + mRankSelectDialog.dismiss(); + mTvList.setText("魅力榜"); + } + }); + + mRankSelectDialog.addSelectButton("金币榜", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mRankType = 1; + chooseMonthData(); + mMainViewPager.setCurrentItem(1, false); + mRankSelectDialog.dismiss(); + mTvList.setText("金币榜"); + } + }); + + mRankSelectDialog.addSelectButton("礼物榜", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mRankType = 2; + chooseMonthData(); + mMainViewPager.setCurrentItem(1, false); + mRankSelectDialog.dismiss(); + mTvList.setText("礼物榜"); + } + }); + + mRankSelectDialog.addSelectButton("消费榜", new BottomSelectiveDialog.OnButtonSelectListener() { + @Override + public void onClicked(View view, int index) { + mRankType = 3; + chooseMonthData(); + mMainViewPager.setCurrentItem(1, false); + mRankSelectDialog.dismiss(); + mTvList.setText("消费榜"); + } + }); + } + + private void chooseWeekData() { + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mWeeklyView.setBackgroundResource(R.drawable.shape_rank_left); + mMonthlyView.setTextColor(getResources().getColor(android.R.color.white)); + mTotalView.setTextColor(getResources().getColor(android.R.color.white)); + mWeeklyView.setTextColor(getResources().getColor(R.color.daka2)); + mRangeType = 1; + whichRank(mRangeType); + } + + private void chooseMonthData() { + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(R.drawable.shape_rank_right); + mWeeklyView.setTextColor(getResources().getColor(android.R.color.white)); + mTotalView.setTextColor(getResources().getColor(android.R.color.white)); + mMonthlyView.setTextColor(getResources().getColor(R.color.daka2)); + mRangeType = 2; + whichRank(mRangeType); + } + + private void chooseTotalData() { + mWeeklyView.setBackgroundResource(android.R.color.transparent); + mMonthlyView.setBackgroundResource(android.R.color.transparent); + mTotalView.setBackgroundResource(R.drawable.shape_rank_right); + mWeeklyView.setTextColor(getResources().getColor(android.R.color.white)); + mMonthlyView.setTextColor(getResources().getColor(android.R.color.white)); + mTotalView.setTextColor(getResources().getColor(R.color.daka2)); + mRangeType = 3; + whichRank(mRangeType); + } + + public void whichRank(int type) { + if (mRankType == 0) { + getLoveRank(type); + } else if (mRankType == 1) { + getWealthRank(type); + } else if (mRankType == 2) { + getGiftRank(type); + } else if (mRankType == 3) { + getCustomerRank(type); + } + } + + //消费榜 + public void getCustomerRank(final int type) { + SettingManager.rankWealth(this, mRangeType, 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { + handleResult(type, result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + + //魅力榜 + public void getLoveRank(final int type) { + SettingManager.rankLove(this, mRangeType, 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { + handleResult(type, result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + //金币榜 + public void getWealthRank(final int type) { + SettingManager.rankRich(this, type, 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { + handleResult(mRangeType, result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + //礼物榜 + public void getGiftRank(final int type) { + SettingManager.rankGift(this, type, 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { + handleResult(mRangeType, result); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + public void handleResult(int type, RankListBean result) { + List list = result.getList(); + NewRankBean myRank = result.getMyrank(); + if (null != myRank && 0 != myRank.getUser_id()) { +// mMyRankView.setVisibility(View.VISIBLE); + mMyName.setText(myRank.getNickname()); + mMyPhoto.setImageURI(ConstUrl.IMAGE_URL + myRank.getAvatar()); + mMyCost.setText(String.format("%.0f", myRank.getTotalMoney())); + mMyNumber.setText(myRank.getNo() + ""); + } else { +// mMyRankView.setVisibility(View.GONE); + } + if (1 == type) { //周榜 + mWeeklyFragment.notifyRankData(list); + mWeeklyFragment.getType(mRankType, mRangeType); + } else if (2 == type) { //月榜 + mMonthlyFragment.notifyRankData(list); + mMonthlyFragment.getType(mRankType, mRangeType); + } else if (3 == type) { //年榜 + mTotalFragment.notifyRankData(list); + mTotalFragment.getType(mRankType, mRangeType); + } + } + + @Override + public void onClick(View view) { + if (view == mMonthlyView) { + mMainViewPager.setCurrentItem(1, false); + } else if (view == mWeeklyView) { + mMainViewPager.setCurrentItem(0, false); + } else if (view == mTotalView) { + mMainViewPager.setCurrentItem(2, false); + } else if (view == mRlBack) { + finish(); + } else if (view == mTvSelect) { + mRankSelectDialog.show(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mRankSelectDialog && mRankSelectDialog.isShowing()) { + mRankSelectDialog.dismiss(); + } + } + + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/RankFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/RankFragment.java new file mode 100644 index 0000000..5f11c56 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/RankFragment.java @@ -0,0 +1,422 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.RankAdapter; +import com.fengliyan.tianlesue.model.settings.NewRankBean; +import com.fengliyan.tianlesue.model.settings.RankListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.MainPageActivity; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.facebook.drawee.view.SimpleDraweeView; + +import java.util.ArrayList; +import java.util.List; + +public class RankFragment extends Fragment { + private RankAdapter mRankAdpter; + private LoadMoreListView mRankListView; + private SimpleDraweeView mFirstPhoto; + private SimpleDraweeView mSecondPhoto; + private SimpleDraweeView mThirdPhoto; + private TextView mFirstName; + private TextView mSecondName; + private TextView mThirdName; + private TextView mFirstCost; + private TextView mSecondCost; + private TextView mThirdCost; + private List mRankDataList = new ArrayList<>(); + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState){ + View v = inflater.inflate(R.layout.fragment_daka_rank, container, false); + initView(v); + return v; + } + + private void initView(View v){ + mRankListView = v.findViewById(R.id.daka_rank_list_view); + mFirstPhoto = v.findViewById(R.id.daka_rank_first_photo); + mSecondPhoto = v.findViewById(R.id.daka_rank_second_photo); + mThirdPhoto = v.findViewById(R.id.daka_rank_third_photo); + mFirstName = v.findViewById(R.id.daka_rank_first_name); + mSecondName = v.findViewById(R.id.daka_rank_second_name); + mThirdName = v.findViewById(R.id.daka_rank_third_name); + mFirstCost = v.findViewById(R.id.daka_rank_first_cost); + mSecondCost = v.findViewById(R.id.daka_rank_second_cost); + mThirdCost = v.findViewById(R.id.daka_rank_third_cost); + mRankAdpter = new RankAdapter(getActivity()); + mRankAdpter.setRankBeans(mRankDataList); + mRankListView.setAdapter(mRankAdpter); + mRankListView.dimissEmptyView(); + mRankListView.colorLoadMoreViewByResId(R.drawable.shape_dake_rank_header); + mRankListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + } + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + int size = mRankDataList.size() + 3; + int lastPosition = mRankListView.getLastVisiblePosition() + 3; + + if(size != 0 && size % 10 == 0 && !mPageLoad + && lastPosition > size - 2){ +// getGenderUserInfo(mType, mPage); + if (mRankType == 0) { + getLoveRank(); + }else if (mRankType == 1) { //金币 + getWealthRank(); + }else if (mRankType == 2) { + getGiftRank(); + }else if (mRankType == 3) { + getConsumerRank(); + } + mPageLoad = true; + }else if(lastPosition <= size - 2){ + mPageLoad = false; + } + } + }); + mFirstPhoto.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (oneId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", oneId); + getActivity().startActivity(intent); + } + } + }); + mSecondPhoto.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (twoId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", twoId); + getActivity().startActivity(intent); + } + } + }); + mThirdPhoto.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (threeId != 0) { + Intent intent = new Intent(getActivity(), MainPageActivity.class); + intent.putExtra("userId", threeId); + getActivity().startActivity(intent); + } + } + }); + } + List rankBeans = new ArrayList<>(); + private boolean mPageLoad = false; + private int oneId; + private int twoId; + private int threeId; + + public void notifyRankData(List rankBeans){ + this.rankBeans = rankBeans; + if (rankBeans.size() == 1) { + final NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.GONE); + mSecondCost.setVisibility(View.GONE); + mSecondPhoto.setImageURI(""); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = 0; + threeId = 0; + + for (int i = 0; i < 1; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + }else if (rankBeans.size() == 2) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getTotalMoney()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.GONE); + mThirdCost.setVisibility(View.GONE); + mThirdPhoto.setImageURI(""); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = 0; + + for (int i = 0; i < 2; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + }else if (rankBeans.size() == 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getTotalMoney()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getTotalMoney()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + + }else if (rankBeans.size() > 3) { + NewRankBean rankBean = rankBeans.get(0); + mFirstName.setText(rankBean.getNickname()); + setTextMoney(mFirstCost, rankBean.getTotalMoney()); +// mFirstCost.setText(String.format("%.0f", rankBean.getTotalMoney())); + mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean.getAvatar()); + NewRankBean rankBean1 = rankBeans.get(1); + mSecondName.setText(rankBean1.getNickname()); + setTextMoney(mSecondCost, rankBean1.getTotalMoney()); +// mSecondCost.setText(String.format("%.0f", rankBean1.getTotalMoney())); + mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean1.getAvatar()); + NewRankBean rankBean2 = rankBeans.get(2); + mThirdName.setText(rankBean2.getNickname()); + setTextMoney(mThirdCost, rankBean2.getTotalMoney()); +// mThirdCost.setText(String.format("%.0f", rankBean2.getTotalMoney())); + mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + rankBean2.getAvatar()); + + mFirstName.setVisibility(View.VISIBLE); + mFirstCost.setVisibility(View.VISIBLE); + mFirstPhoto.setVisibility(View.VISIBLE); + + mSecondName.setVisibility(View.VISIBLE); + mSecondCost.setVisibility(View.VISIBLE); + mSecondPhoto.setVisibility(View.VISIBLE); + + mThirdName.setVisibility(View.VISIBLE); + mThirdCost.setVisibility(View.VISIBLE); + mThirdPhoto.setVisibility(View.VISIBLE); + + oneId = rankBean.getUser_id(); + twoId = rankBean1.getUser_id(); + threeId = rankBean2.getUser_id(); + + for (int i = 0; i < 3; i++) { + rankBeans.remove(0); + } + + mRankDataList.clear(); + mRankDataList.addAll(rankBeans); + mRankAdpter.notifyDataSetChanged(); + } + +// if(rankBeans.size() >= 1){ +// RankBean bean = rankBeans.remove(0); +// mFirstName.setText(bean.getNickname()); +// mFirstCost.setText(String.format("%.0f", bean.getTotalMoney())); +// mFirstPhoto.setImageURI(ConstUrl.IMAGE_URL + bean.getAvatar()); +// } +// +// if(rankBeans.size() >= 2){ +// RankBean bean = rankBeans.remove(0); +// mSecondName.setText(bean.getNickname()); +// mSecondCost.setText(String.format("%.0f", bean.getTotalMoney())); +// mSecondPhoto.setImageURI(ConstUrl.IMAGE_URL + bean.getAvatar()); +// } +// +// if(rankBeans.size() >= 3){ +// Log.d("nail","size==="); +// RankBean bean = rankBeans.remove(0); +// mThirdName.setText(bean.getNickname()); +// mThirdCost.setText(String.format("%.0f", bean.getTotalMoney())); +// mThirdPhoto.setImageURI(ConstUrl.IMAGE_URL + bean.getAvatar()); +// } + +// mRankDataList.clear(); +// mRankDataList.addAll(rankBeans); +// mRankAdpter.notifyDataSetChanged(); + } + + private int mRankType; //0 魅力榜 1金币榜 2礼物榜 //3消费榜 + private int mRangeType; //1 周榜 2 月榜 3 年榜 + private int page = 2; + + public void getType(int mRankType, int mRangeType) { + this.mRankType = mRankType; + this.mRangeType = mRangeType; + mPageLoad = false; + page = 2; + } + + /** + * 大于一万,用小数表示 + * @param view + * @param totalMoney + */ + private void setTextMoney(TextView view, double totalMoney) { + if (totalMoney >= 10000) { + double money = totalMoney / 10000; + view.setText(String.format("%.1f", money) + "万"); + }else { + view.setText(String.format("%.0f", totalMoney)); + } + } + + //消费榜 + public void getConsumerRank() { + SettingManager.rankWealth((BaseActivity) getActivity(), mRangeType, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(type, result); + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + page++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + //魅力榜 + public void getLoveRank() { + SettingManager.rankLove((BaseActivity) getActivity(), mRangeType, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(type, result); + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + page++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + //金币榜 + public void getWealthRank() { + SettingManager.rankRich((BaseActivity) getActivity(), mRangeType, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(mRangeType, result); + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + page++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + //礼物榜 + public void getGiftRank() { + SettingManager.rankGift((BaseActivity) getActivity(), mRangeType, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RankListBean result, String message) { +// handleResult(mRangeType, result); + mRankDataList.addAll(result.getList()); + mRankAdpter.notifyDataSetChanged(); + page++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/RealNameActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/RealNameActivity.java new file mode 100644 index 0000000..e60ba96 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/RealNameActivity.java @@ -0,0 +1,118 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.toast.MaleToast; + +public class RealNameActivity extends BaseActivity implements View.OnClickListener { + private EditText ed_name; + private EditText ed_id_num; + private TextView tv_commit; + + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + if (isCommitEnable()) { + tv_commit.setEnabled(true); + } else { + tv_commit.setEnabled(false); + } + } + }; + + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName("实名认证"); + setContentView(R.layout.activity_real_name); + initView(); + } + + private void initView() { + tv_commit = findViewById(R.id.tv_commit); + ed_id_num = findViewById(R.id.ed_id_num); + ed_name = findViewById(R.id.ed_name); + ed_id_num.addTextChangedListener(mTextWatcher); + ed_name.addTextChangedListener(mTextWatcher); + tv_commit.setOnClickListener(this); + } + + public boolean isCommitEnable() { + if (TextUtils.isEmpty(ed_id_num.getText().toString())) { + return false; + } + if (TextUtils.isEmpty(ed_name.getText().toString())) { + return false; + } + return true; + } + + public boolean checkIsEnable() { + if (TextUtils.isEmpty(ed_id_num.getText())) { + MaleToast.showMessage(RealNameActivity.this, "请输入身份证号"); + return false; + } + if (TextUtils.isEmpty(ed_name.getText())) { + MaleToast.showMessage(RealNameActivity.this, "请输入你的真实姓名"); + return false; + } + return true; + } + + public void CheckRealName() { + SettingManager.CheckRealName(RealNameActivity.this, ed_name.getText().toString(), ed_id_num.getText().toString(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + LoginBean loginBean = (LoginBean) StorageManager.getInstance(RealNameActivity.this).getBean("loginBean", LoginBean.class); + loginBean.getUserinfo().setReal_name_status(1); + StorageManager.getInstance(RealNameActivity.this).putBean("loginBean", loginBean); + UserManager.setUserInfo(loginBean.getUserinfo()); + MaleToast.showMessage(activity, tips); + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.tv_commit: + if (checkIsEnable()) { + CheckRealName(); + } + break; + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/SalesSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SalesSettingActivity.java new file mode 100644 index 0000000..50e8a18 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SalesSettingActivity.java @@ -0,0 +1,19 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +/** + * Created by abby on 2018/4/14. + */ + +public class SalesSettingActivity extends BaseActivity{ + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setTitleName("设置聊天价格"); + setContentView(R.layout.activity_sales_setting); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/SettingFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SettingFragment.java new file mode 100644 index 0000000..f289234 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SettingFragment.java @@ -0,0 +1,901 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Switch; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; + +import com.blankj.utilcode.util.GsonUtils; +import com.facebook.drawee.view.SimpleDraweeView; +import com.flyco.roundview.RoundLinearLayout; +import com.flyco.roundview.RoundTextView; +import com.fengliyan.device.DeviceManager; +import com.fengliyan.http.httprequest.HttpCallback; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.eventBus.BeAnchorEvent; +import com.fengliyan.tianlesue.controller.eventBus.RegisterInfoEvent; +import com.fengliyan.tianlesue.controller.eventBus.SocialToSettingEvent; +import com.fengliyan.tianlesue.controller.main.manager.MainManager; +import com.fengliyan.tianlesue.controller.settings.adapter.constant.SettingOptions; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.im.uikit.common.Constans; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.model.main.BannerBean; +import com.fengliyan.tianlesue.model.main.MainPageAnchorBean; +import com.fengliyan.tianlesue.model.settings.UserFrameBean; +import com.fengliyan.tianlesue.model.settings.UserHomeBean; +import com.fengliyan.tianlesue.model.settings.WalletIndexBean; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.utils.GlideImageLoader1; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.main.utils.JumpUtils; +import com.fengliyan.tianlesue.view.settings.dialog.FreeVipDialog; +import com.fengliyan.tianlesue.view.settings.greeting.GreetingSettingActivity; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.toast.MaleToast; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.youth.banner.Banner; +import com.youth.banner.listener.OnBannerListener; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +/** + * Created by abby on 2018/4/11. + */ + +public class SettingFragment extends Fragment implements View.OnClickListener { + public static int SETTING_SOCIAL_REQUEST = 105; + public static int SETTING_SOCIAL_CHANGE_RESULT = 214; + private ConstraintLayout rl_user_info; + private SimpleDraweeView user_head; + private SimpleDraweeView user_avatar_frame; + private SVGAImageView svga_image_view; + private TextView tv_nick_name; + private TextView tv_age; + private TextView tv_qingyu_id; + private ImageView iv_user_icon1; + private ImageView iv_user_icon2; + private ImageView iv_user_icon3; + private ImageView iv_user_icon4; + private LinearLayout ll_foucs; + private TextView tv_foucus_num; + private ConstraintLayout ll_fans; + private TextView tv_fans_num; + private RoundTextView rtv_new_fans_num; + private ConstraintLayout ll_scan; + private TextView tv_scan_num; + private RoundTextView rtv_new_scan_num; + private LinearLayout ll_foot; + private TextView tv_foot_num; + private ConstraintLayout cl_invite; + private ConstraintLayout cl_task; + private Banner image_banner; + + //男女生内容互换 + private ConstraintLayout cl_income; + private TextView tv_income; + private TextView tv_income_hint; + private TextView tv_income_num; + private TextView tv_recharge_num; + private ConstraintLayout cl_recharge; + private TextView tv_recharge; + private TextView tv_recharge_hint; + + private RoundLinearLayout ll_certification; + private LinearLayout lin_my_list1; + private LinearLayout lin_my_list2; + + private List mOptions1 = new ArrayList<>(); + private List mOptions2 = new ArrayList<>(); + private Disposable mDisponsable; + private int mVideoEnableFlag; + private int gender; + + private FreeVipDialog mFreeVipDialog; + private View mLlVip; + private View mLiVipGo; + private boolean isVip; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_setting, container, false); + initView(v); + initTitle(); +// getUserInfo(); +// getWalletIndex(); + + EventBus.getDefault().register(this); + return v; + } + + @Override + public void onHiddenChanged(boolean hidden) { + if (!hidden) { + initTitle(); + getUserInfo(); + // 审核模式隐藏邀请好友、每日任务 + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + cl_invite.setVisibility(View.GONE); + cl_task.setVisibility(View.GONE); + if (UserManager.getUserInfo().getGender() == 2) { + cl_recharge.setVisibility(View.GONE); + } else { + cl_income.setVisibility(View.GONE); + } + } else { +// cl_invite.setVisibility(View.VISIBLE); + cl_task.setVisibility(View.VISIBLE); +// cl_recharge.setVisibility(View.VISIBLE); +// cl_income.setVisibility(View.VISIBLE); + } + } + } + + @Override + public void onResume() { + super.onResume(); + getWalletIndex(); + getUserInfo(); + } + + private void initView(View v) { + rl_user_info = v.findViewById(R.id.rl_user_info); + user_avatar_frame = v.findViewById(R.id.user_avatar_frame); + svga_image_view = v.findViewById(R.id.svga_image_view); + user_head = v.findViewById(R.id.user_head); + tv_nick_name = v.findViewById(R.id.tv_nick_name); + tv_age = v.findViewById(R.id.tv_age); + tv_qingyu_id = v.findViewById(R.id.tv_qingyu_id); + iv_user_icon1 = v.findViewById(R.id.iv_user_icon1); + iv_user_icon2 = v.findViewById(R.id.iv_user_icon2); + iv_user_icon3 = v.findViewById(R.id.iv_user_icon3); + iv_user_icon4 = v.findViewById(R.id.iv_user_icon4); + ll_foucs = v.findViewById(R.id.ll_foucs); + tv_foucus_num = v.findViewById(R.id.tv_foucus_num); + ll_fans = v.findViewById(R.id.ll_fans); + tv_fans_num = v.findViewById(R.id.tv_fans_num); + rtv_new_fans_num = v.findViewById(R.id.rtv_new_fans_num); + ll_scan = v.findViewById(R.id.ll_scan); + tv_scan_num = v.findViewById(R.id.tv_scan_num); + rtv_new_scan_num = v.findViewById(R.id.rtv_new_scan_num); + ll_foot = v.findViewById(R.id.ll_foot); + tv_foot_num = v.findViewById(R.id.tv_foot_num); + cl_invite = v.findViewById(R.id.cl_invite); + cl_task = v.findViewById(R.id.cl_task); + image_banner = v.findViewById(R.id.image_banner); + + cl_income = v.findViewById(R.id.cl_income); + tv_income = v.findViewById(R.id.tv_income); + tv_income_hint = v.findViewById(R.id.tv_income_hint); + tv_income_num = v.findViewById(R.id.tv_income_num); + tv_recharge_num = v.findViewById(R.id.tv_recharge_num); + cl_recharge = v.findViewById(R.id.cl_recharge); + tv_recharge = v.findViewById(R.id.tv_recharge); + tv_recharge_hint = v.findViewById(R.id.tv_recharge_hint); + + ll_certification = v.findViewById(R.id.ll_certification); + lin_my_list1 = v.findViewById(R.id.lin_my_list1); + lin_my_list2 = v.findViewById(R.id.lin_my_list2); + + rl_user_info.setOnClickListener(this); + ll_foucs.setOnClickListener(this); + ll_fans.setOnClickListener(this); + ll_scan.setOnClickListener(this); + ll_foot.setOnClickListener(this); + cl_invite.setOnClickListener(this); + cl_task.setOnClickListener(this); + cl_income.setOnClickListener(this); + cl_recharge.setOnClickListener(this); + ll_certification.setOnClickListener(this); + UserManager.getInstance().registerUserInfoObserver(new Observer() { + @Override + public void onSubscribe(Disposable d) { + mDisponsable = d; + } + + @Override + public void onNext(BaseUserInfo userInfo) { + if (null == userInfo || 0 == userInfo.getUser_id()) { + return; + } + getUserInfo(); + getWalletIndex(); + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + + } + }); + } + + private void initTitle() { + ((BaseActivity) getActivity()).hideTitleBar(); + } + + private boolean isShowAd = false; + + public void getUserInfo() { + SettingManager.getHomeUser((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, UserHomeBean result, String message) { + save(result); + if (!isShowAd) { + EventBus.getDefault().post(new RegisterInfoEvent(result.getUserinfo().getNewer_win_status())); + isShowAd = true; + } + user_head.setImageURI(ConstUrl.IMAGE_URL + result.getUserinfo().getAvatar()); + tv_nick_name.setText(result.getUserinfo().getNickname()); + tv_age.setText(result.getUserinfo().getAge() + ""); + tv_qingyu_id.setText("用户号:" + result.getUserinfo().getUsercode()); + //1=超级会员 0=普通会员 2=没有会员 + if (0 == result.getUserinfo().getVip()) { + isVip = true; + iv_user_icon1.setVisibility(View.VISIBLE); + iv_user_icon2.setVisibility(View.GONE); + } else if (1 == result.getUserinfo().getVip()) { + isVip = true; + iv_user_icon1.setVisibility(View.GONE); + iv_user_icon2.setVisibility(View.VISIBLE); + } else { + isVip = false; + iv_user_icon1.setVisibility(View.GONE); + iv_user_icon2.setVisibility(View.GONE); + } + SPUtils.saveBoolean(getActivity(), ConsUser.USER_VIP, isVip); + SPUtils.saveString(getActivity(), ConsUser.HIDE_READ_MSG, result.getHide_read_msg()); + //0.无标识 1.真人标识 2.新人标识 + if (1 == result.getUserinfo().getMark()) { + iv_user_icon3.setVisibility(View.VISIBLE); + iv_user_icon3.setImageResource(R.drawable.setting_my_icon31); + } else if (2 == result.getUserinfo().getMark()) { + iv_user_icon3.setVisibility(View.VISIBLE); + iv_user_icon3.setImageResource(R.drawable.setting_my_icon3); + } else { + iv_user_icon3.setVisibility(View.GONE); + } + //1手机号为空 2存在手机号 + if (2 == result.getUserinfo().getIs_mobile()) { + iv_user_icon4.setVisibility(View.VISIBLE); + } else { + iv_user_icon4.setVisibility(View.GONE); + } + + tv_foucus_num.setText(result.getUsercount().getFollow_count() + ""); + tv_fans_num.setText(result.getUsercount().getFans_count() + ""); + if (0 != result.getUsercount().getNew_fans_count()) { + rtv_new_fans_num.setVisibility(View.VISIBLE); + rtv_new_fans_num.setText(result.getUsercount().getNew_fans_count() + ""); + } else { + rtv_new_fans_num.setVisibility(View.GONE); + } + tv_scan_num.setText(result.getUsercount().getVisitor_count()); + if (0 != result.getUsercount().getNew_visitor_count()) { + rtv_new_scan_num.setVisibility(View.VISIBLE); + rtv_new_scan_num.setText(result.getUsercount().getNew_visitor_count() + ""); + } else { + rtv_new_scan_num.setVisibility(View.GONE); + } + tv_foot_num.setText(result.getUsercount().getFootprint_count()); + if (result.getSwitchX() != null) { + mVideoEnableFlag = result.getSwitchX().getOpen_video_status(); + } + mOptions1.clear(); + mOptions2.clear(); + gender = result.getUserinfo().getGender(); + if (result.getUserinfo().getGender() == 2) { + if (result.getUserinfo().getAvatar_hide() == 0 && isVip) { + user_avatar_frame.setVisibility(View.VISIBLE); + user_avatar_frame.setImageResource(R.mipmap.privilege_avatar_border_man1); + } else { + user_avatar_frame.setVisibility(View.GONE); + } + //男 + ll_certification.setVisibility(View.GONE); + // tv_recharge_tag.setVisibility(View.VISIBLE); + // if (StorageManager.getInstance(activity).getInt(Constans.IS_FIRST_RECHARGE) == 0) { + // tv_recharge_tag.setText("首充豪礼"); + // } else { + // tv_recharge_tag.setText("充值加送"); + // } +// tv_age.setBackgroundResource(R.drawable.bg_btn_man); +// tv_age.setTextColor(ContextCompat.getColor(activity, R.color.color_001857)); + tv_age.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(activity, R.drawable.icon_man), null, null, null); +// tv_income.setText("金币充值"); +// tv_income_hint.setText("限时特惠"); +// tv_recharge.setText("我的收益"); +// tv_recharge_hint.setText("每日可提现"); + mOptions1.add(SettingOptions.CUSTOMER); + mOptions1.add(SettingOptions.MEMBER); + mOptions1.add(SettingOptions.DETAIL); + if (NoClearSPUtils.getInt(getContext(), ConsUser.TURNTABLE_COUPON_SWITCH) == 1) { + mOptions1.add(SettingOptions.ITEMS); + } + addOption(mOptions1, lin_my_list1); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 1 && SPUtils.getInt(getContext(), ConsUser.TYPE) != 2) { + mOptions2.add(SettingOptions.GUIDE); + } + mOptions2.add(SettingOptions.VIOLATION); + mOptions2.add(SettingOptions.BEAUTY); + mOptions2.add(SettingOptions.SETTING); + addOption(mOptions2, lin_my_list2); + cl_income.setVisibility(View.VISIBLE); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + cl_recharge.setVisibility(View.GONE); + cl_invite.setVisibility(View.GONE); + } else { + if (result.getUserinfo().getReal_name_status() == 0) { + cl_recharge.setVisibility(View.GONE); + cl_invite.setVisibility(View.GONE); + //0-未认证,1-已认证 + } else { + cl_invite.setVisibility(View.VISIBLE); + cl_recharge.setVisibility(View.VISIBLE); + } + } + } else { + //女 + if (result.getUserinfo().getAvatar_hide() == 0 && isVip) { + user_avatar_frame.setVisibility(View.VISIBLE); + user_avatar_frame.setImageResource(R.mipmap.privilege_avatar_border1); + } else { + user_avatar_frame.setVisibility(View.GONE); + } +// tv_age.setBackgroundResource(R.drawable.bg_btn_woman); +// tv_age.setTextColor(ContextCompat.getColor(activity, R.color.mainColors)); + // tv_recharge_tag.setVisibility(View.GONE); + tv_age.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(activity, R.drawable.icon_women), null, null, null); +// tv_income.setText("我的收益"); +// tv_income_hint.setText("每日可提现"); +// tv_recharge.setText("金币充值"); +// tv_recharge_hint.setText("限时特惠"); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + cl_recharge.setVisibility(View.GONE); + cl_invite.setVisibility(View.GONE); + } else { + if (result.getUserinfo().getIs_anchor() == 1 && result.getUserinfo().getIs_face_status() == 1) { + cl_recharge.setVisibility(View.VISIBLE); + cl_invite.setVisibility(View.VISIBLE); + //0-未认证,1-已认证 + } else { + cl_invite.setVisibility(View.GONE); + cl_recharge.setVisibility(View.GONE); + } + } + if (result.getUserinfo().getIs_anchor() == 1 && result.getUserinfo().getIs_face_status() == 1) { + //0-未认证,1-已认证 + ll_certification.setVisibility(View.GONE); +// mOptions1.add(SettingOptions.VIDEO); + mOptions1.add(SettingOptions.CONTRACT); + if (!"oppo".equals(DeviceManager.getInstance().getApplicationMarket()) + && StrU.equals("1", NoClearSPUtils.getString(getActivity(), ConsUser.WECHAT_STATUS))) { + mOptions1.add(SettingOptions.ADDWECHAT); + } + mOptions1.add(SettingOptions.HELLOW); + mOptions1.add(SettingOptions.BEAUTY); + mOptions1.add(SettingOptions.DETAIL); + addOption(mOptions1, lin_my_list1); + mOptions2.add(SettingOptions.GODDESSPRIVILEGE); + mOptions2.add(SettingOptions.MEMBER); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 1 && SPUtils.getInt(getContext(), ConsUser.TYPE) != 2) { + mOptions2.add(SettingOptions.GUIDE); + } + mOptions2.add(SettingOptions.CUSTOMER); + mOptions2.add(SettingOptions.VIOLATION); + mOptions2.add(SettingOptions.SETTING); + } else { + ll_certification.setVisibility(View.VISIBLE); + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 1 && SPUtils.getInt(getContext(), ConsUser.TYPE) != 2) { + mOptions1.add(SettingOptions.GUIDE); + } + mOptions1.add(SettingOptions.CUSTOMER); + mOptions1.add(SettingOptions.SETTING); + addOption(mOptions1, lin_my_list1); + mOptions2.add(SettingOptions.VIOLATION); + } + addOption(mOptions2, lin_my_list2); + } + + if (result.getUserinfo().getUser_frame() != null) { + SPUtils.saveString(getActivity(), ConsUser.MY_AVATAR_FRAME, GsonUtils.toJson(result.getUserinfo().getUser_frame())); + UserFrameBean bean = result.getUserinfo().getUser_frame(); + if (bean.getProfile_frame() != null) { + if (!StrU.isEmpty(bean.getProfile_frame().getEffect())) { + user_avatar_frame.setVisibility(View.GONE); + svga_image_view.setVisibility(View.VISIBLE); + showSVGA(bean.getProfile_frame().getEffect()); + } else { + if (!StrU.isEmpty(bean.getProfile_frame().getImg())) { + user_avatar_frame.setVisibility(View.VISIBLE); + user_avatar_frame.setImageURI(ConstUrl.IMAGE_URL + bean.getProfile_frame().getImg()); + svga_image_view.setVisibility(View.GONE); + } + } + } + + if (bean.getBubble_frame() != null) { + if (!StrU.isEmpty(bean.getBubble_frame().getImg())) { + String[] strings = bean.getBubble_frame().getImg().split("/"); + String path = strings[strings.length - 1]; + File pngFile = new File(ConstUrl.DEFAULT_PATH, path); + if (!pngFile.exists()) { + MainManager.downloadNewApp((BaseActivity) getActivity(), ConstUrl.IMAGE_URL + bean.getBubble_frame().getImg(), + ConstUrl.DEFAULT_PATH + "/" + path, + new HttpCallback() { + @Override + public void onFailure(int httpStatusCode, String message, Throwable throwable) { + } + + @Override + public void onSuccess(int httpStatusCode, String responseObject) { + } + + @Override + public void onProgress(long bytesCount, long contentLength, boolean done) { + } + }); + + } + } + } + } else { + SPUtils.saveString(getActivity(), ConsUser.MY_AVATAR_FRAME, ""); + } + + if (null != result.getBanner()) { + if (result.getBanner().size() > 0) { + List images = new ArrayList<>(); + for (int i = 0; i < result.getBanner().size(); i++) { + BannerBean bean = new BannerBean(); + bean.setImage(StrU.getResourcePath(result.getBanner().get(i).getImage(), activity)); + bean.setLink_url(result.getBanner().get(i).getLink_url()); + bean.setLink_type(result.getBanner().get(i).getLink_type()); + images.add(bean); + } + if (images.size() > 0) { + if (NoClearSPUtils.getInt(getContext(), Constans.MARKET_STATUS) == 0 || SPUtils.getInt(getContext(), ConsUser.TYPE) == 2) { + image_banner.setVisibility(View.GONE); + } else { + image_banner.setVisibility(View.VISIBLE); + } + image_banner.setImages(images) + .setImageLoader(new GlideImageLoader1()) + .setOnBannerListener(new OnBannerListener() { + @Override + public void OnBannerClick(int position) { + int size = images.size(); + if (size != 0) { + int i = position % size; + JumpUtils.jump(images.get(i).getLink_type(), images.get(i).getLink_url(), getContext()); + } + } + }) + .setDelayTime(3000) + .start(); + } else { + image_banner.setVisibility(View.GONE); + } + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void getWalletIndex() { + SettingManager.getWalletIndex((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WalletIndexBean result, String message) { + if (UserManager.getUserInfo().getGender() == 2) { + tv_income_num.setText(result.getAccount().getCoin() + ""); + tv_income_num.setVisibility(View.VISIBLE); + tv_recharge_num.setVisibility(View.GONE); + } else { + tv_income_num.setVisibility(View.GONE); + tv_recharge_num.setText(result.getAccount().getIncome_coin() + ""); + tv_recharge_num.setVisibility(View.VISIBLE); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void changeVideoStatus() { + MainManager.changeVideoStatus((BaseActivity) getActivity(), + (mVideoEnableFlag == 1 ? 0 : 1), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MainPageAnchorBean result, String message) { + mVideoEnableFlag = result.getOpen_video_status(); + addOption(mOptions1, lin_my_list1); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void showSVGA(String effect) { + SVGAParser mSVGAParser = SVGAParser.Companion.shareParser(); + mSVGAParser.init(requireActivity()); + try { + mSVGAParser.decodeFromURL(new URL(ConstUrl.IMAGE_URL + effect), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svga_image_view.setImageDrawable(drawable); + svga_image_view.startAnimation(); + } + + @Override + public void onError() { + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + /** + * 保存头像到本地 + * + * @param result + */ + private void save(UserHomeBean result) { + LoginBean loginBean = (LoginBean) StorageManager.getInstance(getActivity()).getBean("loginBean", LoginBean.class); + loginBean.getUserinfo().setAvatar(result.getUserinfo().getAvatar()); + loginBean.getUserinfo().setIs_anchor(result.getUserinfo().getIs_anchor()); + loginBean.getUserinfo().setIs_face_status(result.getUserinfo().getIs_face_status()); + loginBean.getUserinfo().setReal_name_status(result.getUserinfo().getReal_name_status()); + loginBean.getUserinfo().setMobile(result.getUserinfo().getMobile()); + loginBean.getUserinfo().setUser_type(result.getUserinfo().getUser_type()); + StorageManager.getInstance(getActivity()).putBean("loginBean", loginBean); + UserManager.setUserInfo(loginBean.getUserinfo()); + BaseApplication.getInstance().setUserInfo(loginBean.getUserinfo()); + } + + @Override + public void onClick(View view) { + Intent intent; + if (view.getId() == R.id.ll_certification) {//真人认证 + intent = new Intent(getActivity(), CertificationActivity.class); + startActivity(intent); + } else { + if (!BaseApplication.getInstance().showCertificationDialog(getContext())) { + switch (view.getId()) { + case R.id.rl_user_info://编辑资料 + intent = new Intent(getActivity(), InfoEditActivity.class); + startActivity(intent); + break; + case R.id.ll_foucs://关注 + intent = new Intent(getActivity(), SocialActivity.class); + intent.putExtra("socialType", 0); + getActivity().startActivityForResult(intent, SETTING_SOCIAL_REQUEST); + break; + case R.id.ll_fans://粉丝 + intent = new Intent(getActivity(), SocialActivity.class); + intent.putExtra("socialType", 1); + getActivity().startActivityForResult(intent, SETTING_SOCIAL_REQUEST); + break; + case R.id.ll_scan://来访 + intent = new Intent(getActivity(), SocialActivity.class); + intent.putExtra("socialType", 2); + startActivity(intent); + break; + case R.id.ll_foot://足迹 + intent = new Intent(getActivity(), SocialActivity.class); + intent.putExtra("socialType", 3); + startActivity(intent); + break; + case R.id.cl_invite://邀请 + intent = new Intent(getActivity(), InvitationActivity.class); + startActivity(intent); + break; + case R.id.cl_task://任务 + intent = new Intent(getActivity(), MissionActivity.class); + startActivity(intent); + break; + case R.id.cl_income: +// if (gender == 2) {//充值 + intent = new Intent(getActivity(), CaibeiRechargeActivity.class); +// } else {//提现 +// intent = new Intent(getActivity(), WithdrawActivity.class); +// } + startActivity(intent); + break; + case R.id.cl_recharge: +// if (gender == 2) {//提现 + intent = new Intent(getActivity(), WithdrawActivity.class); + startActivity(intent); +// } else {//充值 +// intent = new Intent(getActivity(), CaibeiRechargeActivity.class); +// startActivity(intent); +// } + break; + } + } + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + mDisponsable.dispose(); + EventBus.getDefault().unregister(this); + } + + //提交申请通过后,刷新界面 + public void onEventMainThread(BeAnchorEvent event) { + getUserInfo(); + } + + //监听从粉丝界面或者最近来访界面回来 + public void onEventMainThread(SocialToSettingEvent event) { + int type = event.getType(); + if (type == 1) { //粉丝 + rtv_new_fans_num.setVisibility(View.GONE); + } else if (type == 2) { //最近来访 + rtv_new_scan_num.setVisibility(View.GONE); + } + } + + private void addOption(List list, LinearLayout layout) { + layout.removeAllViews(); + LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + for (int i = 0; i < list.size(); i++) { + View view = inflater.inflate(R.layout.item_setting_option, null); + ImageView mLogo = view.findViewById(R.id.setting_option_logo); + TextView mName = view.findViewById(R.id.setting_option_name); + ImageView mArrow = view.findViewById(R.id.iv_option_arrow); + TextView mHint = view.findViewById(R.id.tv_option_hint); + Switch mSwitch = view.findViewById(R.id.st_option_switch); + SettingOptions options = list.get(i); + switch (options) { + case VIDEO: + mSwitch.setChecked(mVideoEnableFlag == 1); + mSwitch.setVisibility(View.VISIBLE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.GONE); + mLogo.setImageResource(R.drawable.icon_my_video); + mName.setText("视频聊天"); + mSwitch.setOnClickListener(v -> changeVideoStatus()); + break; + case CONTRACT: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.drawable.ic_my_certified); + mName.setText("价格设置"); + view.setOnClickListener(view12 -> { + Intent intent = new Intent(getActivity(), SkillSettingActivity.class); + startActivity(intent); + }); + break; + case GUIDE: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.drawable.ic_my_guide); + mName.setText("用户指南"); + view.setOnClickListener(view14 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + Intent intent = new Intent(getActivity(), UseCentreActivity.class); + startActivity(intent); + } + }); + break; + case CUSTOMER: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + if (gender == 2) { + mLogo.setImageResource(R.drawable.ic_my_service); + } else { + mLogo.setImageResource(R.drawable.ic_my_service1); + } + mName.setText("在线客服"); + view.setOnClickListener(view15 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + NimUIKit.startP2PSession(getActivity(), "4"); + } + }); + break; + case DETAIL: + if (gender == 2) { + mLogo.setImageResource(R.drawable.ic_my_certified); + } else { + mLogo.setImageResource(R.mipmap.ic_wd_items); + } + mName.setText("账单明细"); + view.setOnClickListener(view16 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + Intent intent = new Intent(getActivity(), BillActivity.class); + intent.putExtra("type", 0); + startActivity(intent); + } + }); + break; + case BEAUTY: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + if (gender == 2) { + mLogo.setImageResource(R.drawable.ic_my_beauty); + } else { + mLogo.setImageResource(R.drawable.ic_my_beauty1); + } + mName.setText("美颜设置"); + view.setOnClickListener(view17 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + Intent intent = new Intent(getActivity(), BeautySettingActivity.class); + startActivity(intent); + } + }); + break; + case MEMBER: + mSwitch.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + if (gender == 2) { + mLogo.setImageResource(R.drawable.ic_my_vip); + mHint.setVisibility(View.VISIBLE); + } else { + mLogo.setImageResource(R.drawable.ic_my_vip1); + mHint.setVisibility(View.GONE); + } + mName.setText("会员特权"); + view.setOnClickListener(v -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { +// LotteryNineDialog dialog = new LotteryNineDialog(ActivityUtils.getTopActivity(), null); +// dialog.show(); + Intent intent = new Intent(getActivity(), MemberActivity.class); + intent.putExtra("index", 0); + startActivity(intent); + } + }); + break; + case SETTING: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.drawable.ic_my_setting_new); + mName.setText("系统设置"); + view.setOnClickListener(view18 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + Intent intent = new Intent(getActivity(), SystemSettingActivity.class); + intent.putExtra("isVip", isVip); + startActivity(intent); + } + }); + break; + case GODDESSPRIVILEGE: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.mipmap.ic_my_ntequan); + mName.setText("女神特权"); + view.setOnClickListener(view19 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + startActivity(new Intent(getActivity(), GoddessPrivilegeActivity.class)); + } + }); + break; + case VIOLATION: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.mipmap.ic_wd_weigui); + mName.setText("违规公布"); + view.setOnClickListener(view110 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + Intent intent = new Intent(getActivity(), BaseWebViewActivity.class); + intent.putExtra("ClickUrl", ConstUrl.FORBID_LIST); + startActivity(intent); + } + }); + break; + case ADDWECHAT: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.mipmap.ic_wd_addwechat); + mName.setText("微信设置"); + view.setOnClickListener(view111 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + Intent intent = new Intent(getActivity(), WXAccountActivity.class); + startActivity(intent); + } + }); + break; + case HELLOW: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.mipmap.ic_wd_hellow_set); + mName.setText("招呼设置"); + view.setOnClickListener(view112 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + startActivity(new Intent(getActivity(), GreetingSettingActivity.class)); + } + }); + break; + case ITEMS: + mSwitch.setVisibility(View.GONE); + mHint.setVisibility(View.GONE); + mArrow.setVisibility(View.VISIBLE); + mLogo.setImageResource(R.mipmap.ic_wd_items1); + mName.setText("红包卡券"); + view.setOnClickListener(view113 -> { + if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { + startActivity(new Intent(getActivity(), MyItemsActivity.class)); + } + }); + break; + } + layout.addView(view); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/SkillPriceSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SkillPriceSettingActivity.java new file mode 100644 index 0000000..52a5624 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SkillPriceSettingActivity.java @@ -0,0 +1,96 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +import java.math.BigDecimal; + +public class SkillPriceSettingActivity extends BaseActivity implements View.OnClickListener { + private EditText mPriceInput; + private Button mConfirmButton; + private TextView tv_price_interval; + private int skillId; + private String mPrice; + private int priceType; + private String setType; + private int maxPrice; + private int minPrice; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_skill_price_setting); + setDefaultTitle(); + priceType = getIntent().getIntExtra("priceType", 0); + maxPrice = getIntent().getIntExtra("max", 1000); + minPrice = getIntent().getIntExtra("min", 100); + if (priceType == 0) { + setTitleName("语音价格设置"); + setType = "voice_price"; + } else { + setTitleName("视频价格设置"); + setType = "video_price"; + } + skillId = getIntent().getIntExtra("skillId", 0); + mPrice = getIntent().getStringExtra("price"); + initView(); + int price = getIntent().getIntExtra("oldPrice", 0); + if (price > 0) { + mPriceInput.setText(String.valueOf(price)); + } + tv_price_interval.setText("可设置价格区间:" + minPrice + "-" + maxPrice + "金币"); + } + + private void initView() { + mPriceInput = findViewById(R.id.skill_price_setting_input); + mConfirmButton = findViewById(R.id.skill_price_setting_button_confirm); + tv_price_interval = findViewById(R.id.tv_price_interval); + mConfirmButton.setOnClickListener(this); + } + + + @Override + public void onClick(View view) { + if (view == mConfirmButton) { + setSkillPrice(); + } + } + + private void setSkillPrice() { + if (TextUtils.isEmpty(mPriceInput.getText().toString()) || Integer.parseInt(mPriceInput.getText().toString()) < minPrice || Integer.parseInt(mPriceInput.getText().toString()) > maxPrice) { + MaleToast.showMessage(this, "请输入正确金额"); + return; + } + + BigDecimal decimal = new BigDecimal(mPriceInput.getText().toString()); + SettingManager.setSkillPriceNew(this, setType, decimal.toPlainString(), + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { + setResult(RESULT_OK); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + Toast.makeText(activity, tip, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + Toast.makeText(activity, "设置出错了", Toast.LENGTH_SHORT).show(); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/SkillSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SkillSettingActivity.java new file mode 100644 index 0000000..de91b5d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SkillSettingActivity.java @@ -0,0 +1,207 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.Toast; + +import com.fengliyan.device.DeviceManager; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.databinding.ActivitySkillSettingBinding; +import com.fengliyan.tianlesue.model.settings.ChatPriceBean; +import com.fengliyan.tianlesue.model.settings.WXAccountStatusBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +public class SkillSettingActivity extends BaseActivity { + ActivitySkillSettingBinding binding; + WXAccountStatusBean wxPriceBean; + private int chatPrice = 0; + private int voicePrice = 0; + private int open_voice_status; + private int open_video_status; + private int max_video_price; + private int min_video_price; + private int max_voice_price; + private int min_voice_price; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + binding = ActivitySkillSettingBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setDefaultTitle(); + setTitleName("价格设置"); + + String market = DeviceManager.getInstance().getApplicationMarket(); + if (market.equals("oppo") || StrU.equals("0", NoClearSPUtils.getString(this, ConsUser.WECHAT_STATUS))) { + binding.linWechatPrice.setVisibility(View.GONE); + binding.wechatLine.setVisibility(View.GONE); + } + + binding.linVoicePrice.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(SkillSettingActivity.this, SkillPriceSettingActivity.class); + intent.putExtra("oldPrice", voicePrice); + intent.putExtra("max", max_voice_price); + intent.putExtra("min", min_voice_price); + intent.putExtra("priceType", 0); + startActivity(intent); + } + }); + binding.linVideoPrice.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(SkillSettingActivity.this, SkillPriceSettingActivity.class); + intent.putExtra("oldPrice", chatPrice); + intent.putExtra("max", max_video_price); + intent.putExtra("min", min_video_price); + intent.putExtra("priceType", 1); + startActivity(intent); + } + }); + binding.linWechatPrice.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (wxPriceBean.getState() == 2) { + Intent intent = new Intent(SkillSettingActivity.this, WXPriceSettingActivity.class); +// intent.putExtra("bean",wxPriceBean); + startActivity(intent); + } else { + MaleToast.showMessage(SkillSettingActivity.this, "微信号通过审核后可设置"); + } + } + }); + + binding.stVoiceSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.isPressed()) { + if (isChecked) { + open_voice_status = 1; + } else { + open_voice_status = 0; + } + setStatus("open_voice_status", open_voice_status + ""); + } + } + }); + binding.stVideoSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.isPressed()) { + if (isChecked) { + open_video_status = 1; + } else { + open_video_status = 0; + } + setStatus("open_video_status", open_video_status + ""); + } + } + }); + + + } + + @Override + public void onResume() { + super.onResume(); + refresh(); + } + + void refresh() { + SettingManager.wechatAndQQCheck(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WXAccountStatusBean result, String tips) { + if (!TextUtils.isEmpty(result.getPrice())) { + wxPriceBean = result; + binding.tvWechatPrice.setText("解锁微信价格:" + result.getPrice() + "金币"); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + SettingManager.priceSetting(this, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, ChatPriceBean result, String tips) { + if (result != null) { + voicePrice = result.getVoice_price(); + chatPrice = result.getVideo_price(); + open_voice_status = result.getOpen_voice_status(); + open_video_status = result.getOpen_video_status(); + max_video_price = result.getMax_video_price(); + min_video_price = result.getMin_video_price(); + max_voice_price = result.getMax_voice_price(); + min_voice_price = result.getMin_voice_price(); + binding.tvVoicePrice.setText(voicePrice + "金币/分钟"); + binding.tvVideoPrice.setText(chatPrice + "金币/分钟"); + binding.stVoiceSwitch.setChecked(result.getOpen_voice_status() == 1); + binding.stVideoSwitch.setChecked(result.getOpen_video_status() == 1); + if (result.getPrice_desc_display() == 1 && result.getPrice_desc() != null) { + binding.tvPriceTitle.setVisibility(View.VISIBLE); + binding.tvPriceContent.setVisibility(View.VISIBLE); + binding.tvPriceTitle.setText(result.getPrice_desc().getTitle()); + binding.tvPriceContent.setText(result.getPrice_desc().getContent()); + } else { + binding.tvPriceTitle.setVisibility(View.GONE); + binding.tvPriceContent.setVisibility(View.GONE); + } + if (result.getWx_desc_display() == 1 && result.getWx_desc() != null) { + binding.tvWechatPriceTitle.setVisibility(View.VISIBLE); + binding.tvWechatPriceContent.setVisibility(View.VISIBLE); + binding.tvWechatPriceTitle.setText(result.getWx_desc().getTitle()); + binding.tvWechatPriceContent.setText(result.getWx_desc().getContent()); + } else { + binding.tvWechatPriceTitle.setVisibility(View.GONE); + binding.tvWechatPriceContent.setVisibility(View.GONE); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void setStatus(String setType, String value) { + SettingManager.setSkillPriceNew(this, setType, value, + new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + Toast.makeText(activity, tip, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + Toast.makeText(activity, "设置出错了", Toast.LENGTH_SHORT).show(); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/SocialActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SocialActivity.java new file mode 100644 index 0000000..5cae15b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SocialActivity.java @@ -0,0 +1,146 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.view.View; +import android.widget.AbsListView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.eventBus.SocialToSettingEvent; +import com.fengliyan.tianlesue.controller.settings.adapter.SocialAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.main.FollowResultBean; +import com.fengliyan.tianlesue.model.settings.SocialBean; +import com.fengliyan.tianlesue.model.settings.SocialListBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.refresh.LoadMoreListView; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.event.EventBus; + +public class SocialActivity extends BaseActivity implements View.OnClickListener { + private LoadMoreListView mSocialListView; + private SocialAdapter mSocialAdapter; + private List mSocialList = new ArrayList<>(); + private int mType; + private int mPage = 1; + private boolean mPageLoad; + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_social_list); + setDefaultTitle(); + mType = getIntent().getIntExtra("socialType", 0); + switch (mType){ + case 0: + setTitleName("关注"); + break; + case 1: + setTitleName("粉丝"); + break; + case 2: + setTitleName("最近来访"); + break; + case 3: + setTitleName("浏览足迹"); + break; + } + + EventBus.getDefault().post(new SocialToSettingEvent(mType)); + initView(); + getSocialData(mPage); + } + + private void initView(){ + mSocialListView = findViewById(R.id.social_list); + mSocialAdapter = new SocialAdapter(this); + mSocialAdapter.setSocialType(mType); + mSocialAdapter.setSocialBeans(mSocialList); + mSocialListView.setAdapter(mSocialAdapter); + mSocialAdapter.setOnButtonClickedListener(new SocialAdapter.OnButtonClickedListener() { + @Override + public void onCliked(int position) { + follow(mSocialList.get(position).getUserid() + "", position); + } + }); + + mSocialAdapter.setOnItemClickedListener(new SocialAdapter.OnItemClickedListener() { + @Override + public void onClicked(int position) { + + } + }); + + mSocialListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int i) { + + } + + @Override + public void onScroll(AbsListView absListView, int i, int i1, int i2) { + if(mSocialList.size() != 0 && mSocialList.size() % 10 == 0 && !mPageLoad + && mSocialListView.getLastVisiblePosition() > mSocialList.size() - 2){ + getSocialData(mPage); + mPageLoad = true; + }else if(mSocialListView.getLastVisiblePosition() <= mSocialList.size() - 2){ + mPageLoad = false; + } + } + }); + } + + private void getSocialData(int page){ + SettingManager.getSocialData(this, mType, page, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, SocialListBean result, String message) { +// mSocialList.clear(); + mSocialList.addAll(result.getList()); + mSocialAdapter.notifyDataSetChanged(); + mPage ++; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void follow(String uid, final int position){ + DynamicsManager.follow(this, uid, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, FollowResultBean result, String message) { + //getSocialData(); + mSocialList.get(position).setIs_follow(mSocialList.get(position) + .getIs_follow() == 1? 0 :1); + mSocialAdapter.notifyDataSetChanged(); + setResult(SettingFragment.SETTING_SOCIAL_CHANGE_RESULT); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(SocialActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(SocialActivity.this, "关注失败"); + } + }); + } + + @Override + public void onClick(View view) { + + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/SuperMemberFragment.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SuperMemberFragment.java new file mode 100644 index 0000000..2bbb741 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SuperMemberFragment.java @@ -0,0 +1,469 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.widget.NestedScrollView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.alipay.sdk.app.PayTask; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.tianlesue.controller.eventBus.PayEvent; +import com.fengliyan.tianlesue.controller.settings.adapter.GeneralOptionsRecyclerAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.MemberBean; +import com.fengliyan.tianlesue.model.settings.MemberInfoList; +import com.fengliyan.tianlesue.model.settings.MemberPrivilegesInfo; +import com.fengliyan.tianlesue.model.settings.PayBean; +import com.fengliyan.tianlesue.model.settings.PayConfigBean; +import com.fengliyan.tianlesue.model.settings.RechargeListBean; +import com.fengliyan.tianlesue.model.settings.WXPayTypeBean; +import com.fengliyan.tianlesue.model.settings.WeChatPayInfoBean; +import com.fengliyan.tianlesue.utils.PayUtils; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.PayWebViewActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.base.utils.view.MemberPayDialog; +import com.fengliyan.tianlesue.view.base.utils.view.MemberRechargeDialog; +import com.fengliyan.uikit.toast.MaleToast; +import com.sand.qzf.paytypesdk.base.CallBack; +import com.sand.qzf.paytypesdk.base.PayTypeSdk; +import com.sand.qzf.paytypesdk.base.Resp; +import com.tencent.mm.opensdk.modelpay.PayReq; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import de.greenrobot.event.EventBus; + +/** + * Created by zhangbin on 2019/5/14. + */ + +public class SuperMemberFragment extends Fragment implements View.OnClickListener { + + private NestedScrollView sv_super_member; + private TextView tv_member_time; + private ImageView iv_plus_tips; + private RecyclerView mOptionView; + private TextView tv_super_member_setting; + private RelativeLayout rl_super_member_bottom; + private TextView tv_super_member_price; + private TextView tv_super_member_sure; + private GeneralOptionsRecyclerAdapter mAdapter; + private int type = 5; + + private List mPrivileges = new ArrayList<>(); + + private boolean isVip; + private MemberPayDialog mPayDialog; + boolean isWXHF;//微信支付是否是走汇付的微信小程序 + private String ghOriId; + private int mini_program_type; + private OnScrollChange onScrollChange; + private int goodsId; + private String price; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_super_member, container, false); + EventBus.getDefault().register(this); + initView(v); + getWXPayType(); + return v; + } + + void getWXPayType() { + SettingManager.getWechatPaySite((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WXPayTypeBean result, String tips) { + isWXHF = result.getWechat_type() == 3; + ghOriId = result.getGh_ori_id(); + mini_program_type = result.getMini_program_type(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void initView(View v) { + sv_super_member = v.findViewById(R.id.sv_super_member); + tv_member_time = v.findViewById(R.id.tv_member_time); + iv_plus_tips = v.findViewById(R.id.iv_plus_tips); + tv_super_member_setting = v.findViewById(R.id.tv_super_member_setting); + rl_super_member_bottom = v.findViewById(R.id.rl_super_member_bottom); + tv_super_member_price = v.findViewById(R.id.tv_super_member_price); + tv_super_member_sure = v.findViewById(R.id.tv_super_member_sure); + mOptionView = v.findViewById(R.id.general_recycler_view); + mOptionView.setLayoutManager(new StaggeredGridLayoutManager(2, + StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + return false; + } + }); + + if (null == mAdapter) { + mAdapter = new GeneralOptionsRecyclerAdapter(getActivity(), 1); + mAdapter.setOptions(mPrivileges); + mOptionView.setAdapter(mAdapter); + mOptionView.setNestedScrollingEnabled(true); + } + + iv_plus_tips.setOnClickListener(this); + tv_super_member_sure.setOnClickListener(this); + tv_super_member_setting.setOnClickListener(this); + sv_super_member.setOnScrollChangeListener(new View.OnScrollChangeListener() { + @Override + public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { + if (onScrollChange != null) { + onScrollChange.scrollChange(scrollY); + } + } + }); + } + + private void getData(int type) { + SettingManager.getMemberInfo((BaseActivity) getActivity(), type, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, MemberBean result, String message) { + if (result.getInfo() != null) { + if (!TextUtils.isEmpty(result.getInfo().getExpire_date_new())) { + tv_member_time.setText("有效期至:" + result.getInfo().getExpire_date_new()); + isVip = true; + rl_super_member_bottom.setVisibility(View.GONE); + tv_super_member_setting.setVisibility(View.VISIBLE); + } else { + tv_member_time.setText("1000+用户已开通"); + isVip = false; + rl_super_member_bottom.setVisibility(View.VISIBLE); + tv_super_member_setting.setVisibility(View.GONE); + } + SPUtils.saveBoolean(getActivity(), ConsUser.USER_VIP, isVip); + if (SPUtils.getInt(getActivity(), ConsUser.GENDER) == 1) { + rl_super_member_bottom.setVisibility(View.VISIBLE); + tv_super_member_setting.setVisibility(View.GONE); + tv_super_member_sure.setText("邀请好友开通"); + } + + List list = result.getInfo().getList(); + if (list != null && list.size() > 0) { + price = (int) Double.parseDouble(list.get(0).getPrice()) + list.get(0).getExpires_title(); + tv_super_member_price.setText(price); + goodsId = list.get(0).getId(); + } + mAdapter.setVip_day_free_send(result.getInfo().getVip_day_free_send()); + } + + mPrivileges.clear(); + for (int i = 0; i < 7; i++) { + MemberPrivilegesInfo info = new MemberPrivilegesInfo(); + info.setId(i); + if (i == 0) { + info.setName("VISIBLE"); + } + mPrivileges.add(info); + } + + mAdapter.setOptions(mPrivileges); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View v) { + if (v == iv_plus_tips) {//会员充值加送提示 + getGoodsList(); + } else if (v == tv_super_member_sure) { + if (SPUtils.getInt(getActivity(), ConsUser.GENDER) == 1) {//女生邀请好友开通 + Intent intent = new Intent(getContext(), InvitationActivity.class); + startActivity(intent); + } else {//男生开通会员 + showPay(goodsId); + } + } else if (v == tv_super_member_setting) {//设置会员特权 + Intent intent = new Intent(getContext(), PrivilegeSettingActivity.class); + intent.putExtra("isVip", isVip); + startActivity(intent); + } + } + + private void getGoodsList() { + SettingManager.getRechargeInfo((BaseActivity) getActivity(), 6, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, RechargeListBean result, String message) { + if (result != null && result.getList() != null && result.getList().size() > 0) { + MemberRechargeDialog memberRechargeDialog = new MemberRechargeDialog(activity, result.getList()); + memberRechargeDialog.show(); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private String mSelectedPayMethod = "wechat"; //默认微信 + + /** + * 支付方式 + */ + private void showPay(final int id) { + SettingManager.payConfig((BaseActivity) getActivity(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayConfigBean result, String tips) { + mPayDialog = new MemberPayDialog(getActivity(), result, "SVIP " + price); + mPayDialog.setOnClickPayListener(new MemberPayDialog.OnClickPayListener() { + @Override + public void onClickPayListener(String selectedPayMethod) { + mSelectedPayMethod = selectedPayMethod; + confirmToPay(id); + mPayDialog.dismiss(); + } + }); + mPayDialog.show(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "获取支付信息失败"); + } + }); + } + + private String mOrderInfo; + + public static int SDK_PAY_FLAG = 102; + + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + if (msg.what == SDK_PAY_FLAG) { + getData(type); + } + } + }; + + private Runnable mPayRunnable = new Runnable() { + + @Override + public void run() { + PayTask alipay = new PayTask(getActivity()); + Map result = alipay.payV2(mOrderInfo, true); + String code = result.get("resultStatus"); + if (!TextUtils.isEmpty(code)) { + if ("9000".equals(code)) { + Message msg = new Message(); + msg.what = SDK_PAY_FLAG; + msg.obj = result; + mHandler.sendMessage(msg); + } + } + } + }; + + private void confirmToPay(int id) { + if (isWXHF && mSelectedPayMethod.equals("wechat")) { + PayUtils.wxminiPay(getActivity(), id, 1, ghOriId, mini_program_type); + return; + } + + SettingManager.payToRecharge((BaseActivity) getActivity(), mSelectedPayMethod, + id + "", 1, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, PayBean result, String message) { + if ("alipay".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + Thread payThread = new Thread(mPayRunnable); + payThread.start(); + } + } else if (result.getPay_platform_type() == 2) { + if (null != result.getPayinfo()) { + mOrderInfo = result.getPayinfo(); + PayUtils.ailWeb(mOrderInfo, getActivity()); + } + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(getContext(), PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + getActivity().startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(getActivity(), result.getPayinfo()); + } else { + PayTypeSdk.getInstance().cashierPay(getActivity(), result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + getData(type); + } + } + }); + } + } else if ("wechat".equals(mSelectedPayMethod)) { + if (result.getPay_platform_type() == 1) { + IWXAPI wxapi = WXAPIFactory.createWXAPI(getActivity(), Constant.WECHAT_APP_ID, false); + WeChatPayInfoBean wechatpayinfo = result.getWechatpayinfo(); + PayReq req = new PayReq(); + req.appId = Constant.WECHAT_APP_ID; + req.partnerId = wechatpayinfo.getMch_id(); //商户号 + req.prepayId = wechatpayinfo.getPrepay_id(); //预付款id + req.nonceStr = wechatpayinfo.getNonce_str(); + req.timeStamp = wechatpayinfo.getTimestamp() + ""; + req.packageValue = "Sign=WXPay"; //固定值 + req.sign = wechatpayinfo.getPaySign(); + boolean isWXAppInstalledAndSupported = wxapi.isWXAppInstalled(); + if (isWXAppInstalledAndSupported) { + wxapi.registerApp(Constant.WECHAT_APP_ID); + wxapi.sendReq(req); + } else { + MaleToast.showMessage(getActivity(), "未安装微信,不能支付"); + } + } else if (result.getPay_platform_type() == 2) { + PayTypeSdk.getInstance().cashierPay(getActivity(), result.getSandpayinfo().getCashierUrl(), new CallBack() { + @Override + public void onResult(Resp resp) { + if (resp.status.equals(Resp.SUCCESS) || resp.status.equals(Resp.FINISH)) { + } + } + }); + } else if (result.getPay_platform_type() == 4) { + Intent intent = new Intent(getActivity(), PayWebViewActivity.class); + intent.putExtra("ClickUrl", result.getKqPayInfo()); + getActivity().startActivity(intent); + } else if (result.getPay_platform_type() == 5) { + PayUtils.SFTPay(getActivity(), result.getPayinfo()); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void memberAuthority(final String type, final int value) { + SettingManager.memberAuthority((BaseActivity) getActivity(), type, value, new HttpUiCallBack() { + + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + getData(type); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + + if (null != mPayDialog && mPayDialog.isShowing()) { + mPayDialog.dismiss(); + } + } + + //微信支付成功后回调 + public void onEventMainThread(PayEvent event) { + int errCode = event.getErrCode(); + if (errCode == 0) { + MaleToast.showSuccessMsg(getActivity(), "充值成功"); + getData(type); + } else if (errCode == -2) { + MaleToast.showFailureMsg(getActivity(), "充值取消"); + } else { + MaleToast.showFailureMsg(getActivity(), "充值失败"); + } + } + + public void scrollTop() { + if (sv_super_member != null) { + sv_super_member.post(new Runnable() { + @Override + public void run() { + sv_super_member.smoothScrollTo(0, 0); + } + }); + } + } + + public interface OnScrollChange { + void scrollChange(int i); + } + + public void setOnScrollChange(OnScrollChange onScrollChange) { + this.onScrollChange = onScrollChange; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/SystemSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SystemSettingActivity.java new file mode 100644 index 0000000..4085854 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/SystemSettingActivity.java @@ -0,0 +1,168 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.storage.StorageManager; +import com.fengliyan.uikit.dialog.BaseMessageDialog; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.eventBus.KidEvent; +import com.fengliyan.tianlesue.controller.eventBus.UnReadCountEvent; +import com.fengliyan.tianlesue.controller.settings.manager.DataCleanManager; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.user.bean.BaseUserInfo; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.main.KidModelActivity; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; + +import de.greenrobot.event.EventBus; + +/** + * Created by abby on 2018/4/14. + */ + +public class SystemSettingActivity extends BaseActivity implements View.OnClickListener { + private View mBindPhoneView; + private View mBlackListView; + private View mCleanDataView; + private View mAboutView; + private View mLogoutView; + private TextView mBindPhoneTextView; + private TextView mCleanDataTextView; + private BaseMessageDialog mCleanDialog; + private BaseMessageDialog mCleanDialog1; + private View mClearChatView; + private View mRlMessageNotice; + private View mSystem_setting_guard; + private RelativeLayout system_setting_vip; + private boolean isVip; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setTitleName("设置"); + setContentView(R.layout.activity_system_setting); + EventBus.getDefault().register(this); + initView(); + isVip = getIntent().getBooleanExtra("isVip", false); + } + + private void initView() { + mBindPhoneView = findViewById(R.id.system_setting_bind_phone); + mSystem_setting_guard = findViewById(R.id.system_setting_guard); + mBlackListView = findViewById(R.id.system_setting_blacklist); + mClearChatView = findViewById(R.id.system_setting_clear_chat); + mCleanDataView = findViewById(R.id.system_setting_clean_data); + mAboutView = findViewById(R.id.system_setting_about); + mLogoutView = findViewById(R.id.system_setting_logout); + mRlMessageNotice = findViewById(R.id.rl_message_notice); + mBindPhoneTextView = findViewById(R.id.system_setting_bind_phone_text); + mCleanDataTextView = findViewById(R.id.system_setting_clean_data_text); + system_setting_vip = findViewById(R.id.system_setting_vip); + try { + mCleanDataTextView.setText(DataCleanManager.getTotalCacheSize(this)); + } catch (Exception e) { + + } + if (!UserManager.getUserInfo().isWomen()) { + system_setting_vip.setVisibility(View.VISIBLE); + } else { + system_setting_vip.setVisibility(View.GONE); + } + + mBindPhoneView.setOnClickListener(this); + mSystem_setting_guard.setOnClickListener(this); + mBlackListView.setOnClickListener(this); + mCleanDataView.setOnClickListener(this); + mAboutView.setOnClickListener(this); + mLogoutView.setOnClickListener(this); + mClearChatView.setOnClickListener(this); + mRlMessageNotice.setOnClickListener(this); + system_setting_vip.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (view == mBindPhoneView) { + Intent intent = new Intent(this, BindPhoneActivity.class); + startActivity(intent); + + } else if (view == mBlackListView) { + Intent intent = new Intent(this, BlackListActivity.class); + startActivity(intent); + } else if (view == mCleanDataView) { + mCleanDialog = new BaseMessageDialog.Builder(this).setMessage("是否删除私语数据?").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mCleanDialog.dismiss(); + } + }).setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mCleanDialog.dismiss(); + DataCleanManager.clearAllCache(SystemSettingActivity.this); + if (BaseApplication.getSimpleCache() != null) { + BaseApplication.getSimpleCache().release(); + } + mCleanDataTextView.setText("0M"); + } + }).build(); + mCleanDialog.show(); + } else if (view == mAboutView) { + Intent intent = new Intent(this, AboutActivity.class); + startActivity(intent); + } else if (view == mLogoutView) { + UserManager.getInstance().notifyUserInfoChanged(new BaseUserInfo()); + StorageManager.getInstance(this).clear(); +// SpeedWebSocket.getInstance().close(); + finish(); + } else if (view == mClearChatView) { + mCleanDialog1 = new BaseMessageDialog.Builder(this).setMessage("是否清空聊天记录?").setNegative("取消").setNegativeButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mCleanDialog1.dismiss(); + } + }).setPositiveButtonListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mCleanDialog1.dismiss(); + NIMClient.getService(MsgService.class).clearMsgDatabase(true); + EventBus.getDefault().post(new UnReadCountEvent(0, "")); + MaleToast.showMessage(SystemSettingActivity.this, "清空聊天记录成功"); + } + }).build(); + mCleanDialog1.show(); + } else if (view == mRlMessageNotice) { + Intent intent = new Intent(this, NewMessageNoticeActivity.class); + startActivity(intent); + } else if (view == mSystem_setting_guard) { + Intent intent = new Intent(this, KidModelActivity.class); + startActivity(intent); + } else if (view == system_setting_vip) { + Intent intent = new Intent(this, PrivilegeSettingActivity.class); + intent.putExtra("isVip", isVip); + startActivity(intent); + } + } + + //监听青少年模式 + public void onEventMainThread(KidEvent event) { + finish(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + if (mCleanDialog != null && mCleanDialog.isShowing()) { + mCleanDialog.dismiss(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/UseCentreActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/UseCentreActivity.java new file mode 100644 index 0000000..b286821 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/UseCentreActivity.java @@ -0,0 +1,59 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.utils.SPUtils; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.BaseWebViewActivity; + +/** + * Created by zhangbin on 2018/12/6. + */ + +public class UseCentreActivity extends BaseActivity implements View.OnClickListener { + + private View mRl_use; + private View mRl_guide; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTitleName("帮助中心"); + setContentView(R.layout.activity_use_centre); + + initView(); + } + + private void initView() { + mRl_use = findViewById(R.id.rl_use); + mRl_guide = findViewById(R.id.rl_guide); + + mRl_use.setOnClickListener(this); + mRl_guide.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (view == mRl_use) { + Intent intent = new Intent(UseCentreActivity.this, PhoneUseActivity.class); + startActivity(intent); + } else if (view == mRl_guide) { + Intent intent = new Intent(UseCentreActivity.this, BaseWebViewActivity.class); +// if (SPUtils.getInt(UseCentreActivity.this, ConsUser.TYPE) == 2) { +// intent.putExtra("ClickUrl", ConstUrl.HELP_URL_SPECIAL); +// } else { + if (SPUtils.getInt(UseCentreActivity.this, ConsUser.GENDER) == 2) { + intent.putExtra("ClickUrl", ConstUrl.HELP_URL_BOY); + } else { + intent.putExtra("ClickUrl", ConstUrl.HELP_URL_GIRL); + } +// } + startActivity(intent); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/VerifyCodeActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/VerifyCodeActivity.java new file mode 100644 index 0000000..dfec01f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/VerifyCodeActivity.java @@ -0,0 +1,140 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.register.manager.RegisterManager; +import com.fengliyan.tianlesue.model.login.bean.LoginBean; +import com.fengliyan.tianlesue.utils.PhoneCodeView; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.toast.MaleToast; + +public class VerifyCodeActivity extends BaseActivity implements View.OnClickListener { + private TextView tv_send_status; + private TextView tv_phone_num; + private PhoneCodeView pc_vcode; + private TextView tv_send_vcode; + private TextView tv_submit_vcode; + private String mobile; + private boolean isCodeSend; + private CountDownTimer mTimer; + + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName(""); + setContentView(R.layout.activity_verify_code); + initView(); + } + + private void initView() { + tv_send_status = findViewById(R.id.tv_send_status); + tv_phone_num = findViewById(R.id.tv_phone_num); + pc_vcode = findViewById(R.id.pc_vcode); + tv_send_vcode = findViewById(R.id.tv_send_vcode); + tv_submit_vcode = findViewById(R.id.tv_submit_vcode); + tv_send_vcode.setOnClickListener(this); + tv_submit_vcode.setOnClickListener(this); + tv_phone_num.setText("+86 " + getIntent().getStringExtra("mobile") + ",请在3分钟内输入"); + mobile = getIntent().getStringExtra("OriginMobile"); + pc_vcode.showSoftInput(); + pc_vcode.setSetSubmitListener(new PhoneCodeView.SetSubmitListener() { + @Override + public void setSubmitVisibility(boolean b) { + if (b && isCodeSend) { + tv_send_vcode.setVisibility(View.GONE); + tv_submit_vcode.setVisibility(View.VISIBLE); + } else { + tv_send_vcode.setVisibility(View.VISIBLE); + tv_submit_vcode.setVisibility(View.GONE); + } + } + }); + + mTimer = new CountDownTimer(60000, 1000) { + @Override + public void onTick(long l) { + tv_send_vcode.setText("重新获取(" + (l / 1000) + "s)"); + } + + //test + @Override + public void onFinish() { + tv_send_vcode.setEnabled(true); + isCodeSend = false; + tv_send_vcode.setText("获取验证码"); + } + }; + } + + //发送验证码 + public void sendCode(String number) { + RegisterManager.sendAuthCode(this, number, "", "before_change_mobile", new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, LoginBean result, String message) { + tv_send_status.setText("验证码已发送"); + mTimer.start(); + tv_send_vcode.setEnabled(false); + isCodeSend = true; + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + //校验验证码 + public void verifyCode(String code) { + RegisterManager.beforeChangeMobile(this, code, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String message) { + Intent intent = new Intent(activity, ChangeMobileActivity.class); + intent.putExtra("code", code); + startActivity(intent); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showFailureMsg(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + } + }); + } + + @Override + public void onClick(View view) { + if (view == tv_send_vcode) { + sendCode(mobile); + } else if (view == tv_submit_vcode) { + String code = pc_vcode.getPhoneCode(); + if (!TextUtils.isEmpty(code)) { + verifyCode(code); + } + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mTimer) { + mTimer.cancel(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXAccountActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXAccountActivity.java new file mode 100644 index 0000000..8b78f2c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXAccountActivity.java @@ -0,0 +1,233 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.Manifest; +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.fengliyan.base.base.AnyCallback; +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConstUrl; +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.databinding.ActivityWechataccountBinding; +import com.fengliyan.tianlesue.im.uikit.api.NimUIKit; +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean; +import com.fengliyan.tianlesue.model.settings.WXAccountStatusBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.tianlesue.view.settings.dialog.ConfirmWXDialog; +import com.fengliyan.tianlesue.view.settings.dialog.UpdateWXDialog; + +import java.io.File; +import java.util.List; + +public class WXAccountActivity extends BaseActivity { + private ActivityWechataccountBinding binding; + private MultiImageSelector mSelector; + public static final int REQUEST_CODE = 100; + private String imageUrl; + private String imagePath; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mSelector = MultiImageSelector.create().multi().count(1); + binding = ActivityWechataccountBinding.inflate(getLayoutInflater()); + binding.screenshotImageView.setImageResource(R.mipmap.ic_addwechatpic); + setContentView(binding.getRoot()); + setDefaultTitle(); + setTitleName("添加微信"); + + binding.exampleLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + example(); + } + }); + + refreshInfo(); + + } + void refreshInfo(){ + SettingManager.wechatAndQQCheck(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WXAccountStatusBean result, String tips) { + //审核状态:1=待审核 2=审核通过 3=审核不通过 + if (result.getState()==1){ + fill(result); + setRightCustomTextTitle("审核中", Color.parseColor("#999999"),14, + new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + }else if(result.getState()==2){ + fill(result); + setRightCustomTextTitle("去修改", Color.parseColor("#DF4138"),14, + new View.OnClickListener() { + @Override + public void onClick(View v) { +updateWX(); + } + }); + }else{ + binding.screenshotImageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + chooseImage(); + } + }); + setRightCustomTextTitle("提交", Color.parseColor("#333333"),14, + new View.OnClickListener() { + @Override + public void onClick(View v) { + submit(); + } + }); + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + void updateWX(){ + new UpdateWXDialog(this, new AnyCallback() { + @Override + public void callback(Boolean aBoolean) { + NimUIKit.startP2PSession(WXAccountActivity.this, "4"); + + } + }).show(); + } + void fill(WXAccountStatusBean bean){ + binding.idField.setEnabled(false); + binding.idField.setText(bean.getContent()); + binding.screenshotImageView.setImageURI(ConstUrl.IMAGE_URL+bean.getImage()); + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode,resultCode,data); + if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) { + if (data==null){ + return; + } + List albumList = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + if (albumList==null||albumList.size()==0){ + return; + } + String s = "file://" + albumList.get(0); + binding.screenshotImageView.setImageURI(s); + List list = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + imagePath = list.get(0); + uploadImage(imagePath); + + } + } + + void chooseImage(){ + XXPermissions.with(this).permission(Manifest.permission.READ_EXTERNAL_STORAGE) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all){ + mSelector.multi(); + mSelector.count(1); + mSelector.start(WXAccountActivity.this, REQUEST_CODE); + } + } + }); + + } + void example(){ + startActivity(new Intent(this,WXScreenShotExampleActivity.class)); + } + void submit(){ + String id = binding.idField.getText().toString(); + if (TextUtils.isEmpty(id)){ + MaleToast.showMessage(this,"请输入微信账号"); + return; + } + if (TextUtils.isEmpty(imageUrl)){ + MaleToast.showMessage(this,"请上传个人信息页面截图"); + return; + } + new ConfirmWXDialog(this, id, new AnyCallback() { + @Override + public void callback(Boolean aBoolean) { + SettingManager.wechat_qq_verify(WXAccountActivity.this, id, imageUrl, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + MaleToast.showSuccessMsg(activity,"提交成功"); + refreshInfo(); + binding.screenshotImageView.setClickable(false); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showSuccessMsg(activity,tip); + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showSuccessMsg(activity,"请重试"); + + } + }); + } + }).show(); + + + } + + public void uploadImage(String path) { + UploadFile[] uploadFiles = new UploadFile[1]; +// path = ImageUtils.compressImage(this, path, Constant.IMAGE_MEMORY_SIZE); + File file = new File(path); + UploadFile uploadFile = new UploadFile("file", file); + uploadFiles[0] = uploadFile; + ProgressDialog mProgressDialog = ProgressDialog.show(this, "请等待...", "图片正在上传中...", true, false); + DynamicsManager.uploadImage(this, uploadFiles, "wechat_qq", false, + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + imageUrl = result.get(0).getUrl(); + mProgressDialog.dismiss(); +// check(result.get(0).getUrl()); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + mProgressDialog.dismiss(); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "请重试"); + mProgressDialog.dismiss(); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXPriceSettingActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXPriceSettingActivity.java new file mode 100644 index 0000000..2eeed6e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXPriceSettingActivity.java @@ -0,0 +1,88 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; + +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.databinding.ActivityWxpricesettingBinding; +import com.fengliyan.tianlesue.model.settings.WXAccountStatusBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class WXPriceSettingActivity extends BaseActivity { + + ActivityWxpricesettingBinding binding; + WXAccountStatusBean bean; + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + bean = getIntent().getParcelableExtra("bean"); + binding = ActivityWxpricesettingBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + setDefaultTitle(); + setTitleName("解锁微信价格"); + binding.saveBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + submit(); + } + }); + if (bean!=null){ + binding.priceField.setText(bean.getPrice()); + if (!TextUtils.isEmpty(bean.getUp_price_time())){ + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + Date targetDate = format.parse(bean.getUp_price_time()); + if (System.currentTimeMillis()() { + + + @Override + public void onSuccess(BaseActivity activity, Object result, String tips) { + MaleToast.showMessage(activity,"设置成功"); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity,tip); + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity,e.getLocalizedMessage()+""); + + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXScreenShotExampleActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXScreenShotExampleActivity.java new file mode 100644 index 0000000..bf4e9bc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WXScreenShotExampleActivity.java @@ -0,0 +1,24 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.os.Bundle; +import android.view.View; + +import com.fengliyan.tianlesue.databinding.ActivityWxExampleShotBinding; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +public class WXScreenShotExampleActivity extends BaseActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ActivityWxExampleShotBinding binding = ActivityWxExampleShotBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + hideTitleBar(); + binding.root.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/WalletActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WalletActivity.java new file mode 100644 index 0000000..013481f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WalletActivity.java @@ -0,0 +1,115 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.model.settings.WalletIndexBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.title.Title; + +public class WalletActivity extends BaseActivity implements View.OnClickListener{ + public static final int REQUEST_RECHARGE = 110; + private TextView mWalletRecharge; + private TextView mWalletIncoming; + private Button mRechargeButton; + private Button mExchangeButton; + private Button mWithdrawButton; + private TextView mCaiBeiRecharge; + private TextView mCaiBeiImcome; + private View mCaiBeiRechargeButton; + @Override + public void onCreate(Bundle onSavedInstance){ + super.onCreate(onSavedInstance); + setContentView(R.layout.activity_wallet); + Title title = getCustomTitle(); + title.setTitleBackgroundResource(R.drawable.shape_backgound); + title.dismissBottomLine(); + title.findViewById(R.id.title_bg).getBackground().setAlpha(255); + ImageView left = findViewById(R.id.left_image); + left.setImageResource(R.drawable.ic_return_white); + title.setTitleWhite("私语钱包", "账单明细", null, new Title.OnFunctionalAreaClickListener() { + @Override + public void onLeftClick(View v) { + finish(); + } + + @Override + public void onRightClick(View v) { + Intent intent = new Intent(WalletActivity.this, BillActivity.class); + intent.putExtra("type", 0); + startActivity(intent); + } + }); + + initView(); + getWalletIndex(); + } + + private void initView(){ + mWalletRecharge = findViewById(R.id.wallet_charge_amount); + mWalletIncoming = findViewById(R.id.wallet_income_amount); + mRechargeButton = findViewById(R.id.wallet_recharge_button); + mExchangeButton = findViewById(R.id.wallet_exchange_button); + mWithdrawButton = findViewById(R.id.wallet_cash_button); + mCaiBeiRecharge = findViewById(R.id.wallet_caibei_recharge); + mCaiBeiImcome = findViewById(R.id.wallet_caibei_income); + mCaiBeiRechargeButton = findViewById(R.id.wallet_caibei_recharge_layout); + mRechargeButton.setOnClickListener(this); + mExchangeButton.setOnClickListener(this); + mWithdrawButton.setOnClickListener(this); + mCaiBeiRechargeButton.setOnClickListener(this); + } + + private void getWalletIndex(){ + SettingManager.getWalletIndex(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, WalletIndexBean result, String message) { + mWalletRecharge.setText(result.getAccount().getCoin() + ""); + mWalletIncoming.setText(result.getAccount().getIncome_coin() + ""); + mCaiBeiRecharge.setText(result.getAccount().getCoin() + ""); + mCaiBeiImcome.setText(result.getAccount().getIncome_coin() + ""); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + @Override + public void onClick(View view) { + if(view == mRechargeButton){ + Intent intent = new Intent(this, CaibeiRechargeActivity.class); + startActivityForResult(intent, REQUEST_RECHARGE); + }else if(view == mCaiBeiRechargeButton){ + Intent intent = new Intent(this, CaibeiRechargeActivity.class); + startActivityForResult(intent, REQUEST_RECHARGE); + }else if(view == mWithdrawButton){ + Intent intent = new Intent(this, WithdrawActivity.class); + startActivityForResult(intent, REQUEST_RECHARGE); + }else if(view == mExchangeButton){ + Intent intent = new Intent(this, ExchangeActivity.class); + startActivityForResult(intent, REQUEST_RECHARGE); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data){ + if(requestCode == REQUEST_RECHARGE){ + getWalletIndex(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/WithdrawActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WithdrawActivity.java new file mode 100644 index 0000000..24fdbc0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/WithdrawActivity.java @@ -0,0 +1,308 @@ +package com.fengliyan.tianlesue.view.settings; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.settings.adapter.RechargeAdapter; +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager; +import com.fengliyan.tianlesue.im.uikit.common.util.string.StringUtil; +import com.fengliyan.tianlesue.model.settings.BankInfoBean; +import com.fengliyan.tianlesue.model.settings.RechargeBean; +import com.fengliyan.tianlesue.model.settings.WithdrawInfoBean; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack; +import com.fengliyan.uikit.title.Title; +import com.fengliyan.uikit.toast.MaleToast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by abby on 2018/4/14. + */ + +public class WithdrawActivity extends BaseActivity implements View.OnClickListener { + + private int withDrawMoney = 0; + public static final int REQUEST_BIND_ACCOUNT = 211; + private View mAmountView; + + private Button mConfirmButton; + private double mIncome_money; + private int mMin_money; + private RecyclerView recyclerView; + private RechargeAdapter mRechargeAdapter; + private List mRechargeList = new ArrayList<>(); + private int mSelectedGoodPosition = 0; + private TextView accountLabel; + private TextView bindBtn; + private TextView coinLabel; + TextView bankBtn, aliBtn; + BankInfoBean bankBean; + WithdrawInfoBean withdrawInfoBean; + private TextView rateLabel; + + @Override + public void onCreate(Bundle onSavedInstance) { + super.onCreate(onSavedInstance); + setDefaultTitle(); + setTitleName("提现"); + Title title = getCustomTitle(); + title.findViewById(R.id.title_bg).setBackgroundColor(Color.WHITE); + title.dismissBottomLine(); + TextView rightText = title.findViewById(R.id.right_text); + rightText.setText("账单明细"); + rightText.setVisibility(View.VISIBLE); + rightText.setTextColor(Color.BLACK); + rightText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(WithdrawActivity.this, BillActivity.class)); + } + }); + setContentView(R.layout.activity_withdraw); + initView(); + getWithdrawInfo(); + } + + void typeChange(View view) { + aliBtn.setSelected(false); + bankBtn.setSelected(false); + view.setSelected(true); + changeWithDrawType(); + } + + private void initView() { + bankBtn = findViewById(R.id.bankBtn); + aliBtn = findViewById(R.id.aliBtn); + rateLabel = findViewById(R.id.rateLabel); + bankBtn.setSelected(true); + aliBtn.setSelected(false); + bankBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + typeChange(v); + } + }); + aliBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + typeChange(v); + } + }); + + + coinLabel = findViewById(R.id.coinLabel); + bindBtn = findViewById(R.id.bindBtn); + accountLabel = findViewById(R.id.accountLabel); + mAmountView = findViewById(R.id.withdraw_amount_layout); + recyclerView = findViewById(R.id.recyclerView); + mConfirmButton = findViewById(R.id.withdraw_confirm_button); + mConfirmButton.setOnClickListener(this); + mConfirmButton.setEnabled(false); + mAmountView.setOnClickListener(this); + bindBtn.setOnClickListener(this); + + + recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, + StaggeredGridLayoutManager.VERTICAL) { + @Override + public boolean canScrollVertically() { + return false; + } + }); + + + mRechargeAdapter = new RechargeAdapter(this); + mRechargeAdapter.setRechargeList(mRechargeList); + mRechargeAdapter.mSelectedPosition = 0; + mRechargeAdapter.setType(2); + mRechargeAdapter.setOnItemClickListener(new RechargeAdapter.OnItemClickListener() { + @Override + public void onItemClicked(View v, int position) { + + mRechargeAdapter.setSelectedPosition(position); + mRechargeAdapter.notifyDataSetChanged(); + mSelectedGoodPosition = position; + } + }); + recyclerView.setNestedScrollingEnabled(true); + recyclerView.setAdapter(mRechargeAdapter); + } + + private void getBankInfo() { + SettingManager.bank(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, BankInfoBean result, String tips) { + bankBean = result; + changeWithDrawType(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "获取银行卡信息失败"); + + } + }); + } + + void changeWithDrawType() { + if (withdrawInfoBean != null) { + if (aliBtn.isSelected()) { + rateLabel.setText(withdrawInfoBean.getWithdraw_alipay_rate()); + if (0 == withdrawInfoBean.getAlipay_status() || null == withdrawInfoBean.getAlipay_account() + || "".equals(withdrawInfoBean.getAlipay_account())) { + if (!TextUtils.isEmpty(withdrawInfoBean.getAlipay_account())) { + accountLabel.setText(withdrawInfoBean.getAlipay_account()); + accountLabel.setTextColor(Color.parseColor("#333333")); + bindBtn.setText("去修改"); + } else { + bindBtn.setText("去绑定"); + accountLabel.setText("你还未绑定支付宝"); + } + } else { + bindBtn.setText("去修改"); + accountLabel.setText(withdrawInfoBean.getAlipay_account()); + accountLabel.setTextColor(Color.parseColor("#333333")); + } + } else { + rateLabel.setText(withdrawInfoBean.getWithdraw_bank_rate()); + if (bankBean == null || TextUtils.isEmpty(bankBean.getCard_account())) { + bindBtn.setText("去绑定"); + accountLabel.setText("你还未绑定银行卡"); + } else { + bindBtn.setText("去修改"); + accountLabel.setTextColor(Color.parseColor("#333333")); + accountLabel.setText(StringUtil.handleBankCard(bankBean.getCard_account())); + } + } + } + } + + private void getWithdrawInfo() { + + SettingManager.getWithdrawInfo(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, final WithdrawInfoBean result, String message) { + withdrawInfoBean = result; + getBankInfo(); + + //提现金额显示的判断 + mMin_money = result.getMin_money(); + mIncome_money = result.getIncome_money(); + int coin = (int) (mIncome_money * 100); + coinLabel.setText(String.valueOf(coin)); + if (mIncome_money < mMin_money) { + withDrawMoney = 0; + mConfirmButton.setEnabled(false); + } else { + withDrawMoney = mMin_money; + mConfirmButton.setEnabled(true); + } + + + List mList = result.getList(); + mRechargeList.clear();//金额列表 + for (Integer i : mList) { + RechargeBean bean = new RechargeBean(); + bean.setId(i); + bean.setPrice(String.valueOf(i)); + bean.setAmount(i); + bean.setName(""); + bean.setRemark(""); + bean.setReward(0); + bean.setFirst_rechange_reward(0); + mRechargeList.add(bean); + } + mRechargeAdapter.notifyDataSetChanged(); + + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + private void withdraw() { + if (mRechargeList.size() == 0) { + return; + } + int selected = mRechargeList.get(mSelectedGoodPosition).getId(); + if (mIncome_money < selected) { + MaleToast.showMessage(this, "你的提现余额不足,请重新选择"); + return; + } + SettingManager.withdraw(this, selected + "", bankBtn.isSelected(), new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, String result, String message) { + MaleToast.showMessage(WithdrawActivity.this, "提现成功"); + finish(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(WithdrawActivity.this, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(WithdrawActivity.this, "提现失败"); + } + }); + } + + @Override + public void onClick(View view) { + if (bindBtn == view) { + if (aliBtn.isSelected()) { + Intent intent = new Intent(this, BindAliActivity.class); + startActivityForResult(intent, REQUEST_BIND_ACCOUNT); + } else { + Intent intent = new Intent(this, BindBankActivity.class); + startActivityForResult(intent, REQUEST_BIND_ACCOUNT); + } + } else if (mConfirmButton == view) { + withdraw(); + }/*else if (view == mAmountText) { + if (withDrawMoney == 0) { + MaleToast.showMessage(WithdrawActivity.this,"可提现余额小于最小可提现金额" + mMin_money); + }else { + mSelectiveDialog.show(); + } + }*/ + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onActivityResult(int request, int result, Intent data) { + super.onActivityResult(request, result, data); + if (request == REQUEST_BIND_ACCOUNT && result == RESULT_OK) { + getWithdrawInfo(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/BeAnchorDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/BeAnchorDialog.java new file mode 100644 index 0000000..e25b7d9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/BeAnchorDialog.java @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; + + +/** + * 真人认证未完善提示 + */ +public class BeAnchorDialog extends Dialog implements View.OnClickListener { + + + private OnClickListener mListener; + private TextView tTips; + private String sTips; + + public BeAnchorDialog(@NonNull Context context, OnClickListener listener) { + super(context); + mListener = listener; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_beanchor_confirm); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + } + + private void initView() { + tTips = findViewById(R.id.be_confirm_prompt); + findViewById(R.id.be_confirm_finsh).setOnClickListener(this); + findViewById(R.id.be_confirm_ok).setOnClickListener(this); + tTips.setText(sTips); + } + + + public void show(String tips) { + sTips = tips; + if (tTips != null) { + tTips.setText(sTips); + } + super.show(); + } + + @Override + public void onClick(View v) { + dismiss(); + if (v.getId() == R.id.be_confirm_finsh) { + mListener.onClick(); + } + } + + public interface OnClickListener { + void onClick(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/ChatCardRedPacketDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/ChatCardRedPacketDialog.java new file mode 100644 index 0000000..62a64d2 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/ChatCardRedPacketDialog.java @@ -0,0 +1,165 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.chat.ChatCardRewardBean; + + +public class ChatCardRedPacketDialog extends Dialog { + private Context mContext; + private FrameLayout rl_container; + private ConstraintLayout rl_status_open; + private RelativeLayout iv_status_no_open; + private TextView tv_coin; + private TextView tv_title; + private TextView tv_sub_title; + + private TextView tv_open_subtitle; + private TextView tv_type; + private TextView tv_tip; + private ImageView iv_reward; + private TextView tv_unit; + + private OnOpenListener openListener; + private boolean isOpen = false; + + private ChatCardRewardBean chatCardRewardBean; + + public void setOpenListener(OnOpenListener openListener) { + this.openListener = openListener; + } + + public ChatCardRedPacketDialog(@NonNull Context context) { + super(context); + mContext = context; + } + + public ChatCardRedPacketDialog(@NonNull Context context, ChatCardRewardBean bean) { + super(context); + mContext = context; + chatCardRewardBean = bean; + } + + public ChatCardRedPacketDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.layout_chat_card_red_packet); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams lp = window.getAttributes(); + //lp.width = (int) (DisplayUtil.getScreenWidth(mContext) * 0.8); +// lp.width = LinearLayout.LayoutParams.MATCH_PARENT; +// lp.height = LinearLayout.LayoutParams.MATCH_PARENT; +// window.setAttributes(lp); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + setCanceledOnTouchOutside(false); + } + + private void initView() { + ImageView iv_close = findViewById(R.id.iv_close); + rl_container = findViewById(R.id.rl_container); + rl_status_open = findViewById(R.id.rl_status_open); + iv_status_no_open = findViewById(R.id.iv_status_no_open); + tv_coin = findViewById(R.id.tv_coin); + tv_title = findViewById(R.id.tv_title); + tv_sub_title = findViewById(R.id.tv_sub_title); + iv_reward = findViewById(R.id.iv_reward); + tv_unit = findViewById(R.id.tv_unit); + + tv_open_subtitle = findViewById(R.id.tv_open_subtitle); + tv_type = findViewById(R.id.tv_type); + tv_tip = findViewById(R.id.tv_tip); + tv_title.setText("每日发送私信"); + + rl_container.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startAnim(); + } + }); + iv_close.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } + + public void startAnim() { + isOpen = true; + // rl_container.setBackground(mContext.getDrawable(R.drawable.ic_rw_hb_tangchu)); + rl_container.setCameraDistance(60000); + ObjectAnimator animator1 = ObjectAnimator.ofFloat(rl_container, "rotationY", 0, -90); + ObjectAnimator animator2 = ObjectAnimator.ofFloat(rl_container, "rotationY", 90, 0); + animator2.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + iv_status_no_open.setVisibility(View.GONE); + rl_status_open.setVisibility(View.VISIBLE); + iv_reward.setVisibility(View.VISIBLE); + + tv_type.setText("聊天券"); + tv_tip.setText("奖励已成功存入账户"); + if (!TextUtils.isEmpty(chatCardRewardBean.getGive_num())) { + tv_coin.setText(chatCardRewardBean.getGive_num()); + } + tv_unit.setText("张"); + iv_reward.setImageResource(R.drawable.ic_lt_jl); + tv_open_subtitle.setText("每日发送私信"); + tv_open_subtitle.setTextColor(ContextCompat.getColor(mContext, R.color.mainColors)); + tv_open_subtitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13); + } + + @Override + public void onAnimationEnd(Animator animation) { + + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.setDuration(400); + animatorSet.play(animator2).after(animator1); + animatorSet.start(); + } + + public interface OnOpenListener { + void open(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/ConfirmWXDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/ConfirmWXDialog.java new file mode 100644 index 0000000..7dfcfcb --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/ConfirmWXDialog.java @@ -0,0 +1,51 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; + +import com.fengliyan.base.base.AnyCallback; +import com.fengliyan.tianlesue.databinding.DialogConfirmwxBinding; + +public class ConfirmWXDialog extends Dialog { + private String wxId; + private AnyCallback callback; + public ConfirmWXDialog(@NonNull Context context,String wxId,AnyCallback callback) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.wxId = wxId; + this.callback = callback; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + DialogConfirmwxBinding binding = DialogConfirmwxBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + binding.wxIdLabel.setText(wxId); + binding.cancelBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + binding.confirmBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + callback.callback(false); + dismiss(); + } + }); +// Window window = this.getWindow(); +//// window.setGravity(Gravity.CENTER); +//// window.setBackgroundDrawableResource(android.R.color.transparent); + WindowManager windowManager = getWindow().getWindowManager(); + Display display = windowManager.getDefaultDisplay(); + WindowManager.LayoutParams lp = getWindow().getAttributes(); + lp.width = (int) (display.getWidth()*2/3); //设置宽度 + getWindow().setAttributes(lp); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/FreeVipDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/FreeVipDialog.java new file mode 100644 index 0000000..063c01c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/FreeVipDialog.java @@ -0,0 +1,45 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.settings.MemberActivity; + +/** + * ying 2020/12/17 + * Describe : + */ + +public class FreeVipDialog extends Dialog implements View.OnClickListener { + public FreeVipDialog(@NonNull Context context) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + setContentView(R.layout.dialog_free_vip); + findViewById(R.id.free_vip_go).setOnClickListener(this); + findViewById(R.id.free_vip_no).setOnClickListener(this); + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.free_vip_go) { + Intent intent = new Intent(getContext(), MemberActivity.class); + intent.putExtra("index", 0); + getContext().startActivity(intent); + } + dismiss(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/GirlAuthDialog.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/GirlAuthDialog.kt new file mode 100644 index 0000000..dbf7ddc --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/GirlAuthDialog.kt @@ -0,0 +1,67 @@ +package com.fengliyan.tianlesue.view.settings.dialog + +import android.app.Dialog +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.WindowManager +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.databinding.DialogGirlauthBinding +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.BaseApplication +import com.fengliyan.tianlesue.view.settings.CertificationActivity + +class GirlAuthDialog(context: Context) : Dialog(context, R.style.CommonDialog) { + var owner = context as BaseActivity + lateinit var binding: DialogGirlauthBinding + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DialogGirlauthBinding.inflate(layoutInflater) + setContentView(binding.root) + val layoutParams: WindowManager.LayoutParams = window!!.attributes + layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT + layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT + window!!.attributes = layoutParams + binding.closeBtn.setOnClickListener { + dismiss() + } + binding.tvClose.setOnClickListener { + dismiss() + } + binding.realBtn.setOnClickListener { + dismiss() + BaseApplication.getInstance().topActivity.startActivity( + Intent( + BaseApplication.getInstance().topActivity, + CertificationActivity::class.java + ) + ) + } + refresh() + } + + + fun refresh() { +// val loginBean = StorageManager.getInstance(BaseApplication.getInstance()).getBean("loginBean", LoginBean::class.java) as LoginBean +// if (loginBean.userinfo.is_anchor==1){ +// binding.realStatusLabel.text ="(已认证)" +// } +// SettingManager.getHomeUser(owner, object : HttpUiCallBack { +// override fun onSuccess(activity: BaseActivity?, result: UserHomeBean?, message: String?) { +// val info = result!!.userinfo.video_info +// if (info != null) { +// binding.coverStatusLabel.text = "(${info.statusString})" +// } +// val album_list = result.userinfo.album_list +// if (album_list!=null&& album_list.size>0){ +// binding.profileStatusLabel.text = "(已完善)" +// } +// +// } +// +// override fun onFailure(activity: BaseActivity, tip: String) {} +// override fun onException(activity: BaseActivity, e: Throwable) {} +// }) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/InviteSelectTypeDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/InviteSelectTypeDialog.java new file mode 100644 index 0000000..a12b36d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/InviteSelectTypeDialog.java @@ -0,0 +1,100 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; + + +public class InviteSelectTypeDialog extends Dialog { + private Context mContext; + private TextView tv_invite_type1, tv_invite_type2, tv_invite_type3; + + private OnSelectListener selectListener; + + + public void setSelectListener(OnSelectListener selectListener) { + this.selectListener = selectListener; + } + + public InviteSelectTypeDialog(@NonNull Context context) { + super(context); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.layout_invite_select_type); + initView(); + Window window = this.getWindow(); + if (window != null) { + window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + window.setGravity(Gravity.BOTTOM); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + + setCanceledOnTouchOutside(true); + } + + private void initView() { + tv_invite_type1 = findViewById(R.id.tv_invite_type1); + tv_invite_type2 = findViewById(R.id.tv_invite_type2); + tv_invite_type3 = findViewById(R.id.tv_invite_type3); + tv_invite_type1.setSelected(true); + tv_invite_type2.setSelected(false); + tv_invite_type3.setSelected(false); + + tv_invite_type1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + tv_invite_type1.setSelected(true); + tv_invite_type2.setSelected(false); + tv_invite_type3.setSelected(false); + if (selectListener != null) { + selectListener.selectType("1"); + } + dismiss(); + } + }); + tv_invite_type2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + tv_invite_type1.setSelected(false); + tv_invite_type2.setSelected(true); + tv_invite_type3.setSelected(false); + if (selectListener != null) { + selectListener.selectType("2"); + } + dismiss(); + } + }); + tv_invite_type3.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + tv_invite_type1.setSelected(false); + tv_invite_type2.setSelected(false); + tv_invite_type3.setSelected(true); + if (selectListener != null) { + selectListener.selectType("3"); + } + dismiss(); + } + }); + } + + public interface OnSelectListener { + //type 筛选类型1=充值金币/会员 2=通话收益 3=礼物收益 + void selectType(String type); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/NewcomerWelfareDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/NewcomerWelfareDialog.java new file mode 100644 index 0000000..63b054e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/NewcomerWelfareDialog.java @@ -0,0 +1,89 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.model.main.NewUserVideoCardBean; + +import java.util.List; + +/** + * 新人福利弹窗 + */ +public class NewcomerWelfareDialog extends Dialog implements View.OnClickListener { + + private TextView tv_welfare_title1; + private TextView tv_welfare_title2; + private TextView tv_welfare_title3; + private TextView tv_welfare_btn1; + private TextView tv_welfare_btn2; + private TextView tv_welfare_btn3; + private ImageView closeBtn; + private List beanList; + private Context context; + + public NewcomerWelfareDialog(@NonNull Context context, List beanList) { + super(context); + this.context = context; + this.beanList = beanList; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_newcomer_welfare); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + window.setBackgroundDrawableResource(android.R.color.transparent); + } + + private void initView() { + tv_welfare_title1 = findViewById(R.id.tv_welfare_title1); + tv_welfare_btn1 = findViewById(R.id.tv_welfare_btn1); + tv_welfare_title2 = findViewById(R.id.tv_welfare_title2); + tv_welfare_btn2 = findViewById(R.id.tv_welfare_btn2); + tv_welfare_title3 = findViewById(R.id.tv_welfare_title3); + tv_welfare_btn3 = findViewById(R.id.tv_welfare_btn3); + closeBtn = findViewById(R.id.closeBtn); + closeBtn.setOnClickListener(this); + + setData(tv_welfare_title1, tv_welfare_btn1, beanList.get(0)); + setData(tv_welfare_title2, tv_welfare_btn2, beanList.get(1)); + setData(tv_welfare_title3, tv_welfare_btn3, beanList.get(2)); + } + + private void setData(TextView titleTextView, TextView btnTextView, NewUserVideoCardBean bean) { + titleTextView.setText(bean.getTitle()); + btnTextView.setText(bean.getButton_text()); + if (TextUtils.equals("1", bean.getButton_status())) { + btnTextView.setBackgroundResource(R.drawable.btn_newcomer_bg); + btnTextView.setTextColor(ContextCompat.getColor(context, R.color.white)); + } else { + btnTextView.setBackgroundResource(R.drawable.btn_newcomer_bg1); + btnTextView.setTextColor(ContextCompat.getColor(context, R.color.three_text)); + } + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.closeBtn) { + dismiss(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/PosterDialog.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/PosterDialog.kt new file mode 100644 index 0000000..b2d4b7b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/PosterDialog.kt @@ -0,0 +1,89 @@ +package com.fengliyan.tianlesue.view.settings.dialog + +import android.annotation.SuppressLint +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import com.facebook.drawee.view.SimpleDraweeView +import com.fengliyan.base.base.AnyCallback +import com.fengliyan.uikit.mzbanner.holder.MZHolderCreator +import com.fengliyan.uikit.mzbanner.holder.MZViewHolder +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.ConstUrl +import com.fengliyan.tianlesue.databinding.DialogPosterBinding +class PosterDialog(context: Context,callback: AnyCallback,images: List,qrUrl:String) : Dialog(context, R.style.CommonDialog) { + + lateinit var binding:DialogPosterBinding + var callback:AnyCallback = callback + var images:List = images + var qrUrl:String = qrUrl + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DialogPosterBinding.inflate(layoutInflater) + setContentView(binding.root) + window!!.attributes.width = context.resources.displayMetrics.widthPixels*9/10 + window!!.attributes.height = context.resources.displayMetrics.heightPixels*3/5 + binding.closeBtn.setOnClickListener { + dismiss() + } + binding.cancelBtn.setOnClickListener { + dismiss() + } + binding.banner.pause() + + val posterBeans = images.map { + PosterBean(it,qrUrl) + } + + binding.banner.setPages(posterBeans,object : MZHolderCreator { + override fun createViewHolder(): BannerViewHolder { + return BannerViewHolder() + } + }) + + binding.banner.setIndicatorVisible(false) + + binding.saveBtn.setOnClickListener { + val index = binding.banner.currentIndex%images.size + val data = images[index] + callback.callback(PosterBean("${ConstUrl.IMAGE_URL}$data",qrUrl)) + dismiss() + } + + + + } + + + + + + data class PosterBean( + var poster: String, + var qr: String + ) + class BannerViewHolder : MZViewHolder { + lateinit var mImageView: SimpleDraweeView + lateinit var qrImageView: SimpleDraweeView + @SuppressLint("WrongViewCast") + override fun createView(context: Context): View { + // 返回页面布局 + val view: View = LayoutInflater.from(context).inflate(R.layout.item_poster, null) + mImageView = view.findViewById(R.id.banner_image) as SimpleDraweeView + qrImageView = view.findViewById(R.id.qrImageView) as SimpleDraweeView + + return view + } + + override fun onBind(context: Context, position: Int, data: PosterBean) { + mImageView.setImageURI("${ConstUrl.IMAGE_URL}${data.poster}") + qrImageView.setImageURI(data.qr) + // 数据绑定 +// mImageView.setImageResource(data) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/SelectTypeDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/SelectTypeDialog.java new file mode 100644 index 0000000..9fec18e --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/SelectTypeDialog.java @@ -0,0 +1,148 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.constant.ConsUser; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.utils.NoClearSPUtils; +import com.fengliyan.tianlesue.view.settings.RealNameActivity; +import com.fengliyan.uikit.dialog.BaseMessageDialog; + + +public class SelectTypeDialog extends Dialog { + private Context mContext; + private RelativeLayout rl_select1; + private RelativeLayout rl_select2; + private TextView tv_select_cancel; + private TextView tv_select_text1; + private TextView tv_select_text2; + private BaseMessageDialog baseMessageDialog; + + private OnSelectListener selectListener; + private boolean isOpen = false; + + public void setSelectListener(OnSelectListener selectListener) { + this.selectListener = selectListener; + } + + public SelectTypeDialog(@NonNull Context context) { + super(context); + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.layout_select_type); + initView(); + Window window = this.getWindow(); + if (window != null) { + window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + window.setGravity(Gravity.BOTTOM); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + + setCanceledOnTouchOutside(false); + } + + private void initView() { + rl_select1 = findViewById(R.id.rl_select1); + rl_select2 = findViewById(R.id.rl_select2); + tv_select_cancel = findViewById(R.id.tv_select_cancel); + tv_select_text1 = findViewById(R.id.tv_select_text1); + tv_select_text2 = findViewById(R.id.tv_select_text2); + + if (UserManager.getUserInfo().isWomen()) { + tv_select_text1.setText("视频通话(对方付费)"); + tv_select_text2.setText("语音通话(对方付费)"); + } else { + tv_select_text1.setText("视频通话"); + tv_select_text2.setText("语音通话"); + } + + rl_select1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (selectListener != null) { + if (isRealName()) { + return; + } + selectListener.selectVideo(); + } + dismiss(); + } + }); + rl_select2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (selectListener != null) { + if (isRealName()) { + return; + } + selectListener.selectVoice(); + } + dismiss(); + } + }); + tv_select_cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } + + /** + * 是否需要实名认证 + * + * @return + */ + private boolean isRealName() { + if (NoClearSPUtils.getInt(mContext, ConsUser.CHAT_REAL_NAME_SWITCH, 0) > 0 && UserManager.getUserInfo().getReal_name_status() == 0) { + if (baseMessageDialog == null) { + baseMessageDialog = new BaseMessageDialog.Builder(mContext).setMessage("通过实名认证才能使用该功能").setPositive("去实名").setNegative("取消").setNegativeButtonListener(new OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + baseMessageDialog.dismiss(); + } + }).setPositiveButtonListener(new OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(mContext, RealNameActivity.class); + mContext.startActivity(intent); + baseMessageDialog.dismiss(); + } + }).build(); + } + baseMessageDialog.show(); + return true; + } + return false; + } + + public void setSelectText(String text1, String text2) { + tv_select_text1.setText(text1); + tv_select_text2.setText(text2); + } + + public interface OnSelectListener { + void selectVideo(); + + void selectVoice(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/SpeedCallDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/SpeedCallDialog.java new file mode 100644 index 0000000..a72b00f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/SpeedCallDialog.java @@ -0,0 +1,172 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.util.Log; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.viewpager.widget.ViewPager; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.controller.user.manager.UserManager; +import com.fengliyan.tianlesue.model.main.SpeedInfoBean; +import com.fengliyan.tianlesue.utils.GlideImageLoader; +import com.fengliyan.tianlesue.utils.StrU; +import com.fengliyan.tianlesue.view.base.SpeedWebSocket; +import com.youth.banner.Banner; +import com.youth.banner.BannerConfig; + +import java.util.ArrayList; +import java.util.List; + + +public class SpeedCallDialog extends Dialog implements View.OnClickListener { + private static final String TAG = "SpeedCallDialog"; + private Activity mContext; + private CountDownTimer mCloseSpeedTimer; + + private Banner mIvSpeedAvatar; + private SimpleDraweeView iv_user_avatar; + private TextView tv_user_id; + private TextView tv_avatar_num; + private TextView mTvSpeedUserName; + private TextView mTvSpeedType; + private TextView mTvSpeedAgree; + private TextView mTvSpeedDisagree; + + private SpeedInfoBean.SpeedListBean mBean; + + public SpeedCallDialog(@NonNull Activity context, SpeedInfoBean.SpeedListBean bean) { + super(context); + mBean = bean; + mContext = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_speed_call); + Window window = this.getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + setCanceledOnTouchOutside(false); + initView(); + } + + private void initView() { + mIvSpeedAvatar = findViewById(R.id.iv_speed_avatar); + mTvSpeedUserName = findViewById(R.id.tv_speed_user_name); + tv_user_id = findViewById(R.id.tv_user_id); + tv_avatar_num = findViewById(R.id.tv_avatar_num); + mTvSpeedType = findViewById(R.id.tv_speed_type); + iv_user_avatar = findViewById(R.id.iv_user_avatar); + mTvSpeedAgree = findViewById(R.id.tv_speed_agree); + mTvSpeedDisagree = findViewById(R.id.tv_speed_disagree); + + List imagesList = new ArrayList<>(); + imagesList.add(StrU.getResourcePath(mBean.getAvatar(), mContext)); + if (mBean.getAlbum_list() != null && mBean.getAlbum_list().size() > 0) { + for (String url : mBean.getAlbum_list()) { + imagesList.add(StrU.getResourcePath(url, mContext)); + } + } + tv_avatar_num.setText("1/" + imagesList.size()); + mIvSpeedAvatar.setImages(imagesList) + .setImageLoader(new GlideImageLoader()) + .setDelayTime(3000) + .setBannerStyle(BannerConfig.NOT_INDICATOR) + .start() + .setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + tv_avatar_num.setText(position + 1 + "/" + imagesList.size()); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + iv_user_avatar.setImageURI(StrU.getResourcePath(mBean.getAvatar(), mContext)); + if (!StrU.isEmpty(mBean.getUsercode())) { + tv_user_id.setText("ID:" + mBean.getUsercode()); + } + + mTvSpeedUserName.setText(mBean.getNickname()); + if (UserManager.getUserInfo().isWomen()) { + if (mBean.getCall_type() == 3) { + mTvSpeedType.setText("本次语音速配收入(" + mBean.getCoin() + "金币/分钟)"); + } else { + mTvSpeedType.setText("本次视频速配收入(" + mBean.getCoin() + "金币/分钟)"); + } + } else { + if (mBean.getCall_type() == 3) { + mTvSpeedType.setText("本次语音速配消耗(" + mBean.getCoin() + "金币/分钟)"); + } else { + mTvSpeedType.setText("本次视频速配消耗(" + mBean.getCoin() + "金币/分钟)"); + } + } + + mTvSpeedAgree.setOnClickListener(this); + mTvSpeedDisagree.setOnClickListener(this); + mCloseSpeedTimer = new CountDownTimer(mBean.getCountdown() == 0 ? 10 : mBean.getCountdown() * 1000L, 1000) { + @Override + public void onTick(long l) { + Log.i(TAG, "onTick: l-------------->" + l); + mTvSpeedAgree.setText("接听 (" + l / 1000L + "s)"); + } + + @Override + public void onFinish() { + SpeedWebSocket.getInstance().sedText("{\"method\":\"refuseSpeed\",\"data\":{\"from_uid\":" + mBean.getUser_id() + ",\"call_type\":" + mBean.getCall_type() + ",\"source_id\":1}}"); + if (!mContext.isFinishing() && isShowing()) { + dismiss(); + } + } + }; + mCloseSpeedTimer.start(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_speed_agree: + SpeedWebSocket.getInstance().sedText("{\"method\":\"agreeSpeed\",\"data\":{\"from_uid\":" + mBean.getUser_id() + ",\"call_type\":" + mBean.getCall_type() + ",\"source_id\":1}}"); + if (mCloseSpeedTimer != null) { + mCloseSpeedTimer.cancel(); + } + dismiss(); + break; + case R.id.tv_speed_disagree: + if (mCloseSpeedTimer != null) { + mCloseSpeedTimer.cancel(); + } + SpeedWebSocket.getInstance().sedText("{\"method\":\"refuseSpeed\",\"data\":{\"from_uid\":" + mBean.getUser_id() + ",\"call_type\":" + mBean.getCall_type() + ",\"source_id\":1}}"); + dismiss(); + break; + } + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + SpeedWebSocket.getInstance().sedText("{\"method\":\"refuseSpeed\",\"data\":{\"from_uid\":" + mBean.getUser_id() + ",\"call_type\":" + mBean.getCall_type() + ",\"source_id\":1}}"); + if (mCloseSpeedTimer != null) { + mCloseSpeedTimer.cancel(); + } + dismiss(); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/UpdateWXDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/UpdateWXDialog.java new file mode 100644 index 0000000..e77a264 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/UpdateWXDialog.java @@ -0,0 +1,49 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; + +import com.fengliyan.base.base.AnyCallback; +import com.fengliyan.tianlesue.databinding.DialogUpdatewxBinding; + +public class UpdateWXDialog extends Dialog { + private String wxId; + private AnyCallback callback; + public UpdateWXDialog(@NonNull Context context, AnyCallback callback) { + super(context, com.fengliyan.uikit.R.style.SelectiveDialog); + this.callback = callback; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + DialogUpdatewxBinding binding = DialogUpdatewxBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + binding.cancelBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + callback.callback(false); + dismiss(); + } + }); + binding.confirmBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); +// Window window = this.getWindow(); +//// window.setGravity(Gravity.CENTER); +//// window.setBackgroundDrawableResource(android.R.color.transparent); + WindowManager windowManager = getWindow().getWindowManager(); + Display display = windowManager.getDefaultDisplay(); + WindowManager.LayoutParams lp = getWindow().getAttributes(); + lp.width = (int) (display.getWidth()*4/5); //设置宽度 + getWindow().setAttributes(lp); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/WQTipsDialog.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/WQTipsDialog.java new file mode 100644 index 0000000..b3faac9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/dialog/WQTipsDialog.java @@ -0,0 +1,54 @@ +package com.fengliyan.tianlesue.view.settings.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import com.fengliyan.tianlesue.R; + +/** + * 微信QQ提示填写 查看后有收益 + */ +public class WQTipsDialog extends Dialog implements View.OnClickListener { + + private String mTips; + private TextView mTtips; + + public WQTipsDialog(@NonNull Context context) { + super(context); + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_wq_tips); + initView(); + Window window = this.getWindow(); + window.setGravity(Gravity.CENTER); + window.setBackgroundDrawableResource(android.R.color.transparent); + } + + private void initView() { + findViewById(R.id.info_qq_examples_ok).setOnClickListener(this); + mTtips = findViewById(R.id.info_qq_examples_tip); + mTtips.setText(mTips); + } + + @Override + public void onClick(View v) { + dismiss(); + } + + public void show(String tips) { + mTips = tips; + if (mTtips!=null) mTtips.setText(mTips); + super.show(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/AddTextGrettingActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/AddTextGrettingActivity.kt new file mode 100644 index 0000000..1fc2a8b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/AddTextGrettingActivity.kt @@ -0,0 +1,85 @@ +package com.fengliyan.tianlesue.view.settings.greeting + +import android.os.Bundle +import android.text.Editable +import android.text.TextUtils +import android.text.TextWatcher +import com.fengliyan.uikit.toast.MaleToast +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager +import com.fengliyan.tianlesue.databinding.ActivityAddgreetBinding +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack + +class AddTextGrettingActivity : BaseActivity() { + lateinit var binding: ActivityAddgreetBinding + lateinit var watcher: TextWatcher + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityAddgreetBinding.inflate(layoutInflater) + setContentView(binding.root) + setDefaultTitle() + setTitleName("文本招呼") + watcher = object : TextWatcher { + override fun afterTextChanged(s: Editable?) { + } + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + if (binding.contentField.text.length > 30) { + binding.contentField.setText( + binding.contentField.text.toString().substring(0, 30) + ) + binding.countLabel.text = "30/30" + } else { + binding.countLabel.text = "${binding.contentField.text.toString().length}/30" + } + if (binding.contentField.text.length > 0) { + binding.addBtn.alpha = 1f; + binding.addBtn.isClickable = true + } else { + binding.addBtn.alpha = 0.5f; + binding.addBtn.isClickable = false + } + } + + } + binding.addBtn.alpha = 0.5f + binding.addBtn.isClickable = false + binding.contentField.addTextChangedListener(watcher) + binding.addBtn.setOnClickListener { + submit() + } + } + + fun submit() { + val str = binding.contentField.text.toString().trim() + if (!TextUtils.isEmpty(str)) { + SettingManager.addGreet(this, str, 0, object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + MaleToast.showMessage(activity, "添加成功") + finish() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity, tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity, "添加失败") + } + + }) + } else { + MaleToast.showMessage(this, "文字招呼内容不能为空") + } + } + + override fun onDestroy() { + super.onDestroy() + binding.countLabel.removeTextChangedListener(watcher) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/GreetingSettingActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/GreetingSettingActivity.kt new file mode 100644 index 0000000..2cbdaa0 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/GreetingSettingActivity.kt @@ -0,0 +1,27 @@ +package com.fengliyan.tianlesue.view.settings.greeting + +import android.content.Intent +import android.os.Bundle +import com.fengliyan.tianlesue.databinding.ActivityGreetingsettingBinding +import com.fengliyan.tianlesue.view.base.BaseActivity + +class GreetingSettingActivity:BaseActivity() { + lateinit var binding:ActivityGreetingsettingBinding; + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityGreetingsettingBinding.inflate(layoutInflater) + setContentView(binding.root) + setDefaultTitle() + setTitleName("招呼设置") + binding.textBtn.setOnClickListener { + startActivity(Intent(GreetingSettingActivity@this,TextGrettingListActivity::class.java)) + } + binding.voiceBtn.setOnClickListener { + startActivity(Intent(GreetingSettingActivity@this,VoiceGrettingListActivity::class.java)) + + } + binding.photoBtn.setOnClickListener { + startActivity(Intent(GreetingSettingActivity@this,PhotoGreetingListActivity::class.java)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/GreetingVoiceRecorderView.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/GreetingVoiceRecorderView.java new file mode 100644 index 0000000..d4360c8 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/GreetingVoiceRecorderView.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2022 NetEase, Inc. All rights reserved. + * Use of this source code is governed by a MIT license that can be found in the LICENSE file. + */ + +package com.fengliyan.tianlesue.view.settings.greeting; + +import android.app.Activity; +import android.content.Context; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import com.hjq.permissions.XXPermissions; +import com.fengliyan.uikit.toast.MaleToast; +import com.fengliyan.tianlesue.databinding.ViewGreetingVoicerecorderBinding; +import com.fengliyan.tianlesue.view.base.BaseApplication; +import com.fengliyan.tianlesue.view.diooto.tools.Utils; +import com.netease.nimlib.sdk.media.record.AudioRecorder; +import com.netease.nimlib.sdk.media.record.IAudioRecordCallback; +import com.netease.nimlib.sdk.media.record.RecordType; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + + +public class GreetingVoiceRecorderView extends FrameLayout { + private ViewGreetingVoicerecorderBinding mBinding; + private AudioRecorder mAudioRecorder; + private IAudioRecordCallback recordCallback; + private int maxDuration = 15*1000; + private int currentDuration = 1; + private boolean started = false; + private boolean recordFinish = false; + + Disposable disposable; + public GreetingVoiceRecorderView(@NonNull Context context) { + this(context, null); + } + + public GreetingVoiceRecorderView(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public GreetingVoiceRecorderView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + public void setSaveBtnListener( View.OnClickListener saveBtnListener){ + mBinding.finishBtn.setOnClickListener(saveBtnListener); + } + private void init() { + mBinding = ViewGreetingVoicerecorderBinding.inflate(LayoutInflater.from(getContext()), this, true); + mBinding.resetBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + reset(); + } + }); + mBinding.recordBtn.setOnTouchListener((v, event) -> { + if (!XXPermissions.isGranted(BaseApplication.getInstance().getTopActivity(),android.Manifest.permission.RECORD_AUDIO)){ + return true; + } + if (recordFinish){ + return true; + } + if (event.getAction() == MotionEvent.ACTION_DOWN) { +// mBinding.recordButtonIcon.setBackgroundResource(R.drawable.ic_record_pressed); + initAudioRecord(); + startAudioRecord(); + } else if (event.getAction() == MotionEvent.ACTION_CANCEL + || event.getAction() == MotionEvent.ACTION_UP) { +// mBinding.recordButtonIcon.setBackgroundResource(R.drawable.ic_record_normal); + endAudioRecord(isCancelled(v, event)); + } + return true; + }); + reset(); + } + public void recordFinish(){ + recordFinish = true; + mBinding.finishBtn.setVisibility(View.VISIBLE); + mBinding.resetBtn.setVisibility(View.VISIBLE); + if (currentDuration<3){ + MaleToast.showMessage(BaseApplication.getInstance(),"录音时间过短"); + reset(); + } + } + public void reset(){ + recordFinish = false; + mBinding.finishBtn.setVisibility(View.INVISIBLE); + mBinding.resetBtn.setVisibility(View.INVISIBLE); + mBinding.durationLabel.setText("0s"); + mBinding.progressView.setProgress(0); + } + public void setRecordCallback(IAudioRecordCallback callback) { + recordCallback = callback; + } + + private void initAudioRecord() { + if (mAudioRecorder == null) { + mAudioRecorder = new AudioRecorder(getContext(), RecordType.AAC, 15, recordCallback); + } + } + + private void startAudioRecord() { + if (getContext() instanceof Activity) { + ((Activity) getContext()).getWindow() + .setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + mAudioRecorder.startRecord(); + started = true; + recordFinish = false; + if (disposable!=null){ + disposable.dispose(); + } + mBinding.progressView.setProgress(50f); + disposable = Observable.interval(0,500, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(Long aLong) throws Exception { + float percent = (float) (aLong*500.0/maxDuration); + currentDuration = (int) (aLong/2); + mBinding.progressView.setProgress(percent*100); + mBinding.durationLabel.setText(currentDuration+"s"); + if (currentDuration>=maxDuration/1000){ + endAudioRecord(false); + } + } + }); + } + + private void endAudioRecord(boolean cancel) { + if (getContext() instanceof Activity) { + ((Activity) getContext()).getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + mAudioRecorder.completeRecord(false); + started = false; + if (disposable!=null){ + disposable.dispose(); + } + recordFinish(); + } + + @Override + protected void detachAllViewsFromParent() { + super.detachAllViewsFromParent(); + if (disposable!=null){ + disposable.dispose(); + } + if (mAudioRecorder!=null){ + mAudioRecorder.destroyAudioRecorder(); + } + } + + private void willCancelAudioRecord(boolean cancel) { + endAudioRecord(cancel); + + } + + private boolean isCancelled(View view, MotionEvent event) { + int[] location = new int[2]; + view.getLocationOnScreen(location); + int radius = Utils.dip2px(getContext(), 103) / 2; + return !isInCircle(event.getRawX(), event.getRawY(), location[0] + radius, location[1] + radius, radius); + } + + private boolean isInCircle(float x, float y, float cX, float cY, float radius) { + return radius * radius > (x - cX) * (x - cX) + (y - cY) * (y - cY); + } + + + + + + protected void recordReachMaxTime(int maxTime) { + mAudioRecorder.handleEndRecord(true, maxTime); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/PhotoGreetingListActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/PhotoGreetingListActivity.kt new file mode 100644 index 0000000..a4502c9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/PhotoGreetingListActivity.kt @@ -0,0 +1,224 @@ +package com.fengliyan.tianlesue.view.settings.greeting + +import android.app.Activity +import android.app.ProgressDialog +import android.content.Intent +import android.graphics.Rect +import android.os.Bundle +import android.os.Handler +import androidx.recyclerview.widget.RecyclerView +import android.view.Gravity +import android.view.View +import android.widget.PopupWindow +import androidx.recyclerview.widget.GridLayoutManager +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.facebook.drawee.view.SimpleDraweeView +import com.hjq.permissions.XXPermissions +import com.fengliyan.http.httprequest.UploadFile +import com.fengliyan.uikit.photopicker.MultiImageSelector +import com.fengliyan.uikit.toast.MaleToast +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.ConstUrl +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager +import com.fengliyan.tianlesue.databinding.ActivityPhotogrettinglistBinding +import com.fengliyan.tianlesue.databinding.PopwindowGreetingtipBinding +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean +import com.fengliyan.tianlesue.model.settings.GreetingBean +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.diooto.tools.Utils +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog +import com.fengliyan.tianlesue.view.settings.WXAccountActivity +import java.io.File + +class PhotoGreetingListActivity:BaseActivity() { + lateinit var binding: ActivityPhotogrettinglistBinding + lateinit var adapter: BaseQuickAdapter + var datas = mutableListOf() + lateinit var mSelector: MultiImageSelector + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityPhotogrettinglistBinding.inflate(layoutInflater) + mSelector = MultiImageSelector.create().multi().count(1) + + setContentView(binding.root) + setDefaultTitle() + setTitleName("招呼相册") + adapter = object : BaseQuickAdapter(R.layout.item_greeting_photo,datas){ + init { + addChildClickViewIds(R.id.delBtn) + } + override fun convert(helper: BaseViewHolder, item: GreetingBean.ListBean) { + val imageView = helper.getView(R.id.imageView); + imageView.setImageURI(ConstUrl.IMAGE_URL+item.title) + helper.setVisible(R.id.auditImageView,item.status==0) + } + } + adapter.setOnItemChildClickListener { adapter, view, position -> + if (view.id==R.id.delBtn){ + del(position) + } + } + binding.emptyLayout.visibility = View.INVISIBLE + binding.recyclerView.layoutManager = GridLayoutManager(this,3) + binding.recyclerView.addItemDecoration(object :RecyclerView.ItemDecoration(){ + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { + super.getItemOffsets(outRect, view, parent, state) + } + }) + binding.recyclerView.adapter = adapter + binding.addBtn.setOnClickListener { + XXPermissions.with(PhotoGreetingListActivity@this).permission(android.Manifest.permission.READ_EXTERNAL_STORAGE).request { permissions, all -> + if (all){ + chooseImage() + } + } + + } + Handler().postDelayed(object :Runnable{ + override fun run() { + showTipWindow() + } + },600) + refresh() + } + fun chooseImage() { + mSelector.multi() + mSelector.count(1) + mSelector.start(this, WXAccountActivity.REQUEST_CODE) + } + + fun showTipWindow(){ + if (isDestroyed){ + return + } + val popwindow = PopupWindow(this) + val windowBinding = PopwindowGreetingtipBinding.inflate(layoutInflater) + windowBinding.tipLabel.text = "小提示:招呼相册可以在打招呼中便捷使用;\n" + + "照片越多,越容易让Ta喜欢你哦~" + val popView =windowBinding.root + popwindow.isOutsideTouchable = true + popwindow.setBackgroundDrawable(null) + popwindow.contentView = popView + popwindow.showAtLocation(binding.addBtn, Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM, + 0, Utils.dip2px(this,110f)) + } + fun del(position:Int){ + val dialog = CustomAlertDialog(this) + dialog.hideTitle(true) + dialog.setLeftBtnText("取消") + dialog.setRightBtnText("确认") + dialog.setContent("确定删除这张照片吗?") + dialog.setRightOnClickListener { + SettingManager.delGreet(PhotoGreetingListActivity@this,datas[position].id, object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + datas.removeAt(position) + adapter.notifyDataSetChanged() + refreshEmptyLabel() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"删除失败") + } + + }) + } + dialog.show() + } + + + fun refreshEmptyLabel(){ + if (datas.size>0){ + binding.emptyLayout.visibility = View.INVISIBLE + }else{ + binding.emptyLayout.visibility = View.VISIBLE + } + } + fun refresh(){ + SettingManager.greetingList(this,2,object: HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: GreetingBean, tips: String?) { + datas.clear() + datas.addAll(result.list) + adapter.notifyDataSetChanged() + refreshEmptyLabel() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + } + }); + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == WXAccountActivity.REQUEST_CODE && resultCode == Activity.RESULT_OK) { + if (data==null){ + return + } + val list: List? = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT) + list?.let { + if (it.size >0){ + val imagePath = it[0] + uploadImage(imagePath) + } + } + } + } + fun uploadImage(path: String?) { + val uploadFiles = arrayOfNulls(1) + // path = ImageUtils.compressImage(this, path, Constant.IMAGE_MEMORY_SIZE); + val file = File(path) + val uploadFile = UploadFile("file", file) + uploadFiles[0] = uploadFile +// 上传类型 audit 认证 album 相册 dynamic 动态 feedback 反馈 report 举报 wechat_qq 微信/QQ审核 mp4 视频 mp4 视频 charge 付费 + val mProgressDialog = ProgressDialog.show(this, "请等待...", "图片正在上传中...", true, false) + DynamicsManager.uploadImageNew(this, uploadFiles, "greet", false, + object : HttpUiCallBack { + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(activity, tip) + mProgressDialog.dismiss() + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(activity, "请重试") + mProgressDialog.dismiss() + } + + override fun onSuccess(activity: BaseActivity?, result: UploadImageBean?, tips: String?) { + mProgressDialog.dismiss() + var str: String? = result?.img_id + str?.let { + submit(it) + } + + } + }) + } + fun submit(str:String){ + SettingManager.addGreet(this,str,2,object:HttpUiCallBack{ + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + MaleToast.showMessage(activity,"添加成功") + refresh() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"添加失败") + } + + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/TextGrettingListActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/TextGrettingListActivity.kt new file mode 100644 index 0000000..952f803 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/TextGrettingListActivity.kt @@ -0,0 +1,135 @@ +package com.fengliyan.tianlesue.view.settings.greeting + +import android.content.Intent +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.view.Gravity +import android.view.View +import android.widget.ImageView +import android.widget.PopupWindow +import androidx.recyclerview.widget.LinearLayoutManager +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.fengliyan.uikit.toast.MaleToast +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager +import com.fengliyan.tianlesue.databinding.ActivityTextgrettinglistBinding +import com.fengliyan.tianlesue.model.settings.GreetingBean +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.diooto.tools.Utils +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog + +class TextGrettingListActivity :BaseActivity(){ + + lateinit var binding:ActivityTextgrettinglistBinding + lateinit var adapter:BaseQuickAdapter + var datas = mutableListOf() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityTextgrettinglistBinding.inflate(layoutInflater) + setContentView(binding.root) + setDefaultTitle() + setTitleName("文字招呼") + adapter = object :BaseQuickAdapter(R.layout.item_greeting_text,datas){ + override fun convert(helper: BaseViewHolder, item: GreetingBean.ListBean) { + helper.setText(R.id.textLabel,item.title) + helper.getView(R.id.delBtn).setOnClickListener { + del(helper.adapterPosition) + } + if (item.status==0){ + helper.setVisible(R.id.auditNameLabel,true); + helper.setVisible(R.id.delBtn,false) + helper.setBackgroundColor(R.id.root, Color.parseColor("#D9D9D9")) + }else{ + helper.setVisible(R.id.auditNameLabel,false); + helper.setBackgroundColor(R.id.root, Color.parseColor("#ffffff")) + helper.setVisible(R.id.delBtn,true) + } + } + } + binding.emptyLabel.visibility = View.INVISIBLE + binding.recyclerView.layoutManager = LinearLayoutManager(this) + binding.recyclerView.adapter = adapter + binding.addBtn.setOnClickListener { + startActivity(Intent(TextGrettingListActivity@this,AddTextGrettingActivity::class.java)) + } + Handler().postDelayed(object :Runnable{ + override fun run() { + showTipWindow() + } + },600) + } + + + fun showTipWindow(){ + if (isDestroyed){ + return + } + val popwindow = PopupWindow(this) + val popView = layoutInflater.inflate(R.layout.popwindow_greetingtip,null) + popwindow.isOutsideTouchable = true + popwindow.setBackgroundDrawable(null) + popwindow.contentView = popView + popwindow.showAtLocation(binding.addBtn,Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM, + 0,Utils.dip2px(this,110f)) + } + fun del(position:Int){ + val dialog = CustomAlertDialog(this) +dialog.hideTitle(true) + dialog.setLeftBtnText("取消") + dialog.setRightBtnText("确认") + dialog.setContent("确定要删除这条文字招呼吗?") + dialog.setRightOnClickListener { + SettingManager.delGreet(TextGrettingListActivity@this,datas[position].id, object :HttpUiCallBack{ + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + datas.removeAt(position) + adapter.notifyDataSetChanged() + refreshEmptyLabel() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"删除失败") + } + + }) + } + dialog.show() + } + + override fun onResume() { + super.onResume() + refresh() + + } + fun refreshEmptyLabel(){ + if (datas.size>0){ + binding.emptyLabel.visibility = View.INVISIBLE + }else{ + binding.emptyLabel.visibility = View.VISIBLE + } + } + fun refresh(){ + SettingManager.greetingList(this,0,object:HttpUiCallBack{ + override fun onSuccess(activity: BaseActivity?, result: GreetingBean, tips: String?) { + datas.clear() + datas.addAll(result.list) + adapter.notifyDataSetChanged() + refreshEmptyLabel() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + } + }); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/VoiceGrettingListActivity.kt b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/VoiceGrettingListActivity.kt new file mode 100644 index 0000000..2cd2b8c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/greeting/VoiceGrettingListActivity.kt @@ -0,0 +1,327 @@ +package com.fengliyan.tianlesue.view.settings.greeting + +import android.Manifest +import android.app.ProgressDialog +import android.net.Uri +import android.os.Bundle +import android.os.Handler +import android.text.TextUtils +import android.view.Gravity +import android.view.View +import android.widget.PopupWindow +import androidx.recyclerview.widget.LinearLayoutManager +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.hjq.permissions.OnPermissionCallback +import com.hjq.permissions.XXPermissions +import com.fengliyan.base.base.permission.PermissionDialog +import com.fengliyan.http.httprequest.HttpCallback +import com.fengliyan.http.httprequest.UploadFile +import com.fengliyan.tianlesue.R +import com.fengliyan.tianlesue.controller.constant.ConstUrl +import com.fengliyan.tianlesue.controller.dynamics.manager.DynamicsManager +import com.fengliyan.tianlesue.controller.settings.manager.SettingManager +import com.fengliyan.tianlesue.databinding.ActivityVoicegrettinglistBinding +import com.fengliyan.tianlesue.databinding.PopwindowGreetingtipBinding +import com.fengliyan.tianlesue.model.dynamics.UploadImageBean +import com.fengliyan.tianlesue.model.settings.GreetingBean +import com.fengliyan.tianlesue.view.base.BaseActivity +import com.fengliyan.tianlesue.view.base.utils.HttpUiCallBack +import com.fengliyan.tianlesue.view.diooto.tools.Utils +import com.fengliyan.tianlesue.view.main.dialog.CustomAlertDialog +import com.fengliyan.uikit.toast.MaleToast +import com.netease.nimlib.sdk.media.player.AudioPlayer +import com.netease.nimlib.sdk.media.player.OnPlayListener +import com.netease.nimlib.sdk.media.record.IAudioRecordCallback +import com.netease.nimlib.sdk.media.record.RecordType +import java.io.File + +class VoiceGrettingListActivity :BaseActivity(){ + + lateinit var binding: ActivityVoicegrettinglistBinding + var voiceFile:File? = null + var duration = 1 + lateinit var adapter: BaseQuickAdapter + var datas = mutableListOf() + lateinit var player:AudioPlayer + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + player = AudioPlayer(this) + player.onPlayListener = object:OnPlayListener{ + override fun onPrepared() { + } + + override fun onCompletion() { + datas.forEach { + it.isPlaying = false + } + adapter.notifyDataSetChanged() + } + + override fun onInterrupt() { + } + + override fun onError(p0: String?) { + datas.forEach { + it.isPlaying = false + } + adapter.notifyDataSetChanged() + } + + override fun onPlaying(p0: Long) { + } + + } + binding = ActivityVoicegrettinglistBinding.inflate(layoutInflater) + binding.recordView.setSaveBtnListener { + if (voiceFile==null){ + return@setSaveBtnListener + } + uploadFile(voiceFile?.absolutePath) + } + binding.recordView.setRecordCallback(object:IAudioRecordCallback{ + override fun onRecordSuccess(p0: File?, p1: Long, p2: RecordType?) { + voiceFile = p0 + duration = (p1/1000).toInt() + } + + override fun onRecordReachedMaxTime(p0: Int) { + } + + override fun onRecordReady() { + + } + + override fun onRecordCancel() { + + } + + override fun onRecordStart(p0: File?, p1: RecordType?) { + } + + override fun onRecordFail() { + MaleToast.showMessage(this@VoiceGrettingListActivity,"录音失败"); + } + + }) + setContentView(binding.root) + setDefaultTitle() + setTitleName("语音招呼") + adapter = object : BaseQuickAdapter(R.layout.item_greeting_voice,datas){ + init { + addChildClickViewIds(R.id.playBtn,R.id.delBtn) + } + override fun convert(helper: BaseViewHolder, item: GreetingBean.ListBean) { + helper.setImageResource(R.id.playBtn,R.mipmap.greeting_voice_play) + if (item.status==0){ + helper.setImageResource(R.id.playBtn,R.mipmap.greeting_voice_audit) + helper.setText(R.id.durationLabel,"语音招呼正在审核中") + }else{ + helper.setText(R.id.durationLabel,"${item.dur}秒") + } + if (item.isPlaying){ + helper.setImageResource(R.id.playBtn,R.mipmap.greeting_voice_pause) + } + } + } + adapter.setOnItemChildClickListener { adapter1, view, position -> + if (view.id==R.id.playBtn){ + var target = datas[position] + for (item in datas){ + if (item==target){ + if (TextUtils.isEmpty(target.title)) { + return@setOnItemChildClickListener + } + item.isPlaying = !item.isPlaying + if (item.isPlaying){ + play(target.title) + }else{ + pause() + } + }else{ + item.isPlaying = false + }} + adapter.notifyDataSetChanged() + }else if (view.id==R.id.delBtn){ + del(position) + } + } + binding.emptyLayout.visibility = View.INVISIBLE + binding.recyclerView.layoutManager = LinearLayoutManager(this) + binding.recyclerView.adapter = adapter + + Handler().postDelayed(object :Runnable{ + override fun run() { + showTipWindow() + } + },600) + refresh() + + //点击我加的录音按钮 + val permissionDialog = PermissionDialog( + this, + arrayOf(Manifest.permission.RECORD_AUDIO) + ) + permissionDialog.show() + XXPermissions.with(this) // 申请单个权限 + .permission(android.Manifest.permission.RECORD_AUDIO) // 申请多个权限 + .request(object : OnPermissionCallback { + override fun onGranted(permissions: MutableList?, all: Boolean) { + permissionDialog.dismiss() + } + + override fun onDenied(permissions: MutableList?, never: Boolean) { + permissionDialog.dismiss() + MaleToast.showMessage(this@VoiceGrettingListActivity,"没有录音权限不能上传语音招呼"); + } + }) + } + + fun play(fileUrl:String){ + val fullUrlString = "${ConstUrl.IMAGE_URL}${fileUrl}" + val name = Uri.parse(fullUrlString).lastPathSegment + var file = File(cacheDir,name) + if (file.exists()){ + player.setDataSource(file.absolutePath) + player.start(0) + }else{ + SettingManager.downloadVoice(fullUrlString,file.absolutePath, + object :HttpCallback(){ + override fun onFailure(httpStatusCode: Int, message: String?, throwable: Throwable?) { + MaleToast.showMessage(this@VoiceGrettingListActivity,"播放失败") + } + override fun onSuccess(httpStatusCode: Int, responseObject: String?) { + play(fileUrl) + } + + }) + } + } + fun pause(){ + player.stop() + } + + fun showTipWindow(){ + if (isDestroyed){ + return + } + val popwindow = PopupWindow(this) + val windowBinding = PopwindowGreetingtipBinding.inflate(layoutInflater) + windowBinding.tipLabel.text = "小提示:语音招呼可以在打招呼中便捷使用;\n" + + "清晰明朗的声音会加倍提高消息回复率" + val popView =windowBinding.root + popwindow.isOutsideTouchable = true + popwindow.setBackgroundDrawable(null) + popwindow.contentView = popView + popwindow.showAtLocation(binding.recordView, Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM, + 0, Utils.dip2px(this,230f)) + } + fun del(position:Int){ + val dialog = CustomAlertDialog(this) + dialog.hideTitle(true) + dialog.setLeftBtnText("取消") + dialog.setRightBtnText("确认") + dialog.setContent("确定要删除这条语音招呼吗?") + dialog.setRightOnClickListener { + SettingManager.delGreet(VoiceGrettingListActivity@this,datas[position].id, object : HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + datas.removeAt(position) + adapter.notifyDataSetChanged() + refreshEmptyLabel() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"删除失败") + } + + }) + } + dialog.show() + } + + + fun refreshEmptyLabel(){ + if (datas.size>0){ + binding.emptyLayout.visibility = View.INVISIBLE + }else{ + binding.emptyLayout.visibility = View.VISIBLE + } + } + fun refresh(){ + SettingManager.greetingList(this,1,object: HttpUiCallBack { + override fun onSuccess(activity: BaseActivity?, result: GreetingBean, tips: String?) { + datas.clear() + datas.addAll(result.list) + adapter.notifyDataSetChanged() + refreshEmptyLabel() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + + } + }); + } + fun uploadFile(path: String?) { + val uploadFiles = arrayOfNulls(1) + // path = ImageUtils.compressImage(this, path, Constant.IMAGE_MEMORY_SIZE); + val file = File(path) + val uploadFile = UploadFile("file", file) + uploadFiles[0] = uploadFile +// 上传类型 audit 认证 album 相册 dynamic 动态 feedback 反馈 report 举报 wechat_qq 微信/QQ审核 mp4 视频 mp4 视频 charge 付费 + val mProgressDialog = ProgressDialog.show(this, "请等待...", "图片正在上传中...", true, false) + DynamicsManager.uploadVoice(this, uploadFiles, "greet", duration,false, + object : HttpUiCallBack { + + + override fun onFailure(activity: BaseActivity, tip: String) { + MaleToast.showMessage(activity, tip) + mProgressDialog.dismiss() + } + + override fun onException(activity: BaseActivity, e: Throwable) { + MaleToast.showMessage(activity, "请重试") + mProgressDialog.dismiss() + } + + override fun onSuccess(activity: BaseActivity?, result: UploadImageBean?, tips: String?) { + mProgressDialog.dismiss() + var str: String? = result?.img_id + str?.let { + submit(it) + } + + } + }) + } + fun submit(str:String){ + SettingManager.addGreet(this,str,1,object:HttpUiCallBack{ + override fun onSuccess(activity: BaseActivity?, result: Any?, tips: String?) { + MaleToast.showMessage(activity,"添加成功") + binding.recordView.reset() + refresh() + } + + override fun onFailure(activity: BaseActivity?, tip: String?) { + MaleToast.showMessage(activity,tip) + } + + override fun onException(activity: BaseActivity?, e: Throwable?) { + MaleToast.showMessage(activity,"添加失败") + } + + }) + } + + override fun onDestroy() { + super.onDestroy() + player.stop() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/EditSpacingItemDecoration.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/EditSpacingItemDecoration.java new file mode 100644 index 0000000..cc46947 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/EditSpacingItemDecoration.java @@ -0,0 +1,43 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.graphics.Rect; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/2/18-上午1:03 + * 描 述: + * 修订历史: + * ================================================ + */ +public class EditSpacingItemDecoration extends RecyclerView.ItemDecoration { + + private int space; + private int thumbnailsCount; + + public EditSpacingItemDecoration(int space, int thumbnailsCount) { + this.space = space; + this.thumbnailsCount = thumbnailsCount; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + // 第一个的前面和最后一个的后面 + int position = parent.getChildAdapterPosition(view); + if (position == 0) { + outRect.left = space; + outRect.right = 0; + } else if (thumbnailsCount > 10 && position == thumbnailsCount - 1) { + outRect.left = 0; + outRect.right = space; + } else { + outRect.left = 0; + outRect.right = 0; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/ExtractFrameWorkThread.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/ExtractFrameWorkThread.java new file mode 100644 index 0000000..449e6e3 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/ExtractFrameWorkThread.java @@ -0,0 +1,50 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.os.Handler; + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/3/2-下午7:53 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class ExtractFrameWorkThread extends Thread { + public static final int MSG_SAVE_SUCCESS = 0; + private String videoPath; + private String OutPutFileDirPath; + private long startPosition; + private long endPosition; + private int thumbnailsCount; + private VideoExtractFrameAsyncUtils mVideoExtractFrameAsyncUtils; + + public ExtractFrameWorkThread(int extractW, int extractH, Handler mHandler, String videoPath, String OutPutFileDirPath, + long startPosition, long endPosition, int thumbnailsCount) { + this.videoPath = videoPath; + this.OutPutFileDirPath = OutPutFileDirPath; + this.startPosition = startPosition; + this.endPosition = endPosition; + this.thumbnailsCount = thumbnailsCount; + this.mVideoExtractFrameAsyncUtils = new VideoExtractFrameAsyncUtils(extractW,extractH,mHandler); + } + + @Override + public void run() { + super.run(); + mVideoExtractFrameAsyncUtils.getVideoThumbnailsInfoForEdit( + videoPath, + OutPutFileDirPath, + startPosition, + endPosition, + thumbnailsCount); + } + + public void stopExtract() { + if (mVideoExtractFrameAsyncUtils != null) { + mVideoExtractFrameAsyncUtils.stopExtract(); + } + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/ExtractVideoInfoUtil.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/ExtractVideoInfoUtil.java new file mode 100644 index 0000000..30f3d6d --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/ExtractVideoInfoUtil.java @@ -0,0 +1,121 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.graphics.Bitmap; +import android.media.MediaMetadataRetriever; +import android.os.Build; +import android.text.TextUtils; + +import java.io.File; + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/2/23-上午11:05 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class ExtractVideoInfoUtil { + private MediaMetadataRetriever mMetadataRetriever; + private long fileLength = 0;//毫秒 + + public ExtractVideoInfoUtil(String path) { + if (TextUtils.isEmpty(path)) { + throw new RuntimeException("path must be not null !"); + } + File file = new File(path); + if (!file.exists()) { + throw new RuntimeException("path file not exists !"); + } + mMetadataRetriever = new MediaMetadataRetriever(); + mMetadataRetriever.setDataSource(file.getAbsolutePath()); + String len = getVideoLength(); + fileLength = TextUtils.isEmpty(len) ? 0 : Long.valueOf(len); + + } + + public int getVideoWidth() { + String w = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); + int width = -1; + if (!TextUtils.isEmpty(w)) { + width = Integer.valueOf(w); + } + return width; + } + + public int getVideoHeight() { + String h = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); + int height = -1; + if (!TextUtils.isEmpty(h)) { + height = Integer.valueOf(h); + } + return height; + } + + /** + * 获取视频的典型的一帧图片,不耗时 + * + * @return Bitmap + */ + public Bitmap extractFrame() { + return mMetadataRetriever.getFrameAtTime(); + } + + /** + * 获取视频某一帧,不一定是关键帧 + * + * @param timeMs 毫秒 + */ + public Bitmap extractFrame(long timeMs) { + //第一个参数是传入时间,只能是us(微秒) + //OPTION_CLOSEST ,在给定的时间,检索最近一个帧,这个帧不一定是关键帧。 + //OPTION_CLOSEST_SYNC 在给定的时间,检索最近一个同步与数据源相关联的的帧(关键帧) + //OPTION_NEXT_SYNC 在给定时间之后检索一个同步与数据源相关联的关键帧。 + //OPTION_PREVIOUS_SYNC 顾名思义,同上 +// Bitmap bitmap = mMetadataRetriever.getFrameAtTime(timeMs * 1000, MediaMetadataRetriever.OPTION_CLOSEST); + Bitmap bitmap = null; + for (long i = timeMs; i < fileLength; i += 1000) { + bitmap = mMetadataRetriever.getFrameAtTime(i * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); + if (bitmap != null) { + break; + } + } + return bitmap; + } + + + + /*** + * 获取视频的长度时间 + * + * @return String 毫秒 + */ + public String getVideoLength() { + return mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); + } + + /** + * 获取视频旋转角度 + * + * @return + */ + public int getVideoDegree() { + int degree = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + String degreeStr = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); + if (!TextUtils.isEmpty(degreeStr)) { + degree = Integer.valueOf(degreeStr); + } + } + return degree; + } + + public void release() { + if (mMetadataRetriever != null) { + mMetadataRetriever.release(); + } + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/PictureUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/PictureUtils.java new file mode 100644 index 0000000..a9cdd22 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/PictureUtils.java @@ -0,0 +1,90 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.content.Context; +import android.graphics.Bitmap; +import android.os.Environment; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/4/4-下午6:56 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class PictureUtils { + public static final String POSTFIX = ".jpeg"; + private static final String EDIT_PATH = "/EditVideo/"; + + public static String saveImageToSD(Bitmap bmp, String dirPath) { + if (bmp == null) { + return ""; + } + File appDir = new File(dirPath); + if (!appDir.exists()) { + appDir.mkdir(); + } + String fileName = System.currentTimeMillis() + ".jpg"; + File file = new File(appDir, fileName); + try { + FileOutputStream fos = new FileOutputStream(file); + bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos); + fos.flush(); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return file.getAbsolutePath(); + } + + + + public static String saveImageToSDForEdit(Bitmap bmp, String dirPath, String fileName) { + if (bmp == null) { + return ""; + } + File appDir = new File(dirPath); + if (!appDir.exists()) { + appDir.mkdir(); + } + File file = new File(appDir, fileName); + try { + FileOutputStream fos = new FileOutputStream(file); + bmp.compress(Bitmap.CompressFormat.JPEG, 80, fos); + fos.flush(); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return file.getAbsolutePath(); + } + + public static void deleteFile(File f) { + if (f.isDirectory()) { + File[] files = f.listFiles(); + if (files != null && files.length > 0) { + for (int i = 0; i < files.length; ++i) { + deleteFile(files[i]); + } + } + } + f.delete(); + } + + public static String getSaveEditThumbnailDir(Context context) { + String state = Environment.getExternalStorageState(); + File rootDir = state.equals(Environment.MEDIA_MOUNTED) ? context.getExternalFilesDir("") : context.getCacheDir(); + File folderDir = new File(rootDir.getAbsolutePath() + EDIT_PATH); + if (!folderDir.exists() && folderDir.mkdirs()) { + + } + return folderDir.getAbsolutePath(); + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/RangeSeekBar.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/RangeSeekBar.java new file mode 100644 index 0000000..9d0420b --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/RangeSeekBar.java @@ -0,0 +1,559 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.os.Bundle; +import android.os.Parcelable; +import androidx.annotation.Nullable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + + +import com.fengliyan.tianlesue.R; + +import java.text.DecimalFormat; + + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/4/4-下午1:22 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class RangeSeekBar extends View { + private static final String TAG = RangeSeekBar.class.getSimpleName(); + private double absoluteMinValuePrim, absoluteMaxValuePrim; + private double normalizedMinValue = 0d;//点坐标占总长度的比例值,范围从0-1 + private double normalizedMaxValue = 1d;//点坐标占总长度的比例值,范围从0-1 + private long min_cut_time = 3000; + private double normalizedMinValueTime = 0d; + private double normalizedMaxValueTime = 1d;// normalized:规格化的--点坐标占总长度的比例值,范围从0-1 + private int mScaledTouchSlop; + private Bitmap thumbImageLeft; + private Bitmap thumbImageRight; + private Bitmap thumbPressedImage; + private Bitmap mBitmapBlack; + private Bitmap mBitmapPro; + private Paint paint; + private Paint rectPaint; + private int thumbWidth; + private float thumbHalfWidth; + private final float padding = 0; + + private float thumbPaddingTop = 0; + private float thumbPressPaddingTop = 0; + private boolean isTouchDown; + public static final int INVALID_POINTER_ID = 255; + public static final int ACTION_POINTER_INDEX_MASK = 0x0000ff00, ACTION_POINTER_INDEX_SHIFT = 8; + private int mActivePointerId = INVALID_POINTER_ID; + private float mDownMotionX; + private boolean mIsDragging; + private Thumb pressedThumb; + private boolean isMin; + private double min_width = 1;//最小裁剪距离 + private boolean notifyWhileDragging = false; + + public enum Thumb { + MIN, MAX + } + + public RangeSeekBar(Context context) { + super(context); + } + + public RangeSeekBar(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public RangeSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public RangeSeekBar(Context context, long absoluteMinValuePrim, long absoluteMaxValuePrim) { + super(context); + this.absoluteMinValuePrim = absoluteMinValuePrim; + this.absoluteMaxValuePrim = absoluteMaxValuePrim; + setFocusable(true); + setFocusableInTouchMode(true); + init(); + } + + private void init() { + mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + //等比例缩放图片 + thumbImageLeft = BitmapFactory.decodeResource(getResources(), R.drawable.handle_left); + int width = thumbImageLeft.getWidth(); + int height = thumbImageLeft.getHeight(); + int newWidth = dip2px(11); + int newHeight = dip2px(55); + float scaleWidth = newWidth * 1.0f / width; + float scaleHeight = newHeight * 1.0f / height; + Matrix matrix = new Matrix(); + matrix.postScale(scaleWidth, scaleHeight); + thumbImageLeft = Bitmap.createBitmap(thumbImageLeft, 0, 0, width, height, matrix, true); + thumbImageRight = thumbImageLeft; + thumbPressedImage = thumbImageLeft; + thumbWidth = newWidth; + thumbHalfWidth = thumbWidth / 2; + + + mBitmapBlack = BitmapFactory.decodeResource(getResources(), R.drawable.upload_overlay_black); + mBitmapPro = BitmapFactory.decodeResource(getResources(), R.drawable.upload_overlay_trans); + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + rectPaint.setStyle(Paint.Style.FILL); + rectPaint.setColor(Color.parseColor("#ffffff")); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = 300; + if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(widthMeasureSpec)) { + width = MeasureSpec.getSize(widthMeasureSpec); + } + int height = 120; + if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(heightMeasureSpec)) { + height = MeasureSpec.getSize(heightMeasureSpec); + } + setMeasuredDimension(width, height); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + float bg_middle_left = 0; + float bg_middle_right = getWidth() - getPaddingRight(); + float scale = (bg_middle_right - bg_middle_left) / mBitmapPro.getWidth(); + + float rangeL = normalizedToScreen(normalizedMinValue); + float rangeR = normalizedToScreen(normalizedMaxValue); + float scale_pro = (rangeR - rangeL) / mBitmapPro.getWidth(); + if (scale_pro > 0) { + try { + Matrix pro_mx = new Matrix(); + pro_mx.postScale(scale_pro, 1f); + Bitmap m_bitmap_pro_new = Bitmap.createBitmap(mBitmapPro, 0, 0, mBitmapPro.getWidth(), + mBitmapPro.getHeight(), pro_mx, true); + + //画中间的透明遮罩 + canvas.drawBitmap(m_bitmap_pro_new, rangeL, thumbPaddingTop, paint); + + Matrix mx = new Matrix(); + mx.postScale(scale, 1f); + Bitmap m_bitmap_black_new = Bitmap.createBitmap(mBitmapBlack, 0, 0, mBitmapBlack.getWidth(), mBitmapBlack.getHeight(), mx, true); + + //画左边的半透明遮罩 + Bitmap m_bg_new1 = Bitmap.createBitmap(m_bitmap_black_new, 0, 0, (int) (rangeL - bg_middle_left) + (int) thumbWidth / 2, mBitmapBlack.getHeight()); + canvas.drawBitmap(m_bg_new1, bg_middle_left, thumbPaddingTop, paint); + + //画右边的半透明遮罩 + Bitmap m_bg_new2 = Bitmap.createBitmap(m_bitmap_black_new, (int) (rangeR - thumbWidth / 2), 0, (int) (getWidth() - rangeR) + (int) thumbWidth / 2, mBitmapBlack.getHeight()); + canvas.drawBitmap(m_bg_new2, (int) (rangeR - thumbWidth / 2), thumbPaddingTop, paint); + + //画上下的矩形 + canvas.drawRect(rangeL, thumbPaddingTop, rangeR, thumbPaddingTop + dip2px(2), rectPaint); + canvas.drawRect(rangeL, getHeight() - dip2px(2), rangeR, getHeight(), rectPaint); + //画左右thumb + drawThumb(normalizedToScreen(normalizedMinValue), false, canvas, true); + drawThumb(normalizedToScreen(normalizedMaxValue), false, canvas, false); + } catch (Exception e) { + // 当pro_scale非常小,例如width=12,Height=48,pro_scale=0.01979065时, + // 宽高按比例计算后值为0.237、0.949,系统强转为int型后宽就变成0了。就出现非法参数异常 + Log.e(TAG, + "IllegalArgumentException--width=" + mBitmapPro.getWidth() + "Height=" + mBitmapPro.getHeight() + + "scale_pro=" + scale_pro, e); + } + } + } + + + private void drawThumb(float screenCoord, boolean pressed, Canvas canvas, boolean isLeft) { + canvas.drawBitmap(pressed ? thumbPressedImage : (isLeft ? thumbImageLeft : thumbImageRight), screenCoord - (isLeft ? 0 : thumbWidth), (pressed ? thumbPressPaddingTop : thumbPaddingTop), paint); + } + + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isTouchDown) { + return super.onTouchEvent(event); + } + if (event.getPointerCount() > 1) { + return super.onTouchEvent(event); + } + + if (!isEnabled()) + return false; + if (absoluteMaxValuePrim <= min_cut_time) { + return super.onTouchEvent(event); + } + int pointerIndex;// 记录点击点的index + final int action = event.getAction(); + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + //记住最后一个手指点击屏幕的点的坐标x,mDownMotionX + mActivePointerId = event.getPointerId(event.getPointerCount() - 1); + pointerIndex = event.findPointerIndex(mActivePointerId); + mDownMotionX = event.getX(pointerIndex); + // 判断touch到的是最大值thumb还是最小值thumb + pressedThumb = evalPressedThumb(mDownMotionX); + if (pressedThumb == null) + return super.onTouchEvent(event); + setPressed(true);// 设置该控件被按下了 + onStartTrackingTouch();// 置mIsDragging为true,开始追踪touch事件 + trackTouchEvent(event); + attemptClaimDrag(); + if (listener != null) { + listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue(), MotionEvent.ACTION_DOWN, isMin, pressedThumb); + } + break; + case MotionEvent.ACTION_MOVE: + if (pressedThumb != null) { + if (mIsDragging) { + trackTouchEvent(event); + } else { + // Scroll to follow the motion event + pointerIndex = event.findPointerIndex(mActivePointerId); + final float x = event.getX(pointerIndex);// 手指在控件上点的X坐标 + // 手指没有点在最大最小值上,并且在控件上有滑动事件 + if (Math.abs(x - mDownMotionX) > mScaledTouchSlop) { + setPressed(true); + Log.e(TAG, "没有拖住最大最小值");// 一直不会执行? + invalidate(); + onStartTrackingTouch(); + trackTouchEvent(event); + attemptClaimDrag(); + } + } + if (notifyWhileDragging && listener != null) { + listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue(), MotionEvent.ACTION_MOVE, isMin, pressedThumb); + } + } + break; + case MotionEvent.ACTION_UP: + if (mIsDragging) { + trackTouchEvent(event); + onStopTrackingTouch(); + setPressed(false); + } else { + onStartTrackingTouch(); + trackTouchEvent(event); + onStopTrackingTouch(); + } + + invalidate(); + if (listener != null) { + listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue(), MotionEvent.ACTION_UP, isMin, pressedThumb); + } + pressedThumb = null;// 手指抬起,则置被touch到的thumb为空 + break; + case MotionEvent.ACTION_POINTER_DOWN: + final int index = event.getPointerCount() - 1; + // final int index = ev.getActionIndex(); + mDownMotionX = event.getX(index); + mActivePointerId = event.getPointerId(index); + invalidate(); + break; + case MotionEvent.ACTION_POINTER_UP: + onSecondaryPointerUp(event); + invalidate(); + break; + case MotionEvent.ACTION_CANCEL: + if (mIsDragging) { + onStopTrackingTouch(); + setPressed(false); + } + invalidate(); // see above explanation + break; + default: + break; + } + return true; + } + + private void onSecondaryPointerUp(MotionEvent ev) { + final int pointerIndex = (ev.getAction() & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT; + + final int pointerId = ev.getPointerId(pointerIndex); + if (pointerId == mActivePointerId) { + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mDownMotionX = ev.getX(newPointerIndex); + mActivePointerId = ev.getPointerId(newPointerIndex); + } + } + + private void trackTouchEvent(MotionEvent event) { + if (event.getPointerCount() > 1) return; + Log.e(TAG, "trackTouchEvent: " + event.getAction() + " x: " + event.getX()); + final int pointerIndex = event.findPointerIndex(mActivePointerId);// 得到按下点的index + float x = 0; + try { + x = event.getX(pointerIndex); + } catch (Exception e) { + return; + } + if (Thumb.MIN.equals(pressedThumb)) { + // screenToNormalized(x)-->得到规格化的0-1的值 + setNormalizedMinValue(screenToNormalized(x, 0)); + } else if (Thumb.MAX.equals(pressedThumb)) { + setNormalizedMaxValue(screenToNormalized(x, 1)); + } + } + + private double screenToNormalized(float screenCoord, int position) { + int width = getWidth(); + if (width <= 2 * padding) { + // prevent division by zero, simply return 0. + return 0d; + } else { + isMin = false; + double current_width = screenCoord; + float rangeL = normalizedToScreen(normalizedMinValue); + float rangeR = normalizedToScreen(normalizedMaxValue); + double min = min_cut_time / (absoluteMaxValuePrim - absoluteMinValuePrim) * (width - thumbWidth * 2); + + if (absoluteMaxValuePrim > 5 * 60 * 1000) {//大于5分钟的精确小数四位 + DecimalFormat df = new DecimalFormat("0.0000"); + min_width = Double.parseDouble(df.format(min)); + } else { + min_width = Math.round(min + 0.5d); + } + if (position == 0) { + if (isInThumbRangeLeft(screenCoord, normalizedMinValue, 0.5)) { + return normalizedMinValue; + } + + float rightPosition = (getWidth() - rangeR) >= 0 ? (getWidth() - rangeR) : 0; + double left_length = getValueLength() - (rightPosition + min_width); + + + if (current_width > rangeL) { + current_width = rangeL + (current_width - rangeL); + } else if (current_width <= rangeL) { + current_width = rangeL - (rangeL - current_width); + } + + if (current_width > left_length) { + isMin = true; + current_width = left_length; + } + + if (current_width < thumbWidth * 2 / 3) { + current_width = 0; + } + + double resultTime = (current_width - padding) / (width - 2 * thumbWidth); + normalizedMinValueTime = Math.min(1d, Math.max(0d, resultTime)); + double result = (current_width - padding) / (width - 2 * padding); + return Math.min(1d, Math.max(0d, result));// 保证该该值为0-1之间,但是什么时候这个判断有用呢? + } else { + if (isInThumbRange(screenCoord, normalizedMaxValue, 0.5)) { + return normalizedMaxValue; + } + + double right_length = getValueLength() - (rangeL + min_width); + if (current_width > rangeR) { + current_width = rangeR + (current_width - rangeR); + } else if (current_width <= rangeR) { + current_width = rangeR - (rangeR - current_width); + } + + double paddingRight = getWidth() - current_width; + + if (paddingRight > right_length) { + isMin = true; + current_width = getWidth() - right_length; + paddingRight = right_length; + } + + if (paddingRight < thumbWidth * 2 / 3) { + current_width = getWidth(); + paddingRight = 0; + } + + double resultTime = (paddingRight - padding) / (width - 2 * thumbWidth); + resultTime = 1 - resultTime; + normalizedMaxValueTime = Math.min(1d, Math.max(0d, resultTime)); + double result = (current_width - padding) / (width - 2 * padding); + return Math.min(1d, Math.max(0d, result));// 保证该该值为0-1之间,但是什么时候这个判断有用呢? + } + + } + } + + private int getValueLength() { + return (getWidth() - 2 * thumbWidth); + } + + /** + * 计算位于哪个Thumb内 + * + * @param touchX touchX + * @return 被touch的是空还是最大值或最小值 + */ + private Thumb evalPressedThumb(float touchX) { + Thumb result = null; + boolean minThumbPressed = isInThumbRange(touchX, normalizedMinValue, 2);// 触摸点是否在最小值图片范围内 + boolean maxThumbPressed = isInThumbRange(touchX, normalizedMaxValue, 2); + if (minThumbPressed && maxThumbPressed) { + // 如果两个thumbs重叠在一起,无法判断拖动哪个,做以下处理 + // 触摸点在屏幕右侧,则判断为touch到了最小值thumb,反之判断为touch到了最大值thumb + result = (touchX / getWidth() > 0.5f) ? Thumb.MIN : Thumb.MAX; + } else if (minThumbPressed) { + result = Thumb.MIN; + } else if (maxThumbPressed) { + result = Thumb.MAX; + } + return result; + } + + private boolean isInThumbRange(float touchX, double normalizedThumbValue, double scale) { + // 当前触摸点X坐标-最小值图片中心点在屏幕的X坐标之差<=最小点图片的宽度的一般 + // 即判断触摸点是否在以最小值图片中心为原点,宽度一半为半径的圆内。 + return Math.abs(touchX - normalizedToScreen(normalizedThumbValue)) <= thumbHalfWidth * scale; + } + + private boolean isInThumbRangeLeft(float touchX, double normalizedThumbValue, double scale) { + // 当前触摸点X坐标-最小值图片中心点在屏幕的X坐标之差<=最小点图片的宽度的一般 + // 即判断触摸点是否在以最小值图片中心为原点,宽度一半为半径的圆内。 + return Math.abs(touchX - normalizedToScreen(normalizedThumbValue) - thumbWidth) <= thumbHalfWidth * scale; + } + + /** + * 试图告诉父view不要拦截子控件的drag + */ + private void attemptClaimDrag() { + if (getParent() != null) { + getParent().requestDisallowInterceptTouchEvent(true); + } + } + + void onStartTrackingTouch() { + mIsDragging = true; + } + + + void onStopTrackingTouch() { + mIsDragging = false; + } + + public void setMin_cut_time(long min_cut_time) { + this.min_cut_time = min_cut_time; + } + + + private float normalizedToScreen(double normalizedCoord) { + return (float) (getPaddingLeft() + normalizedCoord * (getWidth() - getPaddingLeft() - getPaddingRight())); + } + + private double valueToNormalized(long value) { + if (0 == absoluteMaxValuePrim - absoluteMinValuePrim) { + return 0d; + } + return (value - absoluteMinValuePrim) / (absoluteMaxValuePrim - absoluteMinValuePrim); + } + + public void setSelectedMinValue(long value) { + if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) { + setNormalizedMinValue(0d); + } else { + setNormalizedMinValue(valueToNormalized(value)); + } + } + + public void setSelectedMaxValue(long value) { + if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) { + setNormalizedMaxValue(1d); + } else { + setNormalizedMaxValue(valueToNormalized(value)); + } + } + + public void setNormalizedMinValue(double value) { + normalizedMinValue = Math.max(0d, Math.min(1d, Math.min(value, normalizedMaxValue))); + invalidate();// 重新绘制此view + } + + + public void setNormalizedMaxValue(double value) { + normalizedMaxValue = Math.max(0d, Math.min(1d, Math.max(value, normalizedMinValue))); + invalidate();// 重新绘制此view + } + + + public long getSelectedMinValue() { + return normalizedToValue(normalizedMinValueTime); + } + + public long getSelectedMaxValue() { + return normalizedToValue(normalizedMaxValueTime); + } + + private long normalizedToValue(double normalized) { + return (long) (absoluteMinValuePrim + normalized + * (absoluteMaxValuePrim - absoluteMinValuePrim)); + } + + /** + * 供外部activity调用,控制是都在拖动的时候打印log信息,默认是false不打印 + */ + public boolean isNotifyWhileDragging() { + return notifyWhileDragging; + } + + + public void setNotifyWhileDragging(boolean flag) { + this.notifyWhileDragging = flag; + } + + public int dip2px(int dip) { + float scale = getContext().getResources().getDisplayMetrics().density; + return (int) ((float) dip * scale + 0.5F); + } + + public void setTouchDown(boolean touchDown) { + isTouchDown = touchDown; + } + + @Override + protected Parcelable onSaveInstanceState() { + final Bundle bundle = new Bundle(); + bundle.putParcelable("SUPER", super.onSaveInstanceState()); + bundle.putDouble("MIN", normalizedMinValue); + bundle.putDouble("MAX", normalizedMaxValue); + bundle.putDouble("MIN_TIME", normalizedMinValueTime); + bundle.putDouble("MAX_TIME", normalizedMaxValueTime); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable parcel) { + final Bundle bundle = (Bundle) parcel; + super.onRestoreInstanceState(bundle.getParcelable("SUPER")); + normalizedMinValue = bundle.getDouble("MIN"); + normalizedMaxValue = bundle.getDouble("MAX"); + normalizedMinValueTime = bundle.getDouble("MIN_TIME"); + normalizedMaxValueTime = bundle.getDouble("MAX_TIME"); + } + + private OnRangeSeekBarChangeListener listener; + + public interface OnRangeSeekBarChangeListener { + void onRangeSeekBarValuesChanged(RangeSeekBar bar, long minValue, long maxValue, int action, boolean isMin, Thumb pressedThumb); + } + + public void setOnRangeSeekBarChangeListener(OnRangeSeekBarChangeListener listener) { + this.listener = listener; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/RecyclerViewSpacesItemDecoration.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/RecyclerViewSpacesItemDecoration.java new file mode 100644 index 0000000..2135ac6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/RecyclerViewSpacesItemDecoration.java @@ -0,0 +1,41 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.graphics.Rect; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +import java.util.HashMap; + +/** + * ying 2020/8/19 + * Describe :recyclerView 设置item的间距 + */ + +public class RecyclerViewSpacesItemDecoration extends RecyclerView.ItemDecoration { + private HashMap mSpaceValueMap; + + public static final String TOP_DECORATION = "top_decoration"; + public static final String BOTTOM_DECORATION = "bottom_decoration"; + public static final String LEFT_DECORATION = "left_decoration"; + public static final String RIGHT_DECORATION = "right_decoration"; + + public RecyclerViewSpacesItemDecoration(HashMap mSpaceValueMap) { + this.mSpaceValueMap = mSpaceValueMap; + } + + @Override + public void getItemOffsets(Rect outRect, View view, + RecyclerView parent, RecyclerView.State state) { + if (mSpaceValueMap.get(TOP_DECORATION) != null) + outRect.top = mSpaceValueMap.get(TOP_DECORATION); + if (mSpaceValueMap.get(LEFT_DECORATION) != null) + + outRect.left = mSpaceValueMap.get(LEFT_DECORATION); + if (mSpaceValueMap.get(RIGHT_DECORATION) != null) + outRect.right = mSpaceValueMap.get(RIGHT_DECORATION); + if (mSpaceValueMap.get(BOTTOM_DECORATION) != null) + outRect.bottom = mSpaceValueMap.get(BOTTOM_DECORATION); + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/UIUtil.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/UIUtil.java new file mode 100644 index 0000000..e485c85 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/UIUtil.java @@ -0,0 +1,38 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import static android.content.Context.WINDOW_SERVICE; + +import android.content.Context; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/4/8-下午3:48 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class UIUtil { + public static int dip2px(Context context, int dip) { + float scale = context.getResources().getDisplayMetrics().density; + return (int) ((float) dip * scale + 0.5F); + } + + public static int getScreenWidth(Context context) { + DisplayMetrics metric = new DisplayMetrics(); + WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); + wm.getDefaultDisplay().getMetrics(metric); + return metric.widthPixels; + } + + public static int getScreenHeight(Context context) { + DisplayMetrics metric = new DisplayMetrics(); + WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); + wm.getDefaultDisplay().getMetrics(metric); + return metric.heightPixels; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoBean.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoBean.java new file mode 100644 index 0000000..8cd5ea6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoBean.java @@ -0,0 +1,40 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import java.io.Serializable; + +public class VideoBean implements Serializable { + /** + * video_id : 1 + * url : uploads/vedio/383ac7d8f327ccf393c9a39dd2b05cbb.mp4 + * audit_status : 0 + */ + + private int video_id; + private String url; + private int audit_status; + + public int getVideo_id() { + return video_id; + } + + public void setVideo_id(int video_id) { + this.video_id = video_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public int getAudit_status() { + return audit_status; + } + + public void setAudit_status(int audit_status) { + this.audit_status = audit_status; + } + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoClipUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoClipUtils.java new file mode 100644 index 0000000..b79f963 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoClipUtils.java @@ -0,0 +1,272 @@ +package com.fengliyan.tianlesue.view.settings.video; + +/** + * ying 2020/8/24 + * Describe :mp4parser视频裁剪 + */ + +import android.text.TextUtils; +import android.util.Log; + + +import com.coremedia.iso.boxes.Container; +import com.googlecode.mp4parser.authoring.Movie; +import com.googlecode.mp4parser.authoring.Track; +import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder; +import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator; +import com.googlecode.mp4parser.authoring.tracks.CroppedTrack; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class VideoClipUtils { + private static final String TAG = VideoClipUtils.class.getSimpleName(); + + /** + * 裁剪视频 + * + * @param srcPath 需要裁剪的原视频路径 + * @param outPath 裁剪后的视频输出路径 + * @param startTimeMs 裁剪的起始时间 + * @param endTimeMs 裁剪的结束时间 + */ + public static void clip(String srcPath, String outPath, double startTimeMs, double endTimeMs) throws IOException, IllegalArgumentException { + Log.d(TAG, "--->>>>startTimeMs = " + startTimeMs + " endTimeMs = " + endTimeMs); + if (TextUtils.isEmpty(srcPath) || TextUtils.isEmpty(outPath)) { + throw new IllegalArgumentException("file path can't be null!!!!"); + } + if (!(new File(srcPath).exists())) { + throw new IllegalArgumentException("the source file is not exist!!!!"); + } + if (startTimeMs >= endTimeMs) { + throw new IllegalArgumentException("the startTimeMs is larger than endTimeMs!!!!"); + } + Movie movie = MovieCreator.build(srcPath); + List tracks = movie.getTracks(); + //移除旧的track + movie.setTracks(new LinkedList()); + //处理的时间以秒为单位 + double startTime = startTimeMs / 1000; + double endTime = endTimeMs / 1000; + Log.d(TAG, "--->>>>startTimeMs = " + startTimeMs + " endTimeMs = " + endTimeMs + " tracks.size = " + tracks.size()); + //计算剪切时间,视频的采样间隔大,以视频为准 + for (Track track : tracks) { + if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) { + startTime = correctTimeToSyncSample(track, startTime, false); + endTime = correctTimeToSyncSample(track, endTime, true); + if (track.getHandler().equals("vide")) { + break; + } + } + } + Log.d(TAG, "--->>>>startTime = " + startTime + " endTime = " + endTime); + + //fix bug: 部分视频矫正过后会超出10s,这里进行强制限制在10s内 + if (endTime - startTime > 10) { + int duration = (int) (endTimeMs - startTimeMs) / 1000; + endTime = startTime + duration; + } + //fix bug: 部分视频裁剪后endSecond=0.0,导致播放失败 + if (endTime == 0.0) { + int duration = (int) (endTimeMs - startTimeMs) / 1000; + endTime = startTime + duration; + } + Log.d(TAG, "--->>>>startTime 纠正 = " + startTime + " endTime = " + endTime); + long currentSample; + double currentTime; + double lastTime; + long startSample1; + long endSample1; + long delta; + + for (Track track : tracks) { + currentSample = 0; + currentTime = 0; + lastTime = -1; + startSample1 = -1; + endSample1 = -1; + + //根据起始时间和截止时间获取起始sample和截止sample的位置 + for (int i = 0; i < track.getSampleDurations().length; i++) { + delta = track.getSampleDurations()[i]; + if (currentTime > lastTime && currentTime <= startTime) { + startSample1 = currentSample; + } + if (currentTime > lastTime && currentTime <= endTime) { + endSample1 = currentSample; + } + lastTime = currentTime; + currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale(); + currentSample++; + } + Log.d(TAG, "track.getHandler() = " + track.getHandler() + " startSample1 = " + startSample1 + " endSample1 = " + endSample1); + if (startSample1 <= 0 && endSample1 <= 0) { + throw new RuntimeException("clip failed !!"); + } + movie.addTrack(new CroppedTrack(track, startSample1, endSample1));// 添加截取的track + } + + //合成视频mp4 + Container out = new DefaultMp4Builder().build(movie); + FileOutputStream fos = new FileOutputStream(outPath); + FileChannel fco = fos.getChannel(); + out.writeContainer(fco); + fco.close(); + fos.close(); + } + + + /** + * 换算剪切时间 + * + * @param track + * @param cutHere + * @param next + * @return + */ + public static double correctTimeToSyncSample(Track track, double cutHere, boolean next) { + double[] timeOfSyncSamples = new double[track.getSyncSamples().length]; + long currentSample = 0; + double currentTime = 0; + for (int i = 0; i < track.getSampleDurations().length; i++) { + long delta = track.getSampleDurations()[i]; + int index = Arrays.binarySearch(track.getSyncSamples(), currentSample + 1); + if (index >= 0) { + timeOfSyncSamples[index] = currentTime; + } + currentTime += ((double) delta / (double) track.getTrackMetaData().getTimescale()); + currentSample++; + } + double previous = 0; + for (double timeOfSyncSample : timeOfSyncSamples) { + if (timeOfSyncSample > cutHere) { + if (next) { + return timeOfSyncSample; + } else { + return previous; + } + } + previous = timeOfSyncSample; + } + return timeOfSyncSamples[timeOfSyncSamples.length - 1]; + } + + + /* *//** + * 裁剪视频(异步操作) + * + * @param src 源文件 + * @param dest 输出地址 + * @param startSec 开始时间 + * @param endSec 结束时间 + *//* + public static Observable cutVideo(final String src, final String dest, final double startSec, final double endSec) { + + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter emitter) { + try { + double startSecond = startSec; + double endSecond = endSec; + //构造一个movie对象 + Movie movie = MovieCreator.build(src); + List tracks = movie.getTracks(); + movie.setTracks(new ArrayList()); + + boolean timeCorrected = false; + // Here we try to find a track that has sync samples. Since we can only start decoding + // at such a sample we SHOULD make sure that the start of the new fragment is exactly + // such a frame + for (Track track : tracks) { + if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) { + if (timeCorrected) { + // This exception here could be a false positive in case we have multiple tracks + // with sync samples at exactly the same positions. E.g. a single movie containing + // multiple qualities of the same video (Microsoft Smooth Streaming file) + + throw new RuntimeException( + "The startTime has already been corrected by another track with SyncSample. Not Supported."); + } + //矫正开始时间 + startSecond = correctTimeToSyncSample(track, startSecond, false); + //矫正结束时间 + endSecond = correctTimeToSyncSample(track, endSecond, true); + + timeCorrected = true; + } + } + + //裁剪后的位置 startSecond:299400, endSecond:309390 + //矫正后的位置 startSecond:291.3327083333511, endSecond:313.18787500003214 + Log.e(TAG, "startSecond:" + startSecond + ", endSecond:" + endSecond); + + //fix bug: 部分视频矫正过后会超出10s,这里进行强制限制在10s内 + if (endSecond - startSecond > 10) { + int duration = (int) (endSec - startSec); + endSecond = startSecond + duration; + } + //fix bug: 部分视频裁剪后endSecond=0.0,导致播放失败 + if (endSecond == 0.0) { + int duration = (int) (endSec - startSec); + endSecond = startSecond + duration; + } + + for (Track track : tracks) { + long currentSample = 0; + double currentTime = 0; + double lastTime = -1; + long startSample = -1; + long endSample = -1; + + for (int i = 0; i < track.getSampleDurations().length; i++) { + long delta = track.getSampleDurations()[i]; + + if (currentTime > lastTime && currentTime <= startSecond) { + // current sample is still before the new starttime + startSample = currentSample; + } + if (currentTime > lastTime && currentTime <= endSecond) { + // current sample is after the new start time and still before the new endtime + endSample = currentSample; + } + + lastTime = currentTime; + //计算出某一帧的时长 = 采样时长 / 时间长度 + currentTime += + (double) delta / (double) track.getTrackMetaData().getTimescale(); + //这里就是帧数(采样)加一 + currentSample++; + } + //在这里,裁剪是根据关键帧进行裁剪的,而不是指定的开始时间和结束时间 + //startSample:2453, endSample:2846 393 + //startSample:4795, endSample:5564 769 + Log.e(TAG, "startSample:" + startSample + ", endSample:" + endSample); + movie.addTrack(new CroppedTrack(track, startSample, endSample)); + + Container out = new DefaultMp4Builder().build(movie); + String format = String.format(dest); + FileOutputStream fos = new FileOutputStream(format); + FileChannel fc = fos.getChannel(); + out.writeContainer(fc); + + fc.close(); + fos.close(); + } + + emitter.onNext(dest); + + } catch (Exception e) { + emitter.onError(e); + } + emitter.onComplete(); + } + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()); + }*/ +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditActivity.java new file mode 100644 index 0000000..c872401 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditActivity.java @@ -0,0 +1,487 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.Intent; +import android.media.MediaPlayer; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Toast; +import android.widget.VideoView; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; + +import java.io.File; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/4/8-下午3:48 + * 描 述: + * 修订历史: + * ================================================ + */ +public class VideoEditActivity extends BaseActivity { + private static final String TAG = VideoEditActivity.class.getSimpleName(); + private static final long MIN_CUT_DURATION = 15 * 1000L;// 最小剪辑时间3s + private static final long MAX_CUT_DURATION = 15 * 1000L;//视频最多剪切多长时间 + private static final int MAX_COUNT_RANGE = 10;//seekBar的区域内一共有多少张图片 + private LinearLayout seekBarLayout; + private ExtractVideoInfoUtil mExtractVideoInfoUtil; + private int mMaxWidth; + + private long duration; + private RangeSeekBar seekBar; + private VideoView mVideoView; + private RecyclerView mRecyclerView; + private ImageView positionIcon; + private VideoEditAdapter videoEditAdapter; + private float averageMsPx;//每毫秒所占的px + private float averagePxMs;//每px所占用的ms毫秒 + private String OutPutFileDirPath; + private ExtractFrameWorkThread mExtractFrameWorkThread; + private String path; + private long leftProgress, rightProgress; + private long scrollPos = 0; + private int mScaledTouchSlop; + private int lastScrollX; + private boolean isSeeking; + + public static void launch(Context context, String path) { + Intent intent = new Intent(context,VideoEditActivity.class); + intent.putExtra("VideoPath",path); + context.startActivity(intent); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_video_edit); + path = getIntent().getStringExtra("VideoPath"); + //for video check + if (!new File(path).exists()) { + Toast.makeText(this, "视频文件不存在", Toast.LENGTH_LONG).show(); + finish(); + return; + } + initData(); + initView(); + initEditVideo(); + initPlay(); + setRightCustomTextTitle("裁剪", "完成", new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + String trimmedVideoPath = getTrimmedVideoPath(getBaseContext(), "trimmedVideo", "trimmedVideo_"); + VideoClipUtils.clip(path, trimmedVideoPath, leftProgress, rightProgress); + Intent intent = new Intent(); + intent.putExtra("VideoPath", trimmedVideoPath); + setResult(21, intent); + finish(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } + + private void initData() { + + mExtractVideoInfoUtil = new ExtractVideoInfoUtil(path); + duration = Long.valueOf(mExtractVideoInfoUtil.getVideoLength()); + mMaxWidth = UIUtil.getScreenWidth(this) - UIUtil.dip2px(this, 70); + mScaledTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop(); + + } + + private void initView() { + seekBarLayout = (LinearLayout) findViewById(R.id.id_seekBarLayout); + mVideoView = (VideoView) findViewById(R.id.uVideoView); + positionIcon = (ImageView) findViewById(R.id.positionIcon); + mRecyclerView = (RecyclerView) findViewById(R.id.id_rv_id); + mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + videoEditAdapter = new VideoEditAdapter(getBaseContext(), + (UIUtil.getScreenWidth(this) - UIUtil.dip2px(this, 70)) / 10); + mRecyclerView.setAdapter(videoEditAdapter); + mRecyclerView.addOnScrollListener(mOnScrollListener); + } + + + private void initEditVideo() { + //for video edit + long startPosition = 0; + long endPosition = duration; + int thumbnailsCount; + int rangeWidth; + boolean isOver_60_s; + if (endPosition <= MAX_CUT_DURATION) { + isOver_60_s = false; + thumbnailsCount = MAX_COUNT_RANGE; + rangeWidth = mMaxWidth; + } else { + isOver_60_s = true; + thumbnailsCount = (int) (endPosition * 1.0f / (MAX_CUT_DURATION * 1.0f) * MAX_COUNT_RANGE); + rangeWidth = mMaxWidth / MAX_COUNT_RANGE * thumbnailsCount; + } + mRecyclerView.addItemDecoration(new EditSpacingItemDecoration(UIUtil.dip2px(this, 35), thumbnailsCount)); + + //init seekBar + if (isOver_60_s) { + seekBar = new RangeSeekBar(this, 0L, MAX_CUT_DURATION); + seekBar.setSelectedMinValue(0L); + seekBar.setSelectedMaxValue(MAX_CUT_DURATION); + } else { + seekBar = new RangeSeekBar(this, 0L, endPosition); + seekBar.setSelectedMinValue(0L); + seekBar.setSelectedMaxValue(endPosition); + } + seekBar.setMin_cut_time(MIN_CUT_DURATION);//设置最小裁剪时间 + seekBar.setNotifyWhileDragging(true); + seekBar.setOnRangeSeekBarChangeListener(mOnRangeSeekBarChangeListener); + seekBarLayout.addView(seekBar); + + Log.d(TAG, "-------thumbnailsCount--->>>>" + thumbnailsCount); + averageMsPx = duration * 1.0f / rangeWidth * 1.0f; + Log.d(TAG, "-------rangeWidth--->>>>" + rangeWidth); + Log.d(TAG, "-------localMedia.getDuration()--->>>>" + duration); + Log.d(TAG, "-------averageMsPx--->>>>" + averageMsPx); + OutPutFileDirPath = PictureUtils.getSaveEditThumbnailDir(this); + int extractW = (UIUtil.getScreenWidth(this) - UIUtil.dip2px(this, 70)) / MAX_COUNT_RANGE; + int extractH = UIUtil.dip2px(this, 55); + mExtractFrameWorkThread = new ExtractFrameWorkThread(extractW, extractH, mUIHandler, path, OutPutFileDirPath, startPosition, endPosition, thumbnailsCount); + mExtractFrameWorkThread.start(); + + //init pos icon start + leftProgress = 0; + if (isOver_60_s) { + rightProgress = MAX_CUT_DURATION; + } else { + rightProgress = endPosition; + } + averagePxMs = (mMaxWidth * 1.0f / (rightProgress - leftProgress)); + Log.d(TAG, "------averagePxMs----:>>>>>" + averagePxMs); + + + } + + + private void initPlay() { + mVideoView.setVideoPath(path); + //设置videoview的OnPrepared监听 + mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mp) { + //设置MediaPlayer的OnSeekComplete监听 + mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() { + @Override + public void onSeekComplete(MediaPlayer mp) { + Log.d(TAG, "------ok----real---start-----"); + Log.d(TAG, "------isSeeking-----" + isSeeking); + if (!isSeeking) { + videoStart(); + } + } + }); + } + }); + mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() { + @Override + public boolean onError(MediaPlayer mp, int what, int extra) { + Toast.makeText(VideoEditActivity.this, "视频解析失败", Toast.LENGTH_SHORT).show(); + finish(); + return true; + } + }); + //first + videoStart(); + } + + private boolean isOverScaledTouchSlop; + + private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + Log.d(TAG, "-------newState:>>>>>" + newState); + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + isSeeking = false; +// videoStart(); + } else { + isSeeking = true; + if (isOverScaledTouchSlop && mVideoView != null && mVideoView.isPlaying()) { + videoPause(); + } + } + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + isSeeking = false; + int scrollX = getScrollXDistance(); + //达不到滑动的距离 + if (Math.abs(lastScrollX - scrollX) < mScaledTouchSlop) { + isOverScaledTouchSlop = false; + return; + } + isOverScaledTouchSlop = true; + Log.d(TAG, "-------scrollX:>>>>>" + scrollX); + //初始状态,why ? 因为默认的时候有35dp的空白! + if (scrollX == -UIUtil.dip2px(VideoEditActivity.this, 35)) { + scrollPos = 0; + } else { + // why 在这里处理一下,因为onScrollStateChanged早于onScrolled回调 + if (mVideoView != null && mVideoView.isPlaying()) { + videoPause(); + } + isSeeking = true; + scrollPos = (long) (averageMsPx * (UIUtil.dip2px(VideoEditActivity.this, 35) + scrollX)); + Log.d(TAG, "-------scrollPos:>>>>>" + scrollPos); + leftProgress = seekBar.getSelectedMinValue() + scrollPos; + rightProgress = seekBar.getSelectedMaxValue() + scrollPos; + Log.d(TAG, "-------leftProgress:>>>>>" + leftProgress); + mVideoView.seekTo((int) leftProgress); + } + lastScrollX = scrollX; + } + }; + + /** + * 水平滑动了多少px + * + * @return int px + */ + private int getScrollXDistance() { + LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager(); + int position = layoutManager.findFirstVisibleItemPosition(); + View firstVisibleChildView = layoutManager.findViewByPosition(position); + int itemWidth = firstVisibleChildView.getWidth(); + return (position) * itemWidth - firstVisibleChildView.getLeft(); + } + + private ValueAnimator animator; + + private void anim() { + Log.d(TAG, "--anim--onProgressUpdate---->>>>>>>" + mVideoView.getCurrentPosition()); + if (positionIcon.getVisibility() == View.GONE) { + positionIcon.setVisibility(View.VISIBLE); + } + final FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) positionIcon.getLayoutParams(); + int start = (int) (UIUtil.dip2px(this, 35) + (leftProgress/*mVideoView.getCurrentPosition()*/ - scrollPos) * averagePxMs); + int end = (int) (UIUtil.dip2px(this, 35) + (rightProgress - scrollPos) * averagePxMs); + animator = ValueAnimator + .ofInt(start, end) + .setDuration((rightProgress - scrollPos) - (leftProgress/*mVideoView.getCurrentPosition()*/ - scrollPos)); + animator.setInterpolator(new LinearInterpolator()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + params.leftMargin = (int) animation.getAnimatedValue(); + positionIcon.setLayoutParams(params); + } + }); + animator.start(); + } + + private final MainHandler mUIHandler = new MainHandler(this); + + private static class MainHandler extends Handler { + private final WeakReference mActivity; + + MainHandler(VideoEditActivity activity) { + mActivity = new WeakReference<>(activity); + } + + @Override + public void handleMessage(Message msg) { + VideoEditActivity activity = mActivity.get(); + if (activity != null) { + if (msg.what == ExtractFrameWorkThread.MSG_SAVE_SUCCESS) { + if (activity.videoEditAdapter != null) { + VideoEditInfo info = (VideoEditInfo) msg.obj; + activity.videoEditAdapter.addItemVideoInfo(info); + } + } + } + } + } + + private final RangeSeekBar.OnRangeSeekBarChangeListener mOnRangeSeekBarChangeListener = new RangeSeekBar.OnRangeSeekBarChangeListener() { + @Override + public void onRangeSeekBarValuesChanged(RangeSeekBar bar, long minValue, long maxValue, int action, boolean isMin, RangeSeekBar.Thumb pressedThumb) { + Log.d(TAG, "-----minValue----->>>>>>" + minValue); + Log.d(TAG, "-----maxValue----->>>>>>" + maxValue); + leftProgress = minValue + scrollPos; + rightProgress = maxValue + scrollPos; + Log.d(TAG, "-----leftProgress----->>>>>>" + leftProgress); + Log.d(TAG, "-----rightProgress----->>>>>>" + rightProgress); + switch (action) { + case MotionEvent.ACTION_DOWN: + Log.d(TAG, "-----ACTION_DOWN---->>>>>>"); + isSeeking = false; + videoPause(); + break; + case MotionEvent.ACTION_MOVE: + Log.d(TAG, "-----ACTION_MOVE---->>>>>>"); + isSeeking = true; + mVideoView.seekTo((int) (pressedThumb == RangeSeekBar.Thumb.MIN ? + leftProgress : rightProgress)); + break; + case MotionEvent.ACTION_UP: + Log.d(TAG, "-----ACTION_UP--leftProgress--->>>>>>" + leftProgress); + isSeeking = false; + //从minValue开始播 + mVideoView.seekTo((int) leftProgress); +// videoStart(); + break; + default: + break; + } + } + }; + + + private void videoStart() { + Log.d(TAG, "----videoStart----->>>>>>>"); + mVideoView.start(); + positionIcon.clearAnimation(); + if (animator != null && animator.isRunning()) { + animator.cancel(); + } + anim(); + handler.removeCallbacks(run); + handler.post(run); + } + + private void videoProgressUpdate() { + long currentPosition = mVideoView.getCurrentPosition(); + Log.d(TAG, "----onProgressUpdate-cp---->>>>>>>" + currentPosition); + if (currentPosition >= (rightProgress)) { + mVideoView.seekTo((int) leftProgress); + positionIcon.clearAnimation(); + if (animator != null && animator.isRunning()) { + animator.cancel(); + } + anim(); + } + } + + private void videoPause() { + isSeeking = false; + if (mVideoView != null && mVideoView.isPlaying()) { + mVideoView.pause(); + handler.removeCallbacks(run); + } + Log.d(TAG, "----videoPause----->>>>>>>"); + if (positionIcon.getVisibility() == View.VISIBLE) { + positionIcon.setVisibility(View.GONE); + } + positionIcon.clearAnimation(); + if (animator != null && animator.isRunning()) { + animator.cancel(); + } + } + + + @Override + public void onResume() { + super.onResume(); + if (mVideoView != null) { + mVideoView.seekTo((int) leftProgress); +// videoStart(); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (mVideoView != null && mVideoView.isPlaying()) { + videoPause(); + } + } + + private Handler handler = new Handler(); + private Runnable run = new Runnable() { + + @Override + public void run() { + videoProgressUpdate(); + handler.postDelayed(run, 1000); + } + }; + + @Override + public void onDestroy() { + super.onDestroy(); + if (animator != null) { + animator.cancel(); + } + if (mVideoView != null) { + mVideoView.stopPlayback(); + } + if (mExtractVideoInfoUtil != null) { + mExtractVideoInfoUtil.release(); + } + if (mRecyclerView != null) + mRecyclerView.removeOnScrollListener(mOnScrollListener); + if (mExtractFrameWorkThread != null) { + mExtractFrameWorkThread.stopExtract(); + } + if (mUIHandler != null) + mUIHandler.removeCallbacksAndMessages(null); + if (handler != null) handler.removeCallbacksAndMessages(null); + if (!TextUtils.isEmpty(OutPutFileDirPath)) { + PictureUtils.deleteFile(new File(OutPutFileDirPath)); + } + } + + /** + * 裁剪视频本地路径 + * + * @param context + * @param dirName + * @param fileNamePrefix + * @return + */ + public static String getTrimmedVideoPath(Context context, String dirName, String fileNamePrefix) { + String finalPath = ""; + String dirPath = ""; + if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { + dirPath = context.getExternalCacheDir() + File.separator + dirName; // /mnt/sdcard/Android/data//files/... + } else { + dirPath = context.getCacheDir() + File.separator + dirName; // /data/data//files/... + } + File file = new File(dirPath); + if (!file.exists()) { + file.mkdirs(); + } + finalPath = file.getAbsolutePath(); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()) + .format(new Date()); + String outputName = fileNamePrefix + timeStamp + ".mp4"; + finalPath = finalPath + "/" + outputName; + return finalPath; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditAdapter.java new file mode 100644 index 0000000..7448d92 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditAdapter.java @@ -0,0 +1,76 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.content.Context; +import androidx.recyclerview.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; + + +import com.bumptech.glide.Glide; +import com.fengliyan.tianlesue.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/3/2-下午7:46 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class VideoEditAdapter extends RecyclerView.Adapter { + private List lists = new ArrayList<>(); + private LayoutInflater inflater; + + private int itemW; + private Context context; + + public VideoEditAdapter(Context context, int itemW) { + this.context = context; + this.inflater = LayoutInflater.from(context); + this.itemW = itemW; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new EditViewHolder(inflater.inflate(R.layout.video_item, parent, false)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + EditViewHolder viewHolder = (EditViewHolder) holder; + /*Glide.with(context) + .load("file://" + lists.get(position).path) + .into(viewHolder.img);*/ + Glide.with(context).load("file://" + lists.get(position).path).into(viewHolder.img); + } + + @Override + public int getItemCount() { + return lists.size(); + } + + private final class EditViewHolder extends RecyclerView.ViewHolder { + public ImageView img; + + EditViewHolder(View itemView) { + super(itemView); + img = (ImageView) itemView.findViewById(R.id.id_image); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) img.getLayoutParams(); + layoutParams.width = itemW; + img.setLayoutParams(layoutParams); + } + } + + public void addItemVideoInfo(VideoEditInfo info) { + lists.add(info); + notifyItemInserted(lists.size()); + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditInfo.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditInfo.java new file mode 100644 index 0000000..db44d9c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoEditInfo.java @@ -0,0 +1,31 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import java.io.Serializable; + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/3/2-下午8:52 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class VideoEditInfo implements Serializable { + + public String path; //图片的sd卡路径 + public long time;//图片所在视频的时间 毫秒 + + public VideoEditInfo() { + } + + + @Override + public String toString() { + return "VideoEditInfo{" + + "path='" + path + '\'' + + ", time='" + time + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoExtractFrameAsyncUtils.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoExtractFrameAsyncUtils.java new file mode 100644 index 0000000..29bc883 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoExtractFrameAsyncUtils.java @@ -0,0 +1,124 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.media.MediaMetadataRetriever; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +/** + * ================================================ + * 作 者:顾修忠-guxiuzhong@youku.com/gfj19900401@163.com + * 版 本: + * 创建日期:2017/3/2-下午7:06 + * 描 述: + * 修订历史: + * ================================================ + */ + +public class VideoExtractFrameAsyncUtils { + + private Handler mHandler; + private int extractW; + private int extractH; + + public VideoExtractFrameAsyncUtils(int extractW, int extractH, Handler mHandler) { + this.mHandler = mHandler; + this.extractW = extractW; + this.extractH = extractH; + } + + public void getVideoThumbnailsInfoForEdit(String videoPath, String OutPutFileDirPath, long startPosition, long endPosition, int thumbnailsCount) { + MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever(); + metadataRetriever.setDataSource(videoPath); + long interval; + if (thumbnailsCount > 1) { + interval = (endPosition - startPosition) / (thumbnailsCount - 1); + } else { + interval = (endPosition - startPosition) / thumbnailsCount; + } + for (int i = 0; i < thumbnailsCount; i++) { + if (stop) { + Log.d("ExtractFrame", "-------ok-stop-stop-->>>>>>>>>"); + metadataRetriever.release(); + break; + } + long time = startPosition + interval * i; + if (i == thumbnailsCount - 1) { + if (interval > 1000) { + String path = extractFrame(metadataRetriever, endPosition - 800, OutPutFileDirPath); + sendAPic(path, endPosition - 800); + } else { + String path = extractFrame(metadataRetriever, endPosition, OutPutFileDirPath); + sendAPic(path, endPosition); + } + } else { + String path = extractFrame(metadataRetriever, time, OutPutFileDirPath); + sendAPic(path, time); + } + } + metadataRetriever.release(); + } + + /** + * 成功一张add一张 + * + * @param path path + * @param time time + */ + private void sendAPic(String path, long time) { + VideoEditInfo info = new VideoEditInfo(); + info.path = path; + info.time = time; + Message msg = mHandler.obtainMessage(ExtractFrameWorkThread.MSG_SAVE_SUCCESS); + msg.obj = info; + mHandler.sendMessage(msg); + } + + private String extractFrame(MediaMetadataRetriever metadataRetriever, long time, String OutPutFileDirPath) { + Bitmap bitmap = metadataRetriever.getFrameAtTime(time * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); + if (bitmap != null) { + Bitmap bitmapNew = scaleImage(bitmap); + String path = PictureUtils.saveImageToSDForEdit(bitmapNew, OutPutFileDirPath, System.currentTimeMillis() + "_" + time + PictureUtils.POSTFIX); + if (bitmapNew != null && !bitmapNew.isRecycled()) { + bitmapNew.recycle(); + bitmapNew = null; + } + return path; + } + return null; + } + + /** + * 设置固定的宽度,高度随之变化,使图片不会变形 + * + * @param bm Bitmap + * @return Bitmap + */ + private Bitmap scaleImage(Bitmap bm) { + if (bm == null) { + return null; + } + int width = bm.getWidth(); + int height = bm.getHeight(); + float scaleWidth = extractW * 1.0f / width; +// float scaleHeight =extractH*1.0f / height; + Matrix matrix = new Matrix(); + matrix.postScale(scaleWidth, scaleWidth); + Bitmap newBm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, + true); + if (!bm.isRecycled()) { + bm.recycle(); + bm = null; + } + return newBm; + } + + + private volatile boolean stop; + + public void stopExtract() { + stop = true; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoListAdapter.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoListAdapter.java new file mode 100644 index 0000000..99bf1f9 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoListAdapter.java @@ -0,0 +1,183 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Point; +import android.os.Build; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.im.uikit.common.util.sys.TimeUtil; +import com.fengliyan.tianlesue.utils.GlideUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + + +/** + * ying 2020/8/24 + * Describe :视频列表 + */ + +public class VideoListAdapter extends RecyclerView.Adapter { + + private final Activity mContext; + private final int mMargin; + private final RecyclerView mRecycler; + private List mVideos = new ArrayList<>(); + private List mVideoDatas = new ArrayList<>(); + private onVideoClickListener mOnVideoClickListener; + private boolean mB; + + public VideoListAdapter(Activity activity, RecyclerView recycler, int margin) { + mContext = activity; + mMargin = margin; + mRecycler = recycler; + final int spanCount = 2; + final StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.VERTICAL); + staggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE); + mRecycler.setLayoutManager(staggeredGridLayoutManager); + HashMap stringIntegerHashMap = new HashMap<>(); + stringIntegerHashMap.put(RecyclerViewSpacesItemDecoration.TOP_DECORATION, mMargin);//top间距 + stringIntegerHashMap.put(RecyclerViewSpacesItemDecoration.BOTTOM_DECORATION, mMargin);//底部间距 + stringIntegerHashMap.put(RecyclerViewSpacesItemDecoration.LEFT_DECORATION, mMargin);//左间距 + stringIntegerHashMap.put(RecyclerViewSpacesItemDecoration.RIGHT_DECORATION, mMargin);//右间距 + mRecycler.addItemDecoration(new RecyclerViewSpacesItemDecoration(stringIntegerHashMap)); + recycler.setAdapter(this); + recycler.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + int[] first = new int[spanCount]; + staggeredGridLayoutManager.findFirstCompletelyVisibleItemPositions(first); + if (newState == RecyclerView.SCROLL_STATE_IDLE && (first[0] == 1 || first[1] == 1)) { + staggeredGridLayoutManager.invalidateSpanAssignments(); + } + } + }); + } + + public void setData(List videos) { + mVideos.clear(); + mVideos.addAll(videos); + notifyDataSetChanged(); + + } + + public void setData(List videos, boolean b) { + mB = true; + mVideoDatas.clear(); + mVideoDatas.addAll(videos); + notifyDataSetChanged(); + } + + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new MyHolder(View.inflate(parent.getContext(), R.layout.activity_video_list_item, null)); + } + + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + final MyHolder myHolder = (MyHolder) holder; + if (mB) { + WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + int width = 0; + int height = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + Point size = new Point(); + wm.getDefaultDisplay().getSize(size); + width = size.x; + height = size.y; + } else { + width = wm.getDefaultDisplay().getWidth(); + height = wm.getDefaultDisplay().getHeight(); + } + ViewGroup.LayoutParams layoutParams = myHolder.mImage.getLayoutParams(); + layoutParams.width = width / 2; + layoutParams.height = width / 2; + myHolder.mImage.setLayoutParams(layoutParams); + myHolder.mImage.setScaleType(ImageView.ScaleType.CENTER_CROP); + String thumbnailspath = mVideoDatas.get(holder.getAdapterPosition()).thumbnailspath; + // if (TextUtils.isEmpty(thumbnailspath)) { + GlideUtils.showVideoLocal(mContext, myHolder.mImage, mVideoDatas.get(holder.getAdapterPosition()).path); + int invs = (int) (mVideoDatas.get(holder.getAdapterPosition()).duration / 1000); + myHolder.mTime.setVisibility(View.VISIBLE); + if (mVideoDatas.get(holder.getAdapterPosition()).duration <= 0) { + myHolder.mTime.setText("未知"); + } else { + myHolder.mTime.setText(TimeUtil.secToTime(invs)); + } + + // Glide.with(mContext) + // .load(mVideoDatas.get(holder.getAdapterPosition()).path) + // .into(myHolder.mImage); + // } else + // myHolder.mImage.setImageURI(Uri.parse(thumbnailspath)); +// } else { +// +// GlideUtils.showVideo(mContext, myHolder.mImage, mVideos.get(holder.getAdapterPosition()).getUrl(), mMargin); + } +// +// + myHolder.mImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mOnVideoClickListener == null) { +// Intent intent = new Intent(mContext, VideoPlayActivity.class); +// intent.putExtra("video_id", mVideos.get(holder.getAdapterPosition()).getVideo_id()); +// mContext.startActivity(intent); + } else { + mOnVideoClickListener.onVideoClick(holder.getAdapterPosition()); + } + } + }); + } + + @Override + public int getItemCount() { + return mB ? mVideoDatas.size() : mVideos.size(); + } + + @Override + public long getItemId(int position) { + return position; + } + + class MyHolder extends RecyclerView.ViewHolder { + + public ImageView mImage; + public TextView mTime; + + public MyHolder(View itemView) { + super(itemView); + mImage = itemView.findViewById(R.id.video_list_item_image); + itemView.findViewById(R.id.video_list_item_play).setVisibility(View.VISIBLE); + mTime = itemView.findViewById(R.id.video_list_item_by); + } + } + + //视频点击 + public interface onVideoClickListener { + void onVideoClick(int i); + } + + public void setOnVideoClickListener(onVideoClickListener onVideoClickListener) { + mOnVideoClickListener = onVideoClickListener; + } +} + diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoSelectActivity.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoSelectActivity.java new file mode 100644 index 0000000..ae242c6 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/video/VideoSelectActivity.java @@ -0,0 +1,377 @@ +package com.fengliyan.tianlesue.view.settings.video; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.drawable.ColorDrawable; +import android.media.MediaPlayer; +import android.os.Bundle; +import android.provider.MediaStore; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.GridLayout; +import android.widget.ListPopupWindow; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.VideoView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.fengliyan.tianlesue.R; +import com.fengliyan.tianlesue.view.base.BaseActivity; +import com.fengliyan.uikit.emoji.utils.ScreenUtil; +import com.fengliyan.uikit.photopicker.utils.ScreenUtils; +import com.fengliyan.uikit.title.Title; + +import java.util.ArrayList; +import java.util.List; + + +public class VideoSelectActivity extends BaseActivity { + private static final String TAG = "VideoSelectActivity"; + private RecyclerView mRecyclerView; + private VideoView mVideoView; + private View mVideoLayout; + private String mPath; + private ListPopupWindow mFolderPopupWindow; + private View mPopupAnchorView; + private List mVideoS; + private List mVideo = new ArrayList<>();//总数 + private Button mCategory; + private List mFolderS = new ArrayList() { + { + add("所有视频"); + } + }; + private VideoListAdapter mAdapter; + + private int type = 0; + public static final int TYPE_VIDEO_CUT = 1; + public static final int TYPE_VIDEO_NOT_CUT = 0; + + public static void launchForResult(Activity activity, int action_type, int requestCode) { + Intent intent = new Intent(activity, VideoSelectActivity.class); + intent.putExtra("action_type", action_type); + activity.startActivityForResult(intent, requestCode); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_video_select); + if (getIntent().hasExtra("action_type")) { + type = getIntent().getIntExtra("action_type", 0); + } + initTitle(); + initView(); + createPopupFolderList(); + } + + private void createPopupFolderList() { + Point point = ScreenUtils.getScreenSize(this); + int width = point.x; + int height = (int) (point.y * (4.5f / 8.0f)); + mFolderPopupWindow = new ListPopupWindow(this); + mFolderPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE)); + mFolderPopupWindow.setAdapter(new BaseAdapter() { + @Override + public int getCount() { + return mFolderS.size(); + } + + @Override + public Object getItem(int position) { + return mFolderS.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + TextView textView; + if (convertView == null) { + textView = new TextView(parent.getContext()); + ViewGroup.LayoutParams layoutParams = textView.getLayoutParams(); + if (layoutParams == null) + layoutParams = new GridLayout.LayoutParams(); + layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; + layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; + textView.setLayoutParams(layoutParams); + textView.setTextSize(20); + textView.setPadding(ScreenUtil.dip2px(16), 0, 0, ScreenUtil.dip2px(10)); + convertView = textView; + } else { + textView = (TextView) convertView; + } + textView.setText(mFolderS.get(position)); + textView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mVideoS.clear(); + for (MediaDataBean bean : mVideo) { + if (bean.folder.equals(mFolderS.get(position))) { + mVideoS.add(bean); + } + } + if (mVideoS.size() == 0) { + mVideoS.addAll(mVideo); + } + + mAdapter.setData(mVideoS, true); + mCategory.setText(mFolderS.get(position)); + mFolderPopupWindow.dismiss(); + } + }); + return convertView; + } + }); + mFolderPopupWindow.setContentWidth(width); + mFolderPopupWindow.setWidth(width); + mFolderPopupWindow.setHeight(height); + mFolderPopupWindow.setAnchorView(mPopupAnchorView); + mFolderPopupWindow.setModal(true); + } + + private void initView() { + mRecyclerView = findViewById(R.id.recycler_view); + mVideoView = findViewById(R.id.videoView); + mVideoLayout = findViewById(R.id.videoLayout); + mPopupAnchorView = findViewById(R.id.footer); + mCategory = findViewById(R.id.category_btn); + mCategory.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mFolderPopupWindow.isShowing()) + mFolderPopupWindow.dismiss(); + else + mFolderPopupWindow.show(); + } + }); + + mAdapter = new VideoListAdapter(this, mRecyclerView, 3); + getVideo(VideoSelectActivity.this, new DataCallback() { + @Override + public void onSuccess(List folders) { + mVideoS = folders; + runOnUiThread(new Runnable() { + @Override + public void run() { + if (mVideoS != null && !mVideoS.isEmpty()) { + mVideo.addAll(mVideoS); + mAdapter.setData(mVideoS, true); + } + } + }); + } + }); + + mAdapter.setOnVideoClickListener(new VideoListAdapter.onVideoClickListener() { + @Override + public void onVideoClick(int i) { + if (mVideoLayout.getVisibility() == View.GONE) { + mPath = mVideoS.get(i).path; + //Toast.makeText(VideoSelectActivity.this, ""+video.get(i).duration, Toast.LENGTH_SHORT).show(); + if (type == TYPE_VIDEO_CUT && mVideoS.get(i).duration > 15000) { + Intent intent = new Intent(getBaseContext(), VideoEditActivity.class); + intent.putExtra("VideoPath", mPath); + startActivityForResult(intent, 21); + } else { + playVideo(); + } + } + /*mVideoLayout.setVisibility(View.VISIBLE); + mVideoView.setVideoPath(mPath); + mVideoView.start();*/ + } + }); + } + + private void playVideo() { + if (!mVideoView.isPlaying()) { + mVideoLayout.setVisibility(View.VISIBLE); + mVideoView.setVideoPath(mPath); + mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mp) { + mVideoView.start(); + } + }); + mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + mVideoView.setVideoPath(mPath); + mVideoView.start(); + } + }); + mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() { + @Override + public boolean onError(MediaPlayer mp, int what, int extra) { + Toast.makeText(VideoSelectActivity.this, "打开视频失败", Toast.LENGTH_SHORT).show(); + finishActivity(); + return true; + } + }); + } + } + + + private void initTitle() { + getCustomTitle().setTitleWhite("", "", getString(R.string.app_name), new Title.OnFunctionalAreaClickListener() { + @Override + public void onLeftClick(View v) { + + } + + @Override + public void onRightClick(View v) { + + } + }); + TextView leftView = (TextView) findViewById(com.fengliyan.uikit.R.id.left_text); + leftView.setTextColor(getResources().getColor(R.color.colorAccent)); + } + + @Override + public void finishActivity() { + if (mVideoLayout.getVisibility() == View.VISIBLE) { + mVideoView.stopPlayback(); + mVideoView.setOnCompletionListener(null); + mVideoView.suspend(); + mVideoLayout.setVisibility(View.GONE); + } else { + super.finishActivity(); + } + } + + public interface DataCallback { + void onSuccess(List folders); + } + + public void getVideo(Context context, DataCallback callback) { + new Thread(new Runnable() { + @Override + public void run() { + List list = null; + String[] thumbColumns = {MediaStore.Video.Thumbnails.DATA, + MediaStore.Video.Thumbnails.VIDEO_ID}; + Cursor cursor = context.getContentResolver().query( + MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, + null, MediaStore.MediaColumns.DATE_ADDED + " DESC"); + String ss = ""; + if (cursor != null) { + list = new ArrayList(); + while (cursor.moveToNext()) { + int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)); + String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE)); + String album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.ALBUM)); + String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.ARTIST)); + String displayName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)); + String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE)); + String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)); + long duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)); + long size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)); + String thumbnailspath = ""; + Cursor thumbCursor = context.getContentResolver().query( + MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI, + thumbColumns, MediaStore.Video.Thumbnails.VIDEO_ID + + "=" + id, null, null); + if (thumbCursor != null) { + if (thumbCursor.moveToFirst()) { + thumbnailspath = thumbCursor.getString(thumbCursor.getColumnIndex(MediaStore.Video.Thumbnails.DATA)); + } + } + MediaDataBean video = new MediaDataBean(); + video.title = title; + video.size = size; + video.path = path; + video.duration = duration; + video.id = id; + video.album = album; + video.artist = artist; + video.displayName = displayName; + video.mimeType = mimeType; + video.thumbnailspath = thumbnailspath; + String[] split = path.split("/"); + video.folder = split[split.length - 2]; + + if (!ss.contains(video.folder)) { + ss += video.folder; + mFolderS.add(video.folder); + } + + list.add(video); + } + cursor.close(); + if (callback != null) { + callback.onSuccess(list); + } + } + } + }).start(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + finishActivity(); + return true; + } + return super.onKeyUp(keyCode, event); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 21 && data != null) { + //setResult(22, data); + setResult(RESULT_OK, data); + finish(); + } + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.videoButton: + //上传 然后回调给编辑界面 +// File file = new File(mPath); +// if (file.length() > 5 * 1024 * 1024) { +// MaleToast.showMessage(this, "文件大小超出5M"); +// return; +// } + Intent intent = new Intent(); + intent.putExtra("VideoPath", mPath); + setResult(RESULT_OK, intent); + finish(); + break; + } + } + + + public class MediaDataBean { + public int id; + public String mimeType; + public String album; + public String artist; + public String title; + public String displayName; + public Long size; + public String path; + public String thumbnailspath; //缩略图 + public Long duration; + public String folder; //文件夹 + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/wechat/PayResultListener.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/wechat/PayResultListener.java new file mode 100644 index 0000000..a72985f --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/wechat/PayResultListener.java @@ -0,0 +1,15 @@ +package com.fengliyan.tianlesue.view.settings.wechat; + +/** + * Created by zhangbin on 2018/12/17. + */ + +public interface PayResultListener { + + void onPaySuccess(); + + void onPayFailed(); + + void onPayCancel(); + +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/view/settings/wechat/WeChatPay.java b/app/src/main/java/com/fengliyan/tianlesue/view/settings/wechat/WeChatPay.java new file mode 100644 index 0000000..bc4078c --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/view/settings/wechat/WeChatPay.java @@ -0,0 +1,69 @@ +package com.fengliyan.tianlesue.view.settings.wechat; + +import android.content.Context; + +import com.fengliyan.tianlesue.controller.constant.Constant; +import com.fengliyan.uikit.toast.MaleToast; +import com.tencent.mm.opensdk.modelbase.BaseReq; +import com.tencent.mm.opensdk.modelbase.BaseResp; +import com.tencent.mm.opensdk.modelpay.PayReq; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; + +/** + * Created by Leo on 2017/9/27. + */ + +public class WeChatPay implements IWXAPIEventHandler { + + private static WeChatPay mHandler; + private PayResultListener mPayResultListener; + + public static void pay(Context context, PayReq request, PayResultListener listener) { + mHandler = new WeChatPay(); + mHandler.mPayResultListener = listener; + final IWXAPI wxApi = WXAPIFactory.createWXAPI(context, Constant.WECHAT_APP_ID); + //先检测是否安装了微信 + boolean isWXAppInstalledAndSupported = wxApi.isWXAppInstalled(); + if (isWXAppInstalledAndSupported) { + wxApi.registerApp(Constant.WECHAT_APP_ID); + wxApi.sendReq(request); + } else { +// ToastUtil.st("请先安装微信客户端"); + MaleToast.showMessage(context, "请先安装微信客户端"); + } + } + + + @Override + public void onReq(BaseReq baseReq) { + //微信调用app + } + + @Override + public void onResp(BaseResp baseResp) { + int errCode = baseResp.errCode; + switch (errCode) { + case BaseResp.ErrCode.ERR_OK: + mPayResultListener.onPaySuccess(); + break; + case BaseResp.ErrCode.ERR_COMM: + mPayResultListener.onPayFailed(); + break; + case BaseResp.ErrCode.ERR_USER_CANCEL: + mPayResultListener.onPayCancel(); + break; + } + + destroy(); + } + + public static IWXAPIEventHandler getHandler() { + return mHandler; + } + + public static void destroy() { + mHandler = null; + } +} diff --git a/app/src/main/java/com/fengliyan/tianlesue/wxapi/WXEntryActivity.java b/app/src/main/java/com/fengliyan/tianlesue/wxapi/WXEntryActivity.java new file mode 100644 index 0000000..2bd4887 --- /dev/null +++ b/app/src/main/java/com/fengliyan/tianlesue/wxapi/WXEntryActivity.java @@ -0,0 +1,80 @@ +package com.fengliyan.tianlesue.wxapi; + +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +import com.fengliyan.tianlesue.controller.eventBus.PayEvent; +import com.tencent.mm.opensdk.constants.ConstantsAPI; +import com.tencent.mm.opensdk.modelbase.BaseReq; +import com.tencent.mm.opensdk.modelbase.BaseResp; +import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; +import com.umeng.weixin.callback.WXCallbackActivity; + +import de.greenrobot.event.EventBus; + +public class WXEntryActivity extends WXCallbackActivity implements IWXAPIEventHandler { + private IWXAPI api; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// setContentView(R.layout.pay_result); +//"wx24932e45899137eb" + api = WXAPIFactory.createWXAPI(this, "wx99d6a2e2d4967362"); + api.handleIntent(getIntent(), this); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + try { + if (!api.handleIntent(getIntent(), this)) { + finish(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + @Override + public void onReq(BaseReq baseReq) { + com.tencent.mm.opensdk.utils.Log.d("TAG", "onReq: " + baseReq.getType()); + switch (baseReq.getType()) { + case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX: + break; + case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX: +// goToShowMsg((ShowMessageFromWX.Req) baseReq); + break; + default: + break; + } + + finish(); + + } + + @Override + public void onResp(BaseResp resp) { + + if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { + + Log.d("nail","onResp===" + resp.errCode + " " + resp.errStr); + EventBus.getDefault().post(new PayEvent(resp.errCode)); + } + if (resp.getType() == ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM) { + WXLaunchMiniProgram.Resp launchMiniProResp = (WXLaunchMiniProgram.Resp) resp; + String extraData = launchMiniProResp.extMsg; //对应小程序组件