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 0000000..ad3fe7a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_customer.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_send_msg.png b/app/src/main/res/drawable-xhdpi/ic_send_msg.png new file mode 100644 index 0000000..63ad812 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_send_msg.png differ 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 0000000..32095ea Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_file.png differ diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_file_pre.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_file_pre.png new file mode 100644 index 0000000..e798bbc Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_file_pre.png differ 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 0000000..2af09ca Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_image.png differ 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 0000000..02e9ff9 Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_image_pre.png differ 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 0000000..299761b Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_loaction_pre.png differ 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 0000000..1f643bc Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_location.png differ 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 0000000..5ee2224 Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_video.png differ diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ctype_video_pre.png b/baselib/src/main/res/drawable-xhdpi/ic_ctype_video_pre.png new file mode 100644 index 0000000..2bc16ed Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ctype_video_pre.png differ 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