Kotlin高仿微信-项目实践58篇详细讲解了各个功能点,包括:注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。
效果图:


实现代码:
// 打开相册
ImageSelector.builder()
.useCamera(true) // 设置是否使用拍照
.setSingle(true) //设置是否单选
.canPreview(true) //是否点击放大图片查看,,默认为true
.start(this,REQUEST_CODE)
/**
* author : wangning
* email : maoning20080809@163.com
* Date : 2022/4/15 22:20
* description : 裁剪头像
*/
class ClipImageActivity : AppCompatActivity(), View.OnClickListener {
//类别 1: 圆形头像, 2: 方形头像
private var type = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.wc_clip_image)
type = intent.getIntExtra("type", 1)
initView()
}
/**
* 初始化组件
*/
fun initView() {
//设置点击事件监听器
iv_back.setOnClickListener(this)
btn_cancel.setOnClickListener(this)
bt_ok.setOnClickListener(this)
}
override fun onResume() {
super.onResume()
if (type == 1) {
clipViewLayout1.visibility = View.VISIBLE
clipViewLayout2.visibility = View.GONE
//设置图片资源
clipViewLayout1.setImageSrc(intent.data)
} else {
clipViewLayout2.visibility = View.VISIBLE
clipViewLayout1.visibility = View.GONE
//设置图片资源
clipViewLayout2.setImageSrc(intent.data)
}
}
override fun onClick(v: View) {
when (v.id) {
R.id.iv_back -> finish()
R.id.btn_cancel -> finish()
R.id.bt_ok -> generateUriAndReturn()
}
}
/**
* 生成Uri并且通过setResult返回给打开的activity
*/
private fun generateUriAndReturn() {
//调用返回剪切图
val zoomedCropBitmap: Bitmap?
zoomedCropBitmap = if (type == 1) {
clipViewLayout1.clip()
} else {
clipViewLayout2.clip()
}
if (zoomedCropBitmap == null) {
TagUtils.e( "zoomedCropBitmap == null")
return
}
var file = File(cacheDir, "cropped_" + System.currentTimeMillis() + ".jpg")
val mSaveUri = Uri.fromFile(file)
TagUtils.d("保存路径file:${mSaveUri.path}" )
TagUtils.d("保存路径mSaveUri:${mSaveUri.path}" )
if (mSaveUri != null) {
var outputStream: OutputStream? = null
try {
outputStream = contentResolver.openOutputStream(mSaveUri)
if (outputStream != null) {
zoomedCropBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
}
} catch (ex: IOException) {
Log.e("android", "Cannot open file: $mSaveUri", ex)
} finally {
if (outputStream != null) {
try {
outputStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
val intent = Intent()
intent.data = mSaveUri
setResult(RESULT_OK, intent)
finish()
}
}
companion object {
private const val TAG = "ClipImageActivity"
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE && data != null) {
val images = data.getStringArrayListExtra(ImageSelector.SELECT_RESULT)
if(images != null && images.size > 0) {
gotoClipActivity(images[0])
}
} else if(requestCode == REQUEST_CROP_PHOTO && data != null){
var uri : Uri? = data.data
var bitmap = BitmapFactory.decodeFile(uri?.path)
personal_avatar_img.setImageBitmap(bitmap)
userViewModel.uploadAvatar(uri?.path!!)
}
}
//上传头像
fun uploadAvatar(filePath : String) {
//var filePath = "/sdcard/image/a.jpg"
CoroutineScope(Dispatchers.IO).launch {
var resultFilePath = UploadFileUtils.uploadAvatar(filePath)
if(!TextUtils.isEmpty(resultFilePath)){
var account = DataStoreUtils.getAccount()
var userBean = UserRepository.getUserByAccount(account)
userBean.avatar = resultFilePath
var result = UserRepository.updateUser(userBean)
if(result > 0){
avatarFilePathLiveData.postValue(BaseUtils.BASE_URL_UPLOAD + resultFilePath)
}
val userStr = Gson().toJson(userBean)
UserService.getApi().updateUser(user = userStr)
}
}
}