From d68d5f254b31467a96a565e4459c481737c1e727 Mon Sep 17 00:00:00 2001 From: itgaojian Date: Tue, 29 Oct 2024 18:03:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 +- .../tenlionsoft/aimz_k/model/AppTokenUser.kt | 19 +- .../aimz_k/model/MsgCategoryBean.kt | 2 +- .../aimz_k/model/MsgCategoryDao.kt | 68 ++++++- .../com/tenlionsoft/aimz_k/model/MsgDao.kt | 1 + .../com/tenlionsoft/aimz_k/model/TokenUser.kt | 18 ++ .../aimz_k/page/activity/ChatActivity.kt | 13 +- .../aimz_k/page/activity/SplashActivity.kt | 25 +-- .../aimz_k/page/fragments/MsgFragment.kt | 36 +++- .../aimz_k/viewmodel/ChatPageViewModel.kt | 24 +++ .../aimz_k/viewmodel/LoginPageViewModel.kt | 4 +- .../aimz_k/viewmodel/MsgViewModel.kt | 75 ++++++- .../tenlionsoft/aimz_k/widget/BindingUtils.kt | 51 +++++ .../aimz_k/widget/CategoryAdapter.kt | 43 ++++ .../main/res/drawable-xhdpi/ic_customer.png | Bin 0 -> 5048 bytes .../main/res/drawable-xhdpi/ic_send_msg.png | Bin 0 -> 1454 bytes app/src/main/res/drawable/shp_circle_red.xml | 5 + .../main/res/drawable/shp_divider_gray.xml | 7 + app/src/main/res/layout/activity_chat.xml | 118 ++++++++--- app/src/main/res/layout/fragment_msg.xml | 11 +- app/src/main/res/layout/item_category.xml | 107 ++++++++++ app/src/main/res/layout/layout_chat_input.xml | 52 ----- .../baselib/base/DynamicChangeCallBack.kt | 45 +++++ .../baselib/widget/LoadingDialog.kt | 3 +- .../baselib/widget/chat/ChatUiHelper.kt | 35 ++-- .../baselib/widget/chat/IndicatorView.kt | 94 +++++++++ .../main/res/drawable-xhdpi/ic_ctype_file.png | Bin 0 -> 481 bytes .../res/drawable-xhdpi/ic_ctype_file_pre.png | Bin 0 -> 476 bytes .../res/drawable-xhdpi/ic_ctype_image.png | Bin 0 -> 650 bytes .../res/drawable-xhdpi/ic_ctype_image_pre.png | Bin 0 -> 710 bytes .../drawable-xhdpi/ic_ctype_loaction_pre.png | Bin 0 -> 906 bytes .../res/drawable-xhdpi/ic_ctype_location.png | Bin 0 -> 901 bytes .../res/drawable-xhdpi/ic_ctype_video.png | Bin 0 -> 562 bytes .../res/drawable-xhdpi/ic_ctype_video_pre.png | Bin 0 -> 546 bytes .../main/res/drawable/selector_ctype_file.xml | 6 + .../res/drawable/selector_ctype_image.xml | 6 + .../res/drawable/selector_ctype_location.xml | 6 + .../res/drawable/selector_ctype_video.xml | 6 + .../src/main/res/drawable/shp_tr_radius_5.xml | 2 +- .../main/res/layout/include_add_layout.xml | 184 ++++++++++++++++++ .../main/res/layout/include_emoji_layout.xml | 38 ++++ baselib/src/main/res/values/attrs.xml | 2 +- baselib/src/main/res/values/colors.xml | 1 + 43 files changed, 963 insertions(+), 146 deletions(-) create mode 100644 app/src/main/java/com/tenlionsoft/aimz_k/model/TokenUser.kt create mode 100644 app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt create mode 100644 app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt create mode 100644 app/src/main/java/com/tenlionsoft/aimz_k/widget/CategoryAdapter.kt create mode 100644 app/src/main/res/drawable-xhdpi/ic_customer.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_send_msg.png create mode 100644 app/src/main/res/drawable/shp_circle_red.xml create mode 100644 app/src/main/res/drawable/shp_divider_gray.xml create mode 100644 app/src/main/res/layout/item_category.xml delete mode 100644 app/src/main/res/layout/layout_chat_input.xml create mode 100644 baselib/src/main/java/com/tenlionsoft/baselib/base/DynamicChangeCallBack.kt create mode 100644 baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/IndicatorView.kt create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_file.png create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_file_pre.png create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_image.png create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_image_pre.png create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_loaction_pre.png create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_location.png create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_video.png create mode 100644 baselib/src/main/res/drawable-xhdpi/ic_ctype_video_pre.png create mode 100644 baselib/src/main/res/drawable/selector_ctype_file.xml create mode 100644 baselib/src/main/res/drawable/selector_ctype_image.xml create mode 100644 baselib/src/main/res/drawable/selector_ctype_location.xml create mode 100644 baselib/src/main/res/drawable/selector_ctype_video.xml create mode 100644 baselib/src/main/res/layout/include_add_layout.xml create mode 100644 baselib/src/main/res/layout/include_emoji_layout.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8493df8..36df234 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,7 +29,7 @@ + android:windowSoftInputMode="adjustPan|stateHidden" /> , val roleIds: List, - val user: User + val user: TokenUser ) - -data class User( - val avatar: String, - val email: String, - val id: String, - val isAccountExpired: Int, - val isAccountLocked: Int, - val isDelete: Int, - val isEnable: Int, - val isPasswordExpired: Int, - val nickname: String, - val password: String, - val phone: String, - val tenantId: String, - val userId: String, - val username: String -) \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryBean.kt b/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryBean.kt index 14466cc..398892c 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryBean.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryBean.kt @@ -8,7 +8,7 @@ import java.io.Serializable @Entity(tableName = "db_category") data class MsgCategoryBean( @PrimaryKey(autoGenerate = true) - var id: Long, + var id: Long = 0, @ColumnInfo(name = "avatar") var avatar: String, @ColumnInfo(name = "from") diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryDao.kt b/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryDao.kt index 0f61fe9..77ad650 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryDao.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgCategoryDao.kt @@ -1,10 +1,40 @@ package com.tenlionsoft.aimz_k.model import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy import androidx.room.Query @Dao interface MsgCategoryDao { + + /** + * 获取全部信息 + * + * @return + */ + @Query("SELECT * FROM db_category") + fun getAllCategory(): List + + /** + * 根据ID获取消息 + * + * @param id + * @return + */ + @Query("SELECT * FROM db_category WHERE id =(:id) ") + fun getCategoryById(id: String): List + + /** + * 根据信息来源查询消息 + * + * @param from + * @return + */ + @Query("SELECT * FROM db_category WHERE `from`=(:from)") + fun getCategoryByFrom(from: String?): List + + /** * 查询与单人的聊天记录 SELECT id FROM db_msg WHERE `from`=(:form) AND `to`=(:to) OR `from`=(:to) AND `to`=(:form) ORDER BY timestamp DESC LIMIT (((:page)-1)*(:pageSize)),(:pageSize) */ @@ -12,5 +42,41 @@ interface MsgCategoryDao { fun getCategoryPage( pageSize: Int, page: Int - ): List? + ): MutableList + + + /** + * 清空与某个人的聊天记录 + */ + @Query("DELETE FROM db_category WHERE `from`=(:from) AND `to`=(:to) OR `from`=(:to) AND `to`=(:from)") + fun delChatHistory(from: String?, to: String?) + + /** + * 添加消息多个 + * + * @param beans + */ + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertAll(vararg beans: MsgCategoryBean) + + /** + * 批量添加 + */ + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertAll(beans: List) + + + /** + * 添加消息-单个 + * + * @param bean + */ + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertMsg(bean: MsgCategoryBean) + + /** + * 清除全部聊天记录 + */ + @Query("DELETE FROM db_category") + fun delAllMsg() } \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgDao.kt b/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgDao.kt index 7a2e55f..ba5d386 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgDao.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/model/MsgDao.kt @@ -85,6 +85,7 @@ interface MsgDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertAll(beans: List) + /** * 添加消息-单个 * diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/model/TokenUser.kt b/app/src/main/java/com/tenlionsoft/aimz_k/model/TokenUser.kt new file mode 100644 index 0000000..302ff86 --- /dev/null +++ b/app/src/main/java/com/tenlionsoft/aimz_k/model/TokenUser.kt @@ -0,0 +1,18 @@ +package com.tenlionsoft.aimz_k.model + +data class TokenUser( + val avatar: String, + val email: String, + val id: String, + val isAccountExpired: Int, + val isAccountLocked: Int, + val isDelete: Int, + val isEnable: Int, + val isPasswordExpired: Int, + val nickname: String, + val password: String, + val phone: String, + val tenantId: String, + val userId: String, + val username: String +) \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt index 5e66ab3..c4ddc99 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt @@ -1,10 +1,13 @@ package com.tenlionsoft.aimz_k.page.activity +import android.view.View import android.view.WindowManager import androidx.core.content.ContextCompat import androidx.databinding.DataBindingUtil +import androidx.lifecycle.ViewModelProvider import com.tenlionsoft.aimz_k.R import com.tenlionsoft.aimz_k.databinding.ActivityChatBinding +import com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel import com.tenlionsoft.baselib.base.BaseActivity /** @@ -12,7 +15,9 @@ import com.tenlionsoft.baselib.base.BaseActivity */ class ChatActivity : BaseActivity() { private lateinit var mBinding: ActivityChatBinding - + private val chatPageViewModel: ChatPageViewModel by lazy { + ViewModelProvider(this)[ChatPageViewModel::class.java] + } override fun bindView() { mBinding = DataBindingUtil.setContentView(this, R.layout.activity_chat); @@ -22,6 +27,10 @@ class ChatActivity : BaseActivity() { mBinding.ivBack.setOnClickListener { finish(); } mBinding.srlChats.setEnableRefresh(false) mBinding.srlChats.setEnableLoadMore(false) -// SoftHideKeyBoardUtils.assistActivity(this); + mBinding.viewModel = chatPageViewModel + mBinding.lifecycleOwner = this + chatPageViewModel.showSendBtn.observe(this) { + mBinding.ivSend.visibility = if (it) View.GONE else View.VISIBLE + } } } \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/SplashActivity.kt b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/SplashActivity.kt index f35100b..62d83cd 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/SplashActivity.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/SplashActivity.kt @@ -2,12 +2,12 @@ package com.tenlionsoft.aimz_k.page.activity import android.content.Intent import androidx.databinding.DataBindingUtil +import androidx.lifecycle.lifecycleScope import com.tenlionsoft.aimz_k.R import com.tenlionsoft.aimz_k.databinding.ActivitySplashBinding import com.tenlionsoft.aimz_k.model.DbManager import com.tenlionsoft.baselib.base.BaseActivity import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.util.Timer @@ -22,18 +22,19 @@ class SplashActivity : BaseActivity() { override fun bindView() { mBinding = DataBindingUtil.setContentView(this, R.layout.activity_splash) - GlobalScope.launch(Dispatchers.IO) { - val msgDao = DbManager.db.msgDao() - val cDao = DbManager.db.categoryDao() - withContext(Dispatchers.Main) { - Timer().schedule(object : TimerTask() { - override fun run() { - startActivity(Intent(this@SplashActivity, LoginActivity::class.java)); - finish(); - } - - }, 500) + mBinding.lifecycleOwner = this + lifecycleScope.launch { + withContext(Dispatchers.IO) { + val msgDao = DbManager.db.msgDao() + val cDao = DbManager.db.categoryDao() } + Timer().schedule(object : TimerTask() { + override fun run() { + startActivity(Intent(this@SplashActivity, LoginActivity::class.java)); + finish(); + } + + }, 500) } } } \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt b/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt index 2468bed..a978895 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt @@ -2,19 +2,25 @@ package com.tenlionsoft.aimz_k.page.fragments import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity import androidx.fragment.app.viewModels import com.tenlionsoft.aimz_k.R import com.tenlionsoft.aimz_k.databinding.FragmentMsgBinding +import com.tenlionsoft.aimz_k.model.MsgCategoryBean import com.tenlionsoft.aimz_k.page.activity.ChatActivity import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel +import com.tenlionsoft.baselib.widget.LoadingDialog -class MsgFragment : Fragment() { +class MsgFragment : Fragment(), MsgViewModel.OnItemClickListener { private lateinit var mMsgBinding: FragmentMsgBinding + private var mActivity: FragmentActivity? = null + private var mLoading: LoadingDialog? = null; companion object { fun newInstance() = MsgFragment() @@ -37,9 +43,37 @@ class MsgFragment : Fragment() { container, false ); + mActivity = activity mMsgBinding.llSearchLayout.llSearchLayout.setOnClickListener { startActivity(Intent(this@MsgFragment.context, ChatActivity::class.java)) } + mMsgBinding.msgViewModel = viewModel + mMsgBinding.lifecycleOwner = this + viewModel.onItemClickListener = this//条目点击 + initView(); return mMsgBinding.root; } + + /** + * 初始化页面 + */ + private fun initView() { + mMsgBinding.srlMsgs.setOnLoadMoreListener { viewModel.loadMore() } + mMsgBinding.srlMsgs.setOnRefreshListener { viewModel.refresh() } + + viewModel.isHasMore.observe(viewLifecycleOwner) { + mMsgBinding.srlMsgs.setNoMoreData(it) + mMsgBinding.srlMsgs.finishRefresh() + mMsgBinding.srlMsgs.finishLoadMore() + } + } + + /** + * 条目点击 + */ + override fun onItemClick(msgCategoryBean: MsgCategoryBean) { + Log.e("MsgFragment", "onItemClick: ${msgCategoryBean}") + startActivity(Intent(mActivity, ChatActivity::class.java)) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt new file mode 100644 index 0000000..c77fc9f --- /dev/null +++ b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt @@ -0,0 +1,24 @@ +package com.tenlionsoft.aimz_k.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.tenlionsoft.baselib.base.BaseViewModel + +class ChatPageViewModel : BaseViewModel() { + var txtMsg: String = "" + var showSendBtn = MutableLiveData() + fun onTxtChange(s: CharSequence, start: Int, before: Int, count: Int) { + this.txtMsg = s.toString() + if (s.isEmpty()) { + showSendBtn.value = true + } else { + showSendBtn.value = false + } + } + + /** + * 发送文本信息 + */ + fun sendTxtMsg() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt index d99beca..085e200 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt @@ -20,8 +20,8 @@ import okhttp3.RequestBody.Companion.toRequestBody class LoginPageViewModel : BaseViewModel() { - var userName: String = "" - var userPwd: String = "" + var userName: String = "admin" + var userPwd: String = "admin" val isLoginSuccess = MutableLiveData() private val gson = Gson() private val userApi = RetrofitClient.getInstance(App.context) diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt index d735300..63b9b74 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt @@ -1,7 +1,80 @@ package com.tenlionsoft.aimz_k.viewmodel +import android.util.Log +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.tenlionsoft.aimz_k.model.DbManager +import com.tenlionsoft.aimz_k.model.MsgCategoryBean +import com.tenlionsoft.aimz_k.widget.CategoryAdapter +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class MsgViewModel : ViewModel() { - // TODO: Implement the ViewModel + private val _pwdList = MutableLiveData>() + var adapter: CategoryAdapter = CategoryAdapter(_pwdList.value ?: emptyList(),this) + var onItemClickListener: OnItemClickListener? = null + + private var mCurrentPage: Int = 1 + var isHasMore: MutableLiveData = MutableLiveData().apply { + value = false + } + + init { + Log.e("MsgViewModel", "Init:${_pwdList.value} ") + getPwdList(true) + } + + + /** + * 获取列表数据 + */ + private fun getPwdList(isFirst: Boolean) { + viewModelScope.launch { + if (isFirst) { + _pwdList.value = emptyList() + mCurrentPage = 1 + } else { + ++mCurrentPage + } + val list = getCategoryListByPage(mCurrentPage) + if (list.isNotEmpty()) { + isHasMore.value = false + } else { + isHasMore.value = true + } + val updateData: List = _pwdList.value!! + list + _pwdList.value = updateData + Log.e("MsgViewModel", "getPwdList: ${_pwdList.value}") + adapter.setData(_pwdList.value!!) + } + } + + private suspend fun getCategoryListByPage(page: Int): List { + var tempList: List + withContext(Dispatchers.IO) { + val cDao = DbManager.db.categoryDao() + tempList = cDao.getCategoryPage(10, page) + } + return tempList + } + + /** + * 加载更多 + */ + fun loadMore() { + getPwdList(false) + } + + /** + * 刷新 + */ + fun refresh() { + getPwdList(true) + } + + interface OnItemClickListener { + fun onItemClick(msgCategoryBean: MsgCategoryBean) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt b/app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt new file mode 100644 index 0000000..4c5237d --- /dev/null +++ b/app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt @@ -0,0 +1,51 @@ +package com.tenlionsoft.aimz_k.widget + +import android.widget.ImageView +import androidx.databinding.BindingAdapter +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.Adapter +import com.bumptech.glide.Glide +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.request.RequestOptions +import com.tenlionsoft.aimz_k.R + + +object BindingUtils { + + @BindingAdapter("app:setAdapter") + @JvmStatic + fun bindAdapterToRecyclerView(recyclerView: RecyclerView, adapter: Adapter<*>) { +// adapter.setHasStableIds(true) +// recyclerView.setHasFixedSize(true) + recyclerView.layoutManager = LinearLayoutManager(recyclerView.context) + recyclerView.adapter = adapter + } + + @BindingAdapter("app:imageUrl") + @JvmStatic + fun bindImgUrl(imageView: ImageView, url: String?) { + if (url.isNullOrEmpty()) { + imageView.setImageResource(R.drawable.app_logo_small) + } else { + val requestOptions = RequestOptions() + .error(R.drawable.app_logo_small) + .placeholder(R.drawable.app_logo_small) + .skipMemoryCache(false) + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .centerInside() + Glide.with(imageView.context) + .load(url) + .apply(requestOptions) + .into(imageView) + } + + } + + @BindingAdapter("imgResource") + @JvmStatic + fun bindImgUrl(imageView: ImageView, url: Int) { + imageView.setImageResource(url) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/widget/CategoryAdapter.kt b/app/src/main/java/com/tenlionsoft/aimz_k/widget/CategoryAdapter.kt new file mode 100644 index 0000000..15c9d5f --- /dev/null +++ b/app/src/main/java/com/tenlionsoft/aimz_k/widget/CategoryAdapter.kt @@ -0,0 +1,43 @@ +package com.tenlionsoft.aimz_k.widget + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.tenlionsoft.aimz_k.databinding.ItemCategoryBinding +import com.tenlionsoft.aimz_k.model.MsgCategoryBean +import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel + +class CategoryAdapter( + private var list: List, + private val viewModel: MsgViewModel +) : RecyclerView.Adapter() { + class NewsViewHolder(val binding: ItemCategoryBinding) : RecyclerView.ViewHolder(binding.root) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder { + val inflater = LayoutInflater.from(parent.context) + val binding = ItemCategoryBinding.inflate(inflater, parent, false) + return NewsViewHolder(binding) + } + + override fun getItemCount(): Int { + return list.size + } + + @SuppressLint("NotifyDataSetChanged") + fun setData(list: List) { + this.list = list + this.notifyDataSetChanged() + + } + + override fun onBindViewHolder(holder: NewsViewHolder, position: Int) { + holder.binding.pos = position + holder.binding.item = list[position] + holder.binding.root.setOnClickListener { + viewModel.onItemClickListener?.onItemClick(list[position]) + } + holder.binding.executePendingBindings() + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/ic_customer.png b/app/src/main/res/drawable-xhdpi/ic_customer.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3fe7a0f566d149418b096f8bb32115e5444fb1 GIT binary patch literal 5048 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 IM6N<$g1gPAasU7T literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/shp_circle_red.xml b/app/src/main/res/drawable/shp_circle_red.xml new file mode 100644 index 0000000..abc1a8d --- /dev/null +++ b/app/src/main/res/drawable/shp_circle_red.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shp_divider_gray.xml b/app/src/main/res/drawable/shp_divider_gray.xml new file mode 100644 index 0000000..a373ae6 --- /dev/null +++ b/app/src/main/res/drawable/shp_divider_gray.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml index 4865c41..6618220 100644 --- a/app/src/main/res/layout/activity_chat.xml +++ b/app/src/main/res/layout/activity_chat.xml @@ -4,6 +4,9 @@ + + @@ -53,44 +57,98 @@ android:background="#CBCBCB" /> - - - - - - - - - + android:layout_height="0dp" + android:layout_weight="1"> - + + + + android:layout_height="wrap_content" + android:orientation="vertical"> - + + + + + + + + + + + + + + + + - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_msg.xml b/app/src/main/res/layout/fragment_msg.xml index 07dd49b..47b4bc6 100644 --- a/app/src/main/res/layout/fragment_msg.xml +++ b/app/src/main/res/layout/fragment_msg.xml @@ -1,8 +1,13 @@ - + + + app:setAdapter="@{msgViewModel.adapter}" + android:layout_height="match_parent" + tools:listitem="@layout/item_category" /> diff --git a/app/src/main/res/layout/item_category.xml b/app/src/main/res/layout/item_category.xml new file mode 100644 index 0000000..559b391 --- /dev/null +++ b/app/src/main/res/layout/item_category.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_chat_input.xml b/app/src/main/res/layout/layout_chat_input.xml deleted file mode 100644 index 18dbe4a..0000000 --- a/app/src/main/res/layout/layout_chat_input.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/base/DynamicChangeCallBack.kt b/baselib/src/main/java/com/tenlionsoft/baselib/base/DynamicChangeCallBack.kt new file mode 100644 index 0000000..5f69028 --- /dev/null +++ b/baselib/src/main/java/com/tenlionsoft/baselib/base/DynamicChangeCallBack.kt @@ -0,0 +1,45 @@ +package com.tenlionsoft.baselib.base + +import androidx.databinding.ObservableList +import androidx.recyclerview.widget.RecyclerView + +class DynamicChangeCallBack(private val adapter: RecyclerView.Adapter<*>) : + ObservableList.OnListChangedCallback>() { + override fun onChanged(sender: ObservableList?) { + adapter.notifyDataSetChanged() + } + + override fun onItemRangeChanged( + sender: ObservableList?, + positionStart: Int, + itemCount: Int + ) { + adapter.notifyItemRangeChanged(positionStart, itemCount) + } + + override fun onItemRangeInserted( + sender: ObservableList?, + positionStart: Int, + itemCount: Int + ) { + adapter.notifyItemRangeInserted(positionStart, itemCount) + } + + override fun onItemRangeMoved( + sender: ObservableList?, + fromPosition: Int, + toPosition: Int, + itemCount: Int + ) { + adapter.notifyItemRangeRemoved(fromPosition, itemCount) + adapter.notifyItemRangeInserted(toPosition, itemCount) + } + + override fun onItemRangeRemoved( + sender: ObservableList?, + positionStart: Int, + itemCount: Int + ) { + adapter.notifyItemRangeRemoved(positionStart, itemCount) + } +} \ No newline at end of file diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/widget/LoadingDialog.kt b/baselib/src/main/java/com/tenlionsoft/baselib/widget/LoadingDialog.kt index 1733ec5..0c7488a 100644 --- a/baselib/src/main/java/com/tenlionsoft/baselib/widget/LoadingDialog.kt +++ b/baselib/src/main/java/com/tenlionsoft/baselib/widget/LoadingDialog.kt @@ -1,5 +1,6 @@ package com.tenlionsoft.baselib.widget +import android.app.Activity import android.app.Dialog import android.content.Context import android.content.DialogInterface @@ -33,7 +34,7 @@ class LoadingDialog : Dialog { window.setBackgroundDrawable(ColorDrawable()) } - class Builder(private val context: Context) { + class Builder(private val context: Activity) { //提示信息 private var message: String? = null diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/ChatUiHelper.kt b/baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/ChatUiHelper.kt index 397ef11..a3702bb 100644 --- a/baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/ChatUiHelper.kt +++ b/baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/ChatUiHelper.kt @@ -1,12 +1,10 @@ package com.tenlionsoft.baselib.widget.chat import android.annotation.SuppressLint -import android.annotation.TargetApi import android.app.Activity import android.content.Context import android.content.SharedPreferences import android.graphics.Rect -import android.os.Build import android.text.Editable import android.text.TextWatcher import android.util.DisplayMetrics @@ -26,10 +24,10 @@ class ChatUiHelper { private var mActivity: Activity? = null private var mContentLayout: LinearLayout? = null //整体界面布局 private var mBottomLayout: RelativeLayout? = null //底部布局 + private var mEmojiLayout: LinearLayout? = null //表情布局 - // private LinearLayout mEmojiLayout;//表情布局 // private LinearLayout mAddLayout;//添加布局 - private var mSendBtn: Button? = null //发送按钮 + private var mIvSend: ImageView? = null//发送按钮 private var mAddButton: View? = null //加号按钮 private var mAudioButton: Button? = null //录音按钮 private var mAudioIv: ImageView? = null //录音图片 @@ -46,6 +44,11 @@ class ChatUiHelper { return this } + fun bindSendButton(iv: ImageView): ChatUiHelper { + this.mIvSend = iv + return this + } + @SuppressLint("ClickableViewAccessibility") fun bindEditText(editText: EditText): ChatUiHelper { mEditText = editText @@ -70,11 +73,11 @@ class ChatUiHelper { override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) { if (mEditText!!.text.toString().trim { it <= ' ' }.isNotEmpty()) { - mSendBtn!!.visibility = View.VISIBLE - mAddButton!!.visibility = View.GONE + mIvSend?.visibility = View.VISIBLE +// TODO mAddButton!!.visibility = View.GONE } else { - mSendBtn!!.visibility = View.GONE - mAddButton!!.visibility = View.VISIBLE + mIvSend?.visibility = View.GONE +// TODO mAddButton!!.visibility = View.VISIBLE } } @@ -93,7 +96,7 @@ class ChatUiHelper { //绑定表情布局 fun bindEmojiLayout(emojiLayout: LinearLayout?): ChatUiHelper { -// mEmojiLayout = emojiLayout; + mEmojiLayout = emojiLayout; return this } @@ -103,12 +106,6 @@ class ChatUiHelper { return this } - //绑定发送按钮 - fun bindttToSendButton(sendbtn: Button): ChatUiHelper { - mSendBtn = sendbtn - return this - } - //绑定语音按钮点击事件 // fun bindAudioBtn(audioBtn: RecordButton): ChatUiHelper { @@ -279,12 +276,12 @@ class ChatUiHelper { private fun showEmotionLayout() { -// mEmojiLayout.setVisibility(View.VISIBLE); + mEmojiLayout?.setVisibility(View.VISIBLE); // mIvEmoji.setImageResource(R.drawable.ic_keyboard); } private fun hideEmotionLayout() { -// mEmojiLayout.setVisibility(View.GONE); + mEmojiLayout?.setVisibility(View.GONE); // mIvEmoji.setImageResource(R.drawable.ic_emoji); } @@ -353,7 +350,7 @@ class ChatUiHelper { /** * 释放被锁定的内容高度 */ - fun unlockContentHeightDelayed() { + private fun unlockContentHeightDelayed() { mEditText!!.postDelayed({ (mContentLayout!!.layoutParams as LinearLayout.LayoutParams).weight = 1.0f @@ -420,8 +417,6 @@ class ChatUiHelper { const val SHARE_PREFERENCE_TAG: String = "soft_input_height" fun with(activity: Activity): ChatUiHelper { val mChatUiHelper = ChatUiHelper() - - // AndroidBug5497Workaround.assistActivity(activity); mChatUiHelper.mActivity = activity mChatUiHelper.mInputManager = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/IndicatorView.kt b/baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/IndicatorView.kt new file mode 100644 index 0000000..129b9d2 --- /dev/null +++ b/baselib/src/main/java/com/tenlionsoft/baselib/widget/chat/IndicatorView.kt @@ -0,0 +1,94 @@ +package com.tenlionsoft.baselib.widget.chat + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.RectF +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.util.AttributeSet +import android.widget.LinearLayout +import com.tenlionsoft.baselib.R +import com.tenlionsoft.baselib.utils.DensityUtils + +class IndicatorView : LinearLayout { + private var indicatorColor = Color.rgb(0, 0, 0) + private var indicatorColorSelected = Color.rgb(0, 0, 0) + private var indicatorWidth = 0 + private var gravity = 0 + + private var indicatorCount = 0 + private var currentIndicator = 0 + + private val handler: Handler = object : Handler(Looper.getMainLooper()) { + override fun handleMessage(msg: Message) { + if (msg.what == 0x12) { + invalidate() + } + } + } + + constructor(context: Context) : super(context) { + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + if (attrs != null) { + val typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.IndicatorView) + indicatorColor = + typedArray.getColor(R.styleable.IndicatorView_indicatorColor, Color.rgb(0, 0, 0)) + indicatorColorSelected = typedArray.getColor( + R.styleable.IndicatorView_indicatorColorSelected, + Color.rgb(0, 0, 0) + ) + indicatorWidth = DensityUtils.dp2px( + context, + typedArray.getFloat(R.styleable.IndicatorView_indicatorWidth, 0F) + ) + gravity = typedArray.getInt(R.styleable.IndicatorView_gravity, 0) + typedArray.recycle() + } + } + + + override fun onDraw(canvas: Canvas) { + val viewWidth = width + val viewHeight = height + val totalWidth = indicatorWidth * (2 * indicatorCount - 1) + + val paint = Paint() + paint.isAntiAlias = true + + if (indicatorCount > 0) { + for (i in 0 until indicatorCount) { + if (i == currentIndicator) { + paint.color = indicatorColorSelected + } else { + paint.color = indicatorColor + } + var left = (viewWidth - totalWidth) / 2 + (i * 2 * indicatorWidth) + when (gravity) { + 0 -> left = (viewWidth - totalWidth) / 2 + (i * 2 * indicatorWidth) + 1 -> left = i * 2 * indicatorWidth + 2 -> left = viewWidth - totalWidth + (i * 2 * indicatorWidth) + } + val top = (viewHeight - indicatorWidth) / 2 + val right = left + indicatorWidth + val bottom = top + indicatorWidth + val rectF = RectF(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat()) + canvas.drawOval(rectF, paint) + } + } + } + + fun setIndicatorCount(indicatorCount: Int) { + this.indicatorCount = indicatorCount + } + + fun setCurrentIndicator(currentIndicator: Int) { + this.currentIndicator = currentIndicator + handler.sendEmptyMessage(0x12) + } +} \ No newline at end of file diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_file.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_file.png new file mode 100644 index 0000000000000000000000000000000000000000..32095eaff9bc160a0c0e03df75179388a39d7eba GIT binary patch literal 481 zcmeAS@N?(olHy`uVBq!ia0vp^MIg+<3?z3jm-+*#kN}?$S0G(XZ7@^zp*PT6>5?G7 zV1_Sy=UOH)+wuFpe|4}W=EH$#NlqWN>#HYrluju)62rj2sOah97?N@C?d_XcEQ$iH z4|W)k zfYbik0!N(<^#u<)nu;6n2jtF3To<6*E1;pS@_wRaJim)f@kz1z#5xuovw>Br2+?#=RC`7|qkZ;9elR*%IZr(!+W9|UvV z4Eyw9*7cQNuGF3|XK>{Ds(6(7W9alP8rM5T*84}fezKSZG#!C{F5Y>*aM{EyZrKLxX96595%&JwZYHMpBJ$iKG#*IstE=`|4y{f8e=gyrQH*Q?I zbZKjAD@#y$B+zuuk|4iehUkMy?++w@{U8>Qbc%t2QNz>4F(l*O+uJAe4jb^e2CB+Q z1#M!xojIBB|Nq%*FRvA4$~n5=#qMk-_NKCyC);){OmF_Ru=u|0rzgykB7dgvn-|VK zsk1*%t=cH(+__TWnP#Q$UYsQ)Q%ia*=v>UGU1BpI2+w#P~eT&z-xUiBo8a0V7a(A``@Qs+s@y{1WUx;r@I1 xC%yA2H|EHHetYm=@$qXGb8alSTzF@Tze4}j7t;T{&H@9H!PC{xWt~$(69C@d+rt0= literal 0 HcmV?d00001 diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_image.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_image.png new file mode 100644 index 0000000000000000000000000000000000000000..2af09ca971b57b30d5a7d110e8bcc07b7dd9d11d GIT binary patch literal 650 zcmeAS@N?(olHy`uVBq!ia0vp^MIg+<3?z3jm-+)K?*N|=S0G(XCE%mdV+%A+q9n*K znBiK3%@-xkHwR+)=Ov%Kx2|(iVUVt9$@K3xp6+H~V7%t(;uw-~@9pjGzS#x>tq%{1 z8(ep2c(UjJWV5u@7P`@^d>%!<&H5+)W6B90p>3MiTDh1)7cTD4+OkctQR?=hdq+-9 zirChrro)-$cx9_f)a}3xDzkW>cnPgt$)O@MT_v89(C>K-u?efh@MQ)P%-SdBw<)@!N zU+Zzi-EqyHBaP*jzk2UJ-TUPKW(QsGUt9-tT$iyvTcc2UXj=3UkLLTKaUF9C^CMhO z990Z8VR~ZqU}L~Db>@F>rp(>*=>4rTDebk7e|s3$89ldqox6nb*4;U$y=LX+PT6fa zz2D@iGkI<_iH$$h?CegN6rtcezhXV^nMXo=MJ7x%xlz7T zNjdXCr@vd^ERzXpyhl7WRxX*ep#JHTlT7*{1^cZ&&yHAfoV!xYQ~5^k5#^UE+x#aP zCGB?9v@iO$XW#8}auX+cX?Y&k1ZpaoGwFW&6#KZpqU|T1_MbW(&+%hcHvgyT)=9Ai g0w-Gavi38?F8Z~lq?~atFcmO(y85}Sb4q9e03pL8yZ`_I literal 0 HcmV?d00001 diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_image_pre.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_image_pre.png new file mode 100644 index 0000000000000000000000000000000000000000..02e9ff9636a8bc4465f370a925063ec487b8e062 GIT binary patch literal 710 zcmV;%0y+JOP)xb{}vbARQiC_vbIjAlIr((s-7yv78nSoHqR>vw0hnIe|xf7oEm}BII~Yz zvFwakaXFcYjbNP}zsJmomTiJ{Y($IK!O9uY(p3N>9F)AKq>@T5tWZ)(B^OpG>4j{E zi^WaZu&M7Ls{x$svEq{M19)kvd9EL${|w#mPKOBu)^5Aq|1vWDRL)A?n7J)_fn)A#Sha7kvTrgg~)=)LWs0P zT6r@0y&vrC@R9tHT-@&+1^+eh&e3DZ&$Opk@Y=f%_2?17aQ(A z$%!kT9D6tDXc-=BH;Ag6kg@0W({}cZQBp}I7gi{#q>>9Ol>9lQ{NvT%@euh|{!#hB sc1Ezye$Q(U@-KHxZG~Q8S#Kxp52r|WzZ-%3761SM07*qoM6N<$f^zU(C;$Ke literal 0 HcmV?d00001 diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_loaction_pre.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_loaction_pre.png new file mode 100644 index 0000000000000000000000000000000000000000..299761beb67ed820c737e5c3be5778529010a63e GIT binary patch literal 906 zcmV;519kj~P)n^Jvudc z8Iy&^FO$*lp2RW@VWBWxil?&}6tGqroJ>k#u|gcjaS5v}C!^;SR!g5p;{;X<$0LH} z$dTt9=}1SSKSw&!k?8NgCCet>RlX2@wTqi_c(R_hq}5LALCJa}=_gT~!#Q1=heuOA&X$KP)p5*$Y(d{GG9XvSvt%I~eHnxmDOI7qgc=qyR#ry>%t>nw zB!Mz#S;(FC2P5hfY5&xYg;a)a2E<)*3(SkpoqitbkmZUo51c@4WLTJpp*i zCl*p_q_jaUv=h7PKd}J|*=o~g(YIyR`)unbQxON-w+GR8qu7VogT1 z;3Eq&@`I7YtBJS(C;4tdzL}D2hq>^KNv_dsU{3N(+6vrcCT@^3b`qO@aR+`f+4qSe z8-T<|AGyI0Bz8RuBpHUxWY65;AYr+>e6q$3@v=150668$;yFG>54S3lq(@<%)>KN1BjR)~kZ_F(_z g4y&)QJWo#AFS~b5NSXU4!2kdN07*qoM6N<$g2Ga^1poj5 literal 0 HcmV?d00001 diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_location.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_location.png new file mode 100644 index 0000000000000000000000000000000000000000..1f643bc062a3e0f4d21a3cc491b26c68061882be GIT binary patch literal 901 zcmeAS@N?(olHy`uVBq!ia0vp^MIg+<3?z3jm-+*#`~aU2S0G(XNAPs@yfC1ZDkVXF z!3^y0e|_eEH7QC`?((60!&?^1=J_N&+Gi_rD%)Z0_GucuJuO~^W=p*p7?>7%x;Tbp z+WodxUC?-!pvso(G^XbcfII8X>GCQ5zlQlzwB)hr3F#jn-U75BpePEUYcAy z@5>VPjdRp(UwZ0%zdtEc$p3Z2=LFlMo>}wXbUSA8y5>)Pqwi#=a&E6}k^G6}tkvEr zw@yvpx{`NO&l9IWPyaqAJvFziO*~I#H+4<(QU1A2Lsd08Gr-&P-O@l-*_-U;&Jy`X zV)M)jOU&omN=m+#)|1$m+`7-$Q1oW@^W$1quU+-B4z5z#G{K9VZGp`*rzgjS7_2ik zd%EzwGK@RAVcPwx53h#w7cWo@E|m*bh&~t7Z&Xzus$SUB+z>(0w;X7O@2I$C75JT2a-e*V^{lb$D@O`g0&P4WBu7%ncMO@E#= zU7tAN#?1I@tcw-`&Ny-LkJwy+i8<+i6oiB({xGV&W7X7k=EvlAuW7b6A*Uww z9C4H~ZRlHb=0wYcBd1(qnkUKlp0L&I{I+*T@-daGIeCeGmvnB)TzS&DU(x)D%D!nw zIlrXrh!*;JlBqMLbI$>`&di4_oNp)0tnmD|>0A2Y@Fd=7m0PWeOBK$xm$ldm-A;cb zY36yQKk3|?Ne|CGP;&5I^oYOQQ|i(mpUi~$E{pw_a8Ker^*EJHT;T|NrIx_^L~j=Y@P;qHf#y)aK{(CBLt)u79BVX?{iM zypLRbt1XKE-)z3!Z@ug1W4`6{H>`Q)A5q7AFVoo1sp;GWVB%)*boFyt=akR{04NQe AK>z>% literal 0 HcmV?d00001 diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_video.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_video.png new file mode 100644 index 0000000000000000000000000000000000000000..5ee22247547a492d577c6f643817deb2d26a296d GIT binary patch literal 562 zcmeAS@N?(olHy`uVBq!ia0vp^MIg+<3?z3jm-+*#v;dzFS0G(Xdl3G8UoX%m#gZVu zV21rH(N@2|e3+{xurld&v%TFVU#{EvPY!RG?(ZYr-Bqb_g?)Jm0|R4}r;B4q#=W<< zy}J)9h_pRi+&L?|`1Rhor+@yhFKRMqNfZlfy)3q`{OO}9?UQnpys~!%_puhOy8J}j z$J9h6z&K>thotyP5vluU-RkJPXEJM7m&b#pz`jT&_PBQPyKc^hZwDN`j_fvkUEH8yT+_zk6#D!7(3D%+H})<5F8E~5e&tIwUxI($`fcZO{lwk1ucO~R{L3b!a^e6B z&@5(Qpm97t4J<#Smi+nnDqTity1mx_7H-B**X2_5%X_ANT=YY9n!M7PIc6M6x9xyY O!r@cjAnCrp@7Q&Y2Y<;q#JX0^7q&X_TytE+3@zI|J_ zZhi9P$*o(r)~#E&aN)wMSFg^UJGY^s;f|!X8PGD0k|4iehL6$A2a^sYpL;T4B?ALv zf~SjPNXEUlw@>Fa8wj)}b~w*46rXLq#PjmEzw(^4vcKLU9#jppzZer0Y$>sCQ(d}G%`)0@*PlN1`DOXgY=DN81E_#_P@?0fK(B0>d zp@+D~1O;<7hbESthKxcgCwe(2C@`N`b@Ip0P0Mcimc5DIK6%ZJ{aNxiStjtV-Bp*~ z{8eEygHg2ZwB1hyo7qn)UR?ZVaq4u5O1T-%C-eQ){|;bH^JOF{2lrzwBt+w`Zp zgS~REIsJ3L ziRbC*Yjk#o-09JH`AaI*b9(I_ccs-YzH$X8txwq7Czn$0(zR~xo9g$!S>ELRJ#D+E zTEVgD&I|@lp(n>!px&v`5BgW}Rhw_(@=xwhr*2f4Ve0ko)?seF@*N>sC9O|qteW|o Z^>6O7)Fv*$WMKF+c)I$ztaD0e0sxl4|9AiZ literal 0 HcmV?d00001 diff --git a/baselib/src/main/res/drawable/selector_ctype_file.xml b/baselib/src/main/res/drawable/selector_ctype_file.xml new file mode 100644 index 0000000..8d72921 --- /dev/null +++ b/baselib/src/main/res/drawable/selector_ctype_file.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/baselib/src/main/res/drawable/selector_ctype_image.xml b/baselib/src/main/res/drawable/selector_ctype_image.xml new file mode 100644 index 0000000..99684a4 --- /dev/null +++ b/baselib/src/main/res/drawable/selector_ctype_image.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/baselib/src/main/res/drawable/selector_ctype_location.xml b/baselib/src/main/res/drawable/selector_ctype_location.xml new file mode 100644 index 0000000..da9b755 --- /dev/null +++ b/baselib/src/main/res/drawable/selector_ctype_location.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/baselib/src/main/res/drawable/selector_ctype_video.xml b/baselib/src/main/res/drawable/selector_ctype_video.xml new file mode 100644 index 0000000..39dbb6a --- /dev/null +++ b/baselib/src/main/res/drawable/selector_ctype_video.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/baselib/src/main/res/drawable/shp_tr_radius_5.xml b/baselib/src/main/res/drawable/shp_tr_radius_5.xml index cd5ce76..27e5291 100644 --- a/baselib/src/main/res/drawable/shp_tr_radius_5.xml +++ b/baselib/src/main/res/drawable/shp_tr_radius_5.xml @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/baselib/src/main/res/layout/include_add_layout.xml b/baselib/src/main/res/layout/include_add_layout.xml new file mode 100644 index 0000000..cc2fbe3 --- /dev/null +++ b/baselib/src/main/res/layout/include_add_layout.xml @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/baselib/src/main/res/layout/include_emoji_layout.xml b/baselib/src/main/res/layout/include_emoji_layout.xml new file mode 100644 index 0000000..2e5a737 --- /dev/null +++ b/baselib/src/main/res/layout/include_emoji_layout.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/baselib/src/main/res/values/attrs.xml b/baselib/src/main/res/values/attrs.xml index ec47df2..fc3677f 100755 --- a/baselib/src/main/res/values/attrs.xml +++ b/baselib/src/main/res/values/attrs.xml @@ -133,7 +133,7 @@ - + diff --git a/baselib/src/main/res/values/colors.xml b/baselib/src/main/res/values/colors.xml index f59a32a..694c7d2 100644 --- a/baselib/src/main/res/values/colors.xml +++ b/baselib/src/main/res/values/colors.xml @@ -6,5 +6,6 @@ #00FFFFFF #54000000 #EDEDED + #E75D58 #000000 \ No newline at end of file