作者 zhangji

直播、我的聊天记录写完

正在显示 44 个修改的文件 包含 920 行增加135 行删除
... ... @@ -27,8 +27,8 @@
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.SecurityTrainMaster"
android:usesCleartextTraffic="true">
<meta-data
... ... @@ -199,6 +199,9 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" />
<activity android:name=".ui.view.bank.activity.AnswerRecordDetailsActivity" />
<activity android:name=".ui.view.bank.activity.WrongQuestionsActivity" />
<activity android:name=".ui.view.mine.activity.ChatRecordActivity" />
<activity android:name=".ui.view.mine.activity.ChatActivity" />
<activity android:name=".ui.view.mine.activity.LiveWebActivity" />
</application>
... ...
... ... @@ -10,7 +10,8 @@ import java.io.File
*/
object Constant {
// const val BASE_URL = "https://security.brofirst.cn/"
const val BASE_URL = "http://security.brofirst.cn/"
// const val BASE_URL = "http://security.brofirst.cn/"
const val BASE_URL = "https://test.mobile.anqixing.com/"
// const val BASE_URL = "http://admin.anqixing.com"
const val USERNAME_KEY = "username"
const val USERID_KEY = "userid"
... ...
... ... @@ -128,11 +128,11 @@ interface LessonApi : ApiService {
@FormUrlEncoded
@POST("/api/lesson/lesson_live")
fun lessonLiveList(
@Field("keyword") keyword: String, // 搜索关键词
@Field("keyword") keyword: String?, // 搜索关键词
@Field("type") type: Int, // 直播类型1=正在直播2=回放直播3=即将开播
@Field("page") page: String,
@Field("page_num") page_num: String,
): Observable<BaseResponse<CommonDataList<CommonPage<LessonLive>>>>
@Field("page") page: Int,
@Field("page_num") page_num: Int,
): Observable<BaseResponse<CommonDataList<CommonPage<LessonLiveBean>>>>
/**
* 直播课程列表
... ...
... ... @@ -3,6 +3,7 @@ package com.br_technology.securitytrain_master.base.network.api
import com.br_technology.securitytrain_master.base.network.response.*
import com.br_technology.securitytrain_master.ui.bean.*
import com.br_technology.securitytrain_master.ui.view.login.bean.LoginBean
import com.br_technology.securitytrain_master.ui.view.mine.bean.ChatRecordBean
import io.reactivex.rxjava3.core.Observable
import retrofit2.http.*
... ... @@ -209,7 +210,6 @@ interface UserApi : ApiService {
/**
* 证件类型
*/
@FormUrlEncoded
@POST("/api/user/cert_list")
fun certClassify(): Observable<BaseResponse<CommonList<CertType>>>
... ... @@ -236,12 +236,11 @@ interface UserApi : ApiService {
@FormUrlEncoded
@POST("/api/user/my_cert_add")
fun certAdd(
// @Field("id") id: Int,
@Field("id") id: Int?,
@Field("cert_id") cert_id: Int,
@Field("image") image: Int,
@Field("image") image: String,
@Field("start_time") start_time: String,
@Field("end_time") end_time: String,
@FieldMap map: HashMap<String, String>
@Field("end_time") end_time: String?
): Observable<BaseResponse<Void>>
/**
... ... @@ -257,6 +256,18 @@ interface UserApi : ApiService {
): Observable<BaseResponse<CommonPage<CertLog>>>
/**
* 教师消息列表
* @param page 页数
* @param page_num 每页显示数量
*/
@FormUrlEncoded
@POST("/api/teachermessage/msg_list")
fun msgList(
@Field("page") page: Int,
@Field("page_num") page_num: Int
): Observable<BaseResponse<CommonDataList<CommonPage<ChatRecordBean>>>>
/**
* 删除证件
* @param id 证件id
*/
... ...
... ... @@ -74,11 +74,11 @@ class LessonRepository(loadState: MutableLiveData<State>) : ApiRepository(loadSt
}
fun lessonLiveList(
keyword: String,
keyword: String?=null,
type: Int,
page: String,
page_num: String,
liveData: MutableLiveData<BaseResponse<CommonDataList<CommonPage<LessonLive>>>>
page: Int,
page_num: Int,
liveData: MutableLiveData<BaseResponse<CommonDataList<CommonPage<LessonLiveBean>>>>
) {
addRequest(lessonService.lessonLiveList(keyword, type, page, page_num), liveData)
}
... ...
... ... @@ -5,6 +5,14 @@ import com.br_technology.securitytrain_master.base.common.State
import com.br_technology.securitytrain_master.base.network.response.*
import com.br_technology.securitytrain_master.ui.bean.*
import com.br_technology.securitytrain_master.ui.view.login.bean.LoginBean
import com.wjx.android.wanandroidmvvm.base.observer.BaseObserver
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.File
import java.net.URLEncoder
/**
* Author by YSir
... ... @@ -12,7 +20,7 @@ import com.br_technology.securitytrain_master.ui.view.login.bean.LoginBean
* description
* PS: Not easy to write code, please indicate.
*/
class UserRepository(loadState: MutableLiveData<State>) : ApiRepository(loadState) {
class UserRepository(val loadState: MutableLiveData<State>) : ApiRepository(loadState) {
fun userCenter(liveData: MutableLiveData<BaseResponse<UserInfo>>) {
addRequest(userService.getUserCenter(), liveData)
... ... @@ -128,15 +136,14 @@ class UserRepository(loadState: MutableLiveData<State>) : ApiRepository(loadStat
}
fun certAdd(
// id: Int,
id: Int?,
cert_id: Int,
image: Int,
image: String,
start_time: String,
end_time: String,
map: HashMap<String, String>,
end_time: String?,
liveData: MutableLiveData<BaseResponse<Void>>
) {
addRequest(userService.certAdd(cert_id, image, start_time, end_time, map), liveData)
addRequest(userService.certAdd(id,cert_id, image, start_time, end_time), liveData)
}
fun certLog(
... ... @@ -158,4 +165,33 @@ class UserRepository(loadState: MutableLiveData<State>) : ApiRepository(loadStat
) {
addRequest(userService.scoreLog(page, page_num), liveData)
}
fun uploadFile(
path: String,
liveData: MutableLiveData<BaseResponse<UploadFileData>>
) {
val imageRequestFile: RequestBody?
var imageBody: MultipartBody.Part? = null
val file = File(path)
if (file.exists()) {
imageRequestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file)
imageBody = MultipartBody.Part.createFormData(
"file",
URLEncoder.encode(file.name, "UTF-8"), imageRequestFile!!
)
}
apiService.uploadFile(imageBody!!)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
BaseObserver(
liveData,
loadState,
this
)
)
}
}
\ No newline at end of file
... ...
... ... @@ -70,6 +70,109 @@ open class LessonLive(
var teacher: Teacher
) : Serializable
data class LessonLiveBean(
val average_study: String,
val company_id: Int,
val create_time: Int,
val create_time_text: String,
val delete_time: Any,
val delete_time_text: String,
val id: Int,
val lesson_id: String,
val lessonlive: LessonLiveEntity,
val name: String,
val playerPcUrl: String,
val playerUrl: String,
val sort_id: String,
val sort_id_text: String,
val train_class_id: Int,
val train_id: Int,
val trainclass: TrainclassBean,
val update_time: Int,
val update_time_text: String
)
data class LessonLiveEntity(
val class_hours: Int,
val company_id: Int,
val content: String,
val create_time: Int,
val create_time_text: String,
val delete_time: Any,
val delete_time_text: String,
val end_time: String,
val id: Int,
val image: String,
val is_open: String,
val is_open_text: String,
val live_status: String,
val live_time: Int,
val live_url: String,
val name: String,
val playback_url: String,
val pos_ids: String,
val score: Int,
val stream_name: String,
val teacher_id: Int,
val type: String,
val type_text: String,
val update_time: Int,
val update_time_text: String,
val webrtc_url: String
)
data class TrainclassBean(
val average_study: String,
val company_id: Int,
val create_time: Int,
val create_time_text: String,
val delete_time: Any,
val delete_time_text: String,
val des: String,
val end_time: Int,
val end_time_text: String,
val id: Int,
val is_exam: String,
val is_exam_text: String,
val is_parctise: String,
val is_parctise_text: String,
val lesson_ids: String,
val lesson_live_ids: String,
val lesson_offline_content: String,
val lesson_offline_ids: String,
val lesson_offline_image: String,
val lesson_times: Int,
val lesson_times_count: Int,
val lesson_word_ids: String,
val lessons: String,
val name: String,
val sort_id: String,
val sort_id_text: String,
val start_time: Int,
val start_time_text: String,
val status: String,
val status_text: String,
val students: Int,
val study_per: String,
val teacher_id: String,
val teachers: Teachers,
val train_id: Int,
val update_time: Int,
val update_time_text: String,
val user_item_pass: Any
)
data class Teachers(
val avatar: String,
val create_time_text: String,
val delete_time_text: String,
val gender_text: String,
val id: Int,
val name: String,
val update_time_text: String
)
open class LessonOffline(
var class_name: String,
var pos_names: String,
... ...
... ... @@ -62,9 +62,14 @@ open class UserCertData(
)
open class CertType(
var id: Int,
var name: String, // 证件名称
var valid: Int, // 有效期
val id:Int,
val company_id:Int,
val name:String,// 证件名称
val valid:Int,// 有效期
val weigh:Int,
val create_time:Int,
val update_time:Int,
val delete_time:Int,
)
open class UserCertDetail(
... ...
... ... @@ -8,6 +8,7 @@ import com.br_technology.securitytrain_master.base.view.BasePagerAdapter
import com.br_technology.securitytrain_master.databinding.ActivityLiveCourseBinding
import com.br_technology.securitytrain_master.ui.view.home.fragment.OnLiveCourseFragment
import com.br_technology.securitytrain_master.ui.view.home.viewmodel.LiveCourseViewModel
import com.br_technology.securitytrain_master.util.sp_job_name
import com.br_technology.securitytrain_master.view.ClassifyPop
import com.br_technology.securitytrain_master.view.listener.ToolBarClickListener
import com.google.android.material.tabs.TabLayout
... ... @@ -41,35 +42,39 @@ class LiveCourseActivity
binding.apply {
toolBar.setRightText("焊工")
toolBar.setRightText(sp_job_name)
toolBar.setRightTextDrawable(
ContextCompat.getDrawable(
baseContext,
R.mipmap.down_arrow
)
)
toolBar.addRightListener(object : ToolBarClickListener {
override fun onClick(view: View) {
if (!classifyPop.isShowing) {
classifyPop.showAsDropDown(view)
}
}
})
// toolBar.addRightListener(object : ToolBarClickListener {
// override fun onClick(view: View) {
// if (!classifyPop.isShowing) {
// classifyPop.showAsDropDown(view)
// }
//
// }
// })
val searchResultAdapter = BasePagerAdapter(
supportFragmentManager,
FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
)
val list =
mutableListOf(OnLiveCourseFragment(),OnLiveCourseFragment(),OnLiveCourseFragment())
mutableListOf(
OnLiveCourseFragment.newInstance(1),
OnLiveCourseFragment.newInstance(2),
OnLiveCourseFragment.newInstance(3)
)
val titles = listOf("正在直播", "回放课程", "即将开播")
searchResultAdapter.addData(list.toMutableList())
searchResultAdapter.addTitle(titles)
viewPager.adapter = searchResultAdapter
tabLayout.setupWithViewPager(viewPager)
tabLayout.addOnTabSelectedListener(object :TabLayout.OnTabSelectedListener{
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
}
... ...
package com.br_technology.securitytrain_master.ui.view.home.adapter
import com.br_technology.securitytrain_master.R
import com.br_technology.securitytrain_master.ui.bean.LessonLiveBean
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
/**
* auth: 张继
* date: 2022/1/27 16:38
* dsc:
* updateInfo:
*/
class LiveAdapter(layoutResId: Int) :
BaseQuickAdapter<LessonLiveBean, BaseViewHolder>(layoutResId) {
override fun convert(holder: BaseViewHolder, item: LessonLiveBean) {
// 视频首贞图片
Glide.with(context)
.load(item.lessonlive.image)
.apply(RequestOptions.bitmapTransform(RoundedCorners(14)))
.into(holder.getView(R.id.video_pic))
val typeName = when (item.lessonlive.live_status) {
"1" -> {
"正在直播"
}
"2" -> {
"回放直播"
}
else -> {
"即将开播"
}
}
holder.setText(R.id.course_name, item.lessonlive.name)
.setText(R.id.name, "${item.trainclass.teachers.name}-${item.trainclass.name}")
.setText(R.id.lesson, "$typeName")
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.home.fragment
import android.content.Intent
import android.os.Bundle
import com.br_technology.securitytrain_master.R
import com.br_technology.securitytrain_master.databinding.FragmentOnliveCourseBinding
import com.br_technology.securitytrain_master.expand.addItemDecoration2
import com.br_technology.securitytrain_master.ui.view.home.adapter.VideoCourseAdapter
import com.br_technology.securitytrain_master.ui.view.home.bean.VideoLessonBean
import com.br_technology.securitytrain_master.ui.bean.LessonLiveBean
import com.br_technology.securitytrain_master.ui.view.home.adapter.LiveAdapter
import com.br_technology.securitytrain_master.ui.view.home.viewmodel.OnLiveCourseFragmentViewModel
import com.br_technology.securitytrain_master.ui.view.mine.activity.LiveWebActivity
import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.LiveWebViewModel
import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleFragment
/**
... ... @@ -14,42 +18,92 @@ import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleFragment
* Description: 初见时你很迷人
*/
class OnLiveCourseFragment
: BaseLifeCycleFragment<OnLiveCourseFragmentViewModel,FragmentOnliveCourseBinding>(FragmentOnliveCourseBinding :: inflate){
private var videoLessonList: MutableList<VideoLessonBean.ListBean.DataBean>? = null
override fun initDataObserver() {
: BaseLifeCycleFragment<OnLiveCourseFragmentViewModel, FragmentOnliveCourseBinding>(
FragmentOnliveCourseBinding::inflate
) {
private var page = 1
private val map = hashMapOf(1 to true, 2 to true, 3 to true)
private var type: Int = 1
private val adapter: LiveAdapter by lazy {
LiveAdapter(R.layout.adapter_video_course)
}
override fun initDataObserver() {
mViewModel.liveData.observe(this) {
if (it.data.list.data.size < 10) {
binding.smartRefresh.setNoMoreData(true)
}
if (page == 1) {
adapter.setNewInstance(it.data.list.data as MutableList<LessonLiveBean>)
} else {
adapter.addData(it.data.list.data)
}
}
}
override fun initData() {
super.initData()
type = arguments?.getInt("type") ?: 1
binding.apply {
smartRefresh.setOnRefreshListener {
page = 1
smartRefresh.setNoMoreData(false)
mViewModel.lessonLiveList(type, page)
smartRefresh.finishRefresh()
}
onlineRecycler.addItemDecoration2(2, 15,24)
val videoCourseAdapter = VideoCourseAdapter(R.layout.adapter_video_course, videoLessonList)
// val list = mutableListOf(
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// VideoCourse(R.mipmap.banner, "10课时", "自动化制作课程", "", "张钧-三岗职位培训班"),
// )
videoLessonList = mutableListOf()
onlineRecycler.adapter = videoCourseAdapter
// videoCourseAdapter.addList(videoLessonList!!)
//
// videoCourseAdapter.addListener(object : OnItemClickListener<VideoLessonBean.ListBean.DataBean> {
//
// override fun onClick(position: Int, data: VideoLessonBean.ListBean.DataBean) {
// startActivity(OnlineDetailActivity :: class.java)
// }
//
// })
smartRefresh.setOnLoadMoreListener {
++page
mViewModel.lessonLiveList(type, page)
smartRefresh.finishLoadMore()
}
onlineRecycler.addItemDecoration2(2, 15, 24)
onlineRecycler.adapter = adapter
adapter.setOnItemClickListener { _, _, position ->
val status = adapter.data.get(position).lessonlive.live_status
if (status == "3") {
showTip("教师未开播")
return@setOnItemClickListener
}
var url = ""
if (status == "2") {
url = adapter.data.get(position).lessonlive.playback_url
}
if (status == "1") {
url = adapter.data.get(position).playerUrl
}
val title = adapter.data.get(position).name
val intent = Intent(requireActivity(), LiveWebActivity::class.java)
intent.putExtra("url", url)
intent.putExtra("title", title)
startActivity(intent)
}
}
}
override fun onResume() {
super.onResume()
if (map[type] == true) {
map[type] = false
binding.smartRefresh.autoRefresh()
}
}
companion object {
fun newInstance(type: Int): OnLiveCourseFragment {
val fragment = OnLiveCourseFragment()
val bundle = Bundle()
bundle.putInt("type", type)
fragment.arguments = bundle
return fragment
}
}
}
\ No newline at end of file
... ...
... ... @@ -10,4 +10,9 @@ import com.br_technology.securitytrain_master.base.repository.ApiRepository
* Description: 初见时你很迷人
*/
class OnLiveCourseFragmentRepository(val loadState: MutableLiveData<State>) : ApiRepository(loadState) {
fun lessonLiveList() {
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.home.viewmodel
import androidx.lifecycle.MutableLiveData
import com.br_technology.securitytrain_master.base.network.response.BaseResponse
import com.br_technology.securitytrain_master.base.network.response.CommonDataList
import com.br_technology.securitytrain_master.base.network.response.CommonPage
import com.br_technology.securitytrain_master.base.repository.LessonRepository
import com.br_technology.securitytrain_master.base.view.BaseViewModel
import com.br_technology.securitytrain_master.ui.bean.LessonLive
import com.br_technology.securitytrain_master.ui.bean.LessonLiveBean
import com.br_technology.securitytrain_master.ui.view.home.repository.OnLiveCourseFragmentRepository
/**
... ... @@ -8,5 +15,12 @@ import com.br_technology.securitytrain_master.ui.view.home.repository.OnLiveCour
* Author: Captain
* Description: 初见时你很迷人
*/
class OnLiveCourseFragmentViewModel : BaseViewModel<OnLiveCourseFragmentRepository>() {
class OnLiveCourseFragmentViewModel : BaseViewModel<LessonRepository>() {
val liveData: MutableLiveData<BaseResponse<CommonDataList<CommonPage<LessonLiveBean>>>> =
MutableLiveData()
fun lessonLiveList(type: Int, page: Int) {
mRepository.lessonLiveList(null, type, page, 20, liveData)
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.activity
import com.br_technology.securitytrain_master.databinding.ActivityChatRecordBinding
import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.ChatRecordViewModel
import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity
/**
* auth: 张继
* date: 2022/1/27 15:00
* dsc:聊天详情
* updateInfo:
*/
class ChatActivity :
BaseLifeCycleActivity<ChatRecordViewModel, ActivityChatRecordBinding>(ActivityChatRecordBinding::inflate) {
override fun initDataObserver() {
}
override fun initData() {
super.initData()
binding.apply {
// chatRv.adapter=
}
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.activity
import com.br_technology.securitytrain_master.databinding.ActivityChatRecordBinding
import com.br_technology.securitytrain_master.ui.view.mine.adapter.ChatRecordAdapter
import com.br_technology.securitytrain_master.ui.view.mine.bean.ChatRecordBean
import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.ChatRecordViewModel
import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity
/**
* auth: 张继
* date: 2022/1/27 13:28
* dsc:聊天记录
* updateInfo:
*/
class ChatRecordActivity :
BaseLifeCycleActivity<ChatRecordViewModel, ActivityChatRecordBinding>(ActivityChatRecordBinding::inflate) {
private val chatRecordAdapter: ChatRecordAdapter by lazy {
ChatRecordAdapter()
}
private var page = 1
override fun initDataObserver() {
mViewModel.liveData.observe(this) {
if (it.data.list.data.size < 10) {
binding.smartRefresh.setNoMoreData(true)
}
if (page == 1) {
chatRecordAdapter.setNewInstance(it.data.list.data as MutableList<ChatRecordBean>)
} else {
chatRecordAdapter.addData(it.data.list.data)
}
}
}
override fun initData() {
super.initData()
binding.apply {
smartRefresh.autoRefresh()
// 刷新
smartRefresh.setOnRefreshListener {
smartRefresh.setNoMoreData(false)
page = 1
mViewModel.msgList(page)
smartRefresh.finishRefresh()
}
// 加载
smartRefresh.setOnLoadMoreListener {
++page
mViewModel.msgList(page)
smartRefresh.finishLoadMore()
}
chatRv.adapter = chatRecordAdapter
}
chatRecordAdapter.setOnItemClickListener { adapter, view, position ->
startActivity(ChatActivity::class.java)
}
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.activity
import android.graphics.Color
import android.view.View
import android.widget.TimePicker
import androidx.recyclerview.widget.RecyclerView
import com.bigkoo.pickerview.builder.TimePickerBuilder
import com.bigkoo.pickerview.configure.PickerOptions
import com.bigkoo.pickerview.listener.OnTimeSelectListener
import com.bigkoo.pickerview.view.TimePickerView
import com.br_technology.securitytrain_master.R
import com.br_technology.securitytrain_master.databinding.ActivityCredentialsUploadBinding
import com.br_technology.securitytrain_master.expand.dp2px
import com.br_technology.securitytrain_master.expand.loadPicNoCrop
import com.br_technology.securitytrain_master.expand.screenWidth
import com.br_technology.securitytrain_master.ui.bean.CertType
import com.br_technology.securitytrain_master.ui.bean.UserCertDetail
import com.br_technology.securitytrain_master.ui.view.mine.adapter.CertTypeAdapter
import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.CredentialsUpLoadViewModel
import com.br_technology.securitytrain_master.util.GlideEnginePic
import com.br_technology.securitytrain_master.util.PoPWindowUtil
import com.br_technology.securitytrain_master.view.CenterToast
import com.google.gson.Gson
import com.luck.picture.lib.PictureSelector
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.listener.OnResultCallbackListener
import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
/**
... ... @@ -28,40 +34,119 @@ import java.util.*
class CredentialsUpLoadActivity :
BaseLifeCycleActivity<CredentialsUpLoadViewModel, ActivityCredentialsUploadBinding>(
ActivityCredentialsUploadBinding::inflate
), View.OnClickListener {
) {
private var path: String = ""
private var dateTime: String = ""
private var typeId: Int = 0
private var id: Int? = 0
private var endTime: String? = ""
private val certTypeAdapter: CertTypeAdapter by lazy {
CertTypeAdapter()
}
override fun initDataObserver() {
mViewModel.liveData.observe(this) {
certTypeAdapter.setNewInstance(it.data.list as MutableList<CertType>)
}
mViewModel.picLiveData.observe(this) {
// 图片地址
path = it.data.fullurl
}
mViewModel.certLiveData.observe(this) {
// 根据类型跳转
binding.tvUpload.isClickable = true
val title = CenterToast(this).setTitle("上传成功")
title.setOnDismissListener {
finish()
}
title.show()
}
}
override fun initData() {
super.initData()
mViewModel.certClassify()
val json = intent.getStringExtra("json")
if (json?.isNotEmpty() == true) {
val user = Gson().fromJson<UserCertDetail>(json, UserCertDetail::class.java)
// 证件类型id
typeId = user.cert.id
// 证件照片地址
path = user.image_text
// 开始时间
dateTime = user.start_time
// 证件id
id = user.id
// 结束时间
endTime = user.end_time
// 适配宽度
val width = mRootView.screenWidth() - 64.dp2px()
binding.uploadPic.loadPicNoCrop(path, width, 208.dp2px())
// 开始时间
binding.uploadTime.text = dateTime
// 证件名称
binding.certTypeTv.text = user.cert.name
}
id = if (id == 0) {
null
} else {
id
}
endTime = if (endTime?.isEmpty() == true) {
null
} else {
endTime
}
binding.apply {
tvUpload.setOnClickListener(this@CredentialsUpLoadActivity)
// 上传照片
tvUpload.setOnClickListener {
tvUpload.isClickable = false
if (path.isEmpty()) {
showTip("请选择证件照片")
tvUpload.isClickable = true
return@setOnClickListener
}
if (typeId == 0) {
tvUpload.isClickable = true
showTip("请选择证件类型")
return@setOnClickListener
}
if (dateTime.isEmpty()) {
tvUpload.isClickable = true
showTip("请选择证件开始时间")
return@setOnClickListener
}
mViewModel.certAdd(id, typeId, path, dateTime, endTime)
}
// 选择图片
uploadPic.setOnClickListener {
selectPicture()
// PictureSelector.create(this@CredentialsUpLoadActivity)
}
// 选择时间
selectionPeriod.setOnClickListener {
selectTime()
}
}
// // 根据类型跳转
// CenterToast(this@MyCredentialsActivity).setTitle("上传成功").show()
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.tv_upload -> {
// 选择证件类型
selectType.setOnClickListener {
val initPopWindow = PoPWindowUtil.get()
.initPopWindow(baseContext, selectType, R.layout.dialog_cert_type)
val certRv = initPopWindow.findViewById<RecyclerView>(R.id.cert_rv)
certRv.adapter = certTypeAdapter
}
}
certTypeAdapter.setOnItemClickListener { _, _, position ->
val certType = certTypeAdapter.data[position]
binding.certTypeTv.text = certType.name
typeId = certType.id
PoPWindowUtil.get().dismissPoPWindow()
}
}
private fun selectPicture() {
... ... @@ -71,24 +156,28 @@ class CredentialsUpLoadActivity :
.imageEngine(GlideEnginePic.createGlideEngine())
.forResult(object : OnResultCallbackListener<LocalMedia> {
override fun onResult(result: MutableList<LocalMedia>?) {
path = result?.get(0)?.realPath ?: ""
val path = result?.get(0)?.realPath ?: ""
if (path.isNotEmpty()) {
binding.uploadPic.loadPicNoCrop(path, width, 208.dp2px())
mViewModel.uploadFile(path)
}
}
override fun onCancel() {
}
override fun onCancel() {}
})
}
private fun selectTime() {
TimePickerBuilder(baseContext, object : OnTimeSelectListener {
override fun onTimeSelect(date: Date?, v: View?) {
}
}).build().show()
TimePickerBuilder(this) { date, _ ->
val dateFormat = SimpleDateFormat("yyyy-MM-dd")
val format = dateFormat.format(date)
dateTime = format
binding.uploadTime.text = format
}.setTitleText("选择日期")
.setTitleBgColor(Color.parseColor("#ffffff"))
.setCancelColor(Color.parseColor("#000000"))
.setSubmitColor(Color.parseColor("#000000"))
.build().show()
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.activity
import com.br_technology.securitytrain_master.databinding.ActivityLiveWebBinding
import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.LiveWebViewModel
import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity
/**
* auth: 张继
* date: 2022/1/27 17:23
* dsc:
* updateInfo:
*/
class LiveWebActivity :
BaseLifeCycleActivity<LiveWebViewModel, ActivityLiveWebBinding>(ActivityLiveWebBinding::inflate) {
override fun initDataObserver() {
}
override fun initData() {
super.initData()
val url = intent.getStringExtra("url") ?: ""
val title = intent.getStringExtra("title")?:""
binding.apply {
toolBar.setTitle(title)
liveWeb.loadUrl(url)
}
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.activity
import android.content.Intent
import com.br_technology.securitytrain_master.databinding.ActivityMyCredentialsDetailBinding
import com.br_technology.securitytrain_master.expand.loadPic
import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.MyCredentialDetailViewModel
import com.google.gson.Gson
import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity
/**
... ... @@ -14,8 +16,12 @@ class MyCredentialsDetailActivity :
BaseLifeCycleActivity<MyCredentialDetailViewModel, ActivityMyCredentialsDetailBinding>(
ActivityMyCredentialsDetailBinding::inflate
) {
private var json = ""
override fun initDataObserver() {
mViewModel.liveData.observe(this) {
json = Gson().toJson(it.data.detail)
binding.apply {
pictureIv.loadPic(it.data.detail.image_text)
certName.text = it.data.detail.cert.name
... ... @@ -30,8 +36,10 @@ class MyCredentialsDetailActivity :
super.initData()
binding.apply {
tvReUpload.setOnClickListener {
val intent = Intent(baseContext, CredentialsUpLoadActivity::class.java)
intent.putExtra("json", json)
//重新上传
startActivity(CredentialsUpLoadActivity::class.java)
startActivity(intent)
}
}
}
... ...
package com.br_technology.securitytrain_master.ui.view.mine.adapter
import com.br_technology.securitytrain_master.R
import com.br_technology.securitytrain_master.ui.bean.CertType
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
/**
* auth: 张继
* date: 2022/1/27 10:25
* dsc:
* updateInfo:
*/
class CertTypeAdapter:BaseQuickAdapter<CertType,BaseViewHolder>(R.layout.adapter_cert_type) {
override fun convert(holder: BaseViewHolder, item: CertType) {
holder.setText(R.id.cert_name,item.name)
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.adapter
import com.br_technology.securitytrain_master.R
import com.br_technology.securitytrain_master.ui.view.mine.bean.ChatRecordBean
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
/**
* auth: 张继
* date: 2022/1/27 14:09
* dsc:
* updateInfo:
*/
class ChatRecordAdapter :
BaseQuickAdapter<ChatRecordBean, BaseViewHolder>(R.layout.adapter_chat_record) {
override fun convert(holder: BaseViewHolder, item: ChatRecordBean) {
holder.setText(R.id.chat_name, item.teacher.name)
.setText(R.id.chat_content, item.last_content)
.setText(R.id.chat_date, item.update_time)
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.bean
/**
* auth: 张继
* date: 2022/1/27 13:58
* dsc:
* updateInfo:
*/
data class ChatRecordBean(
val id: Int,
val is_read: String,
val last_content: String,
val teacher: Teacher,
val teacher_id: Int,
val update_time: String
)
data class Teacher(
val create_time_text: String,
val delete_time_text: String,
val gender_text: String,
val name: String,
val update_time_text: String
)
\ No newline at end of file
... ...
... ... @@ -136,6 +136,7 @@ class MineFragment
R.id.rl_mine_liaotianjilu -> {
//我的聊天记录
startActivity(ChatRecordActivity::class.java)
}
R.id.rl_mine_tousuyujianyi -> {
... ...
package com.br_technology.securitytrain_master.ui.view.mine.repository
import androidx.lifecycle.MutableLiveData
import com.br_technology.securitytrain_master.base.common.State
import com.br_technology.securitytrain_master.base.network.response.BaseResponse
import com.br_technology.securitytrain_master.base.network.response.CommonDataList
import com.br_technology.securitytrain_master.base.network.response.CommonPage
import com.br_technology.securitytrain_master.base.repository.ApiRepository
import com.br_technology.securitytrain_master.ui.view.mine.bean.ChatRecordBean
/**
* auth: 张继
* date: 2022/1/27 13:50
* dsc:
* updateInfo:
*/
class ChatRepository(val loadState: MutableLiveData<State>) : ApiRepository(loadState) {
fun msgList(
page: Int,
liveData: MutableLiveData<BaseResponse<CommonDataList<CommonPage<ChatRecordBean>>>>
) {
addRequest(userService.msgList(page, 20), liveData)
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.viewmodel
import androidx.lifecycle.MutableLiveData
import com.br_technology.securitytrain_master.base.network.response.BaseResponse
import com.br_technology.securitytrain_master.base.network.response.CommonDataList
import com.br_technology.securitytrain_master.base.network.response.CommonPage
import com.br_technology.securitytrain_master.base.view.BaseViewModel
import com.br_technology.securitytrain_master.ui.view.mine.bean.ChatRecordBean
import com.br_technology.securitytrain_master.ui.view.mine.repository.ChatRepository
/**
* auth: 张继
* date: 2022/1/27 13:31
* dsc:
* updateInfo:
*/
class ChatRecordViewModel : BaseViewModel<ChatRepository>() {
val liveData: MutableLiveData<BaseResponse<CommonDataList<CommonPage<ChatRecordBean>>>> =
MutableLiveData()
fun msgList(page: Int) {
mRepository.msgList(page, liveData)
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.viewmodel
import androidx.lifecycle.MutableLiveData
import com.br_technology.securitytrain_master.base.network.response.BaseResponse
import com.br_technology.securitytrain_master.base.network.response.CommonList
import com.br_technology.securitytrain_master.base.repository.UserRepository
import com.br_technology.securitytrain_master.base.view.BaseViewModel
import com.br_technology.securitytrain_master.ui.bean.CertType
import com.br_technology.securitytrain_master.ui.bean.UploadFileData
import com.br_technology.securitytrain_master.ui.view.mine.repository.CredentialsUpLoadRepository
/**
... ... @@ -8,5 +14,31 @@ import com.br_technology.securitytrain_master.ui.view.mine.repository.Credential
* Author: Captain
* Description: 初见时你很迷人
*/
class CredentialsUpLoadViewModel : BaseViewModel<CredentialsUpLoadRepository>() {
class CredentialsUpLoadViewModel : BaseViewModel<UserRepository>() {
val liveData: MutableLiveData<BaseResponse<CommonList<CertType>>> = MutableLiveData()
val picLiveData: MutableLiveData<BaseResponse<UploadFileData>> = MutableLiveData()
val certLiveData: MutableLiveData<BaseResponse<Void>> = MutableLiveData()
fun certClassify() {
mRepository.certClassify(liveData)
}
fun uploadFile(
path: String,
) {
mRepository.uploadFile(path, picLiveData)
}
fun certAdd(
id: Int?,
cert_id: Int,
image: String,
start_time: String,
end_time: String?
) {
mRepository.certAdd(id, cert_id, image, start_time, end_time, certLiveData)
}
}
\ No newline at end of file
... ...
package com.br_technology.securitytrain_master.ui.view.mine.viewmodel
import com.br_technology.securitytrain_master.base.repository.UserRepository
import com.br_technology.securitytrain_master.base.view.BaseViewModel
/**
* auth: 张继
* date: 2022/1/27 17:26
* dsc:
* updateInfo:
*/
class LiveWebViewModel:BaseViewModel<UserRepository>() {
}
\ No newline at end of file
... ...
... ... @@ -3,10 +3,13 @@ package com.br_technology.securitytrain_master.util
import android.content.Context
import android.content.res.Resources
import android.graphics.drawable.ColorDrawable
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.PopupWindow
import com.br_technology.securitytrain_master.expand.dp2px
import com.br_technology.securitytrain_master.expand.screenWidth
/**
... ... @@ -38,7 +41,7 @@ class PoPWindowUtil {
* @param layout 弹窗的布局文件
*
*/
fun initPopWindow(context: Context?, anchorView: View?, layout: Int): View? {
fun initPopWindow(context: Context?, anchorView: View?, layout: Int): View {
// 初始化popUpWindow
// 生成 View 对象
val popRootView: View = LayoutInflater.from(context).inflate(layout, null)
... ... @@ -54,18 +57,16 @@ class PoPWindowUtil {
// mPopupWindow.setAnimationStyle(R.style.popwin_anim_style);//设置动画
// 设置背景
//实例化一个ColorDrawable颜色为半透明,以达到变暗的效果
val dw = ColorDrawable(-0x50000000)
mPopupWindow!!.setBackgroundDrawable(dw)
// val dw = ColorDrawable(-0x50000000)
// mPopupWindow?.setBackgroundDrawable(dw)
mPopupWindow?.width=popRootView.screenWidth()-64.dp2px()
// 外部点击事件
mPopupWindow!!.setOutsideTouchable(false)
mPopupWindow?.isOutsideTouchable = false
// 传入点
mPopupWindow!!.showAsDropDown(anchorView)
// mPopupWindow?.showAtLocation(anchorView,Gravity.CENTER_HORIZONTAL,0,0)
mPopupWindow?.showAsDropDown(anchorView)
//关闭时置空对象
mPopupWindow!!.setOnDismissListener(object : PopupWindow.OnDismissListener {
override fun onDismiss() {
mPopupWindow = null
}
})
mPopupWindow?.setOnDismissListener { mPopupWindow = null }
return popRootView //返回View
}
... ... @@ -86,7 +87,7 @@ class PoPWindowUtil {
*/
fun dismissPoPWindow() {
if (mPopupWindow != null) {
mPopupWindow!!.dismiss()
mPopupWindow?.dismiss()
}
}
... ...
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/layout_tool_bar" />
<com.br_technology.securitytrain_master.view.ViewToolBar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:toolTitle="聊天记录" />
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/smart_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/chat_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
\ No newline at end of file
... ...
... ... @@ -35,6 +35,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/cert_type_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
... ... @@ -75,11 +76,13 @@
<TextView
android:id="@+id/upload_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="16dp"
android:background="@null"
android:gravity="right"
android:hint="请选择初始取证时间"
android:textColor="@color/color_32"
android:textColorHint="@color/color_96"
... ... @@ -88,13 +91,12 @@
</LinearLayout>
<LinearLayout
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical">
android:orientation="vertical" />
</LinearLayout>
<TextView
android:id="@+id/tv_upload"
... ...
... ... @@ -19,7 +19,7 @@
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:overScrollMode="never"
app:tabMode="auto"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/color_252"
app:tabTextColor="@color/color_96" />
... ...
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/layout_tool_bar" />
<com.br_technology.securitytrain_master.view.ViewToolBar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.tencent.smtt.sdk.WebView
android:id="@+id/live_web"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.appcompat.widget.LinearLayoutCompat>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/cert_name"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:paddingHorizontal="16dp"
android:textColor="@color/black"
android:textSize="@dimen/sp_14" />
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/chat_icon"
android:layout_width="44dp"
android:layout_height="44dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/icon_chat_group" />
<TextView
android:id="@+id/chat_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/color_96"
android:textSize="12sp"
app:layout_constraintBaseline_toBaselineOf="@id/chat_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/chat_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:textColor="@color/color_32"
android:textSize="14sp"
app:layout_constraintEnd_toStartOf="@+id/chat_date"
app:layout_constraintStart_toEndOf="@+id/chat_icon"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/chat_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="8dp"
android:textColor="@color/color_32"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/chat_icon"
app:layout_constraintTop_toBottomOf="@id/chat_name" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginVertical="15dp"
android:background="@color/color_eb"
app:layout_constraintTop_toBottomOf="@id/chat_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
... ...
... ... @@ -10,19 +10,20 @@
<ImageView
android:scaleType="fitXY"
android:id="@+id/video_pic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/logo"
android:scaleType="fitXY"
android:src="@mipmap/banner" />
<TextView
android:id="@+id/lesson"
android:layout_width="39dp"
android:layout_width="wrap_content"
android:layout_height="16dp"
android:background="@drawable/gradient_e8_e5_4"
android:gravity="center"
android:paddingHorizontal="5dp"
android:textColor="@color/white"
android:textSize="10sp" />
</FrameLayout>
... ...
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_marginHorizontal="32dp"
android:layout_height="wrap_content">
<FrameLayout
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/cert_rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</FrameLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
\ No newline at end of file
... ...
... ... @@ -5,17 +5,22 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/online_recycler"
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/smart_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:overScrollMode="never"
android:paddingTop="4dp"
android:paddingBottom="12dp"
android:scrollbars="none"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" />
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/online_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:overScrollMode="never"
android:paddingTop="4dp"
android:paddingBottom="12dp"
android:scrollbars="none"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
</LinearLayout>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file

3.5 KB | 宽: | 高:

2.5 KB | 宽: | 高:

  • 两方对比
  • 交换覆盖
  • 透明覆盖

2.6 KB | 宽: | 高:

1.6 KB | 宽: | 高:

  • 两方对比
  • 交换覆盖
  • 透明覆盖

4.8 KB | 宽: | 高:

3.5 KB | 宽: | 高:

  • 两方对比
  • 交换覆盖
  • 透明覆盖

7.7 KB | 宽: | 高:

5.2 KB | 宽: | 高:

  • 两方对比
  • 交换覆盖
  • 透明覆盖

10.4 KB | 宽: | 高:

7.1 KB | 宽: | 高:

  • 两方对比
  • 交换覆盖
  • 透明覆盖