feat: 新增联系人列表、修改昵称功能
1.新增联系人列表 2.新增修改昵称界面
This commit is contained in:
parent
d4dc9a3b24
commit
53bbc029b9
@ -2,7 +2,19 @@
|
||||
<project version="4">
|
||||
<component name="GitCommitMessageStorage">
|
||||
<option name="messageStorage">
|
||||
<MessageStorage />
|
||||
<MessageStorage>
|
||||
<option name="commitTemplate">
|
||||
<CommitTemplate>
|
||||
<option name="body" value="" />
|
||||
<option name="changes" value="" />
|
||||
<option name="closes" value="" />
|
||||
<option name="scope" value="" />
|
||||
<option name="skipCi" value="" />
|
||||
<option name="subject" value="" />
|
||||
<option name="type" value="refactor" />
|
||||
</CommitTemplate>
|
||||
</option>
|
||||
</MessageStorage>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RenderSettings">
|
||||
<option name="showDecorations" value="true" />
|
||||
</component>
|
||||
</project>
|
@ -72,6 +72,8 @@ dependencies {
|
||||
implementation(libs.shapeview)
|
||||
implementation(libs.shapedrawable)
|
||||
|
||||
implementation(libs.pinyin4j)
|
||||
|
||||
// implementation(libs.therouter)
|
||||
// ksp(libs.therouter.ksp)
|
||||
}
|
||||
|
@ -100,9 +100,58 @@
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
},
|
||||
{
|
||||
"id": "4:6179749773128044271",
|
||||
"lastPropertyId": "9:468674632316468263",
|
||||
"name": "Contact",
|
||||
"properties": [
|
||||
{
|
||||
"id": "1:21644744643871861",
|
||||
"name": "id",
|
||||
"type": 6,
|
||||
"flags": 1
|
||||
},
|
||||
{
|
||||
"id": "2:3202277046871450743",
|
||||
"name": "username",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "3:8037315472776382017",
|
||||
"name": "nickname",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "4:4442492673513561150",
|
||||
"name": "avatarUrl",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "5:5924281870400961702",
|
||||
"name": "signature",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "6:4419123739192764234",
|
||||
"name": "remark",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "7:2091607227595340484",
|
||||
"name": "quanpin",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "9:468674632316468263",
|
||||
"name": "showHeader",
|
||||
"type": 1
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
}
|
||||
],
|
||||
"lastEntityId": "3:4156940900268054047",
|
||||
"lastEntityId": "4:6179749773128044271",
|
||||
"lastIndexId": "0:0",
|
||||
"lastRelationId": "0:0",
|
||||
"lastSequenceId": "0:0",
|
||||
@ -123,7 +172,8 @@
|
||||
3687999935415577905,
|
||||
5421937431301885220,
|
||||
1118829668259721786,
|
||||
1490263641107250384
|
||||
1490263641107250384,
|
||||
2701112806559265255
|
||||
],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
|
@ -102,59 +102,77 @@
|
||||
"relations": []
|
||||
},
|
||||
{
|
||||
"id": "3:4156940900268054047",
|
||||
"lastPropertyId": "6:1490263641107250384",
|
||||
"name": "UserInfo",
|
||||
"id": "4:6179749773128044271",
|
||||
"lastPropertyId": "8:2701112806559265255",
|
||||
"name": "Contact",
|
||||
"properties": [
|
||||
{
|
||||
"id": "1:5682400492130737484",
|
||||
"id": "1:21644744643871861",
|
||||
"name": "id",
|
||||
"type": 6,
|
||||
"flags": 1
|
||||
},
|
||||
{
|
||||
"id": "2:404167074012121135",
|
||||
"name": "avatarUrl",
|
||||
"id": "2:3202277046871450743",
|
||||
"name": "username",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "3:3687999935415577905",
|
||||
"id": "3:8037315472776382017",
|
||||
"name": "nickname",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "4:5421937431301885220",
|
||||
"id": "4:4442492673513561150",
|
||||
"name": "avatarUrl",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "5:5924281870400961702",
|
||||
"name": "signature",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "5:1118829668259721786",
|
||||
"name": "status",
|
||||
"type": 13
|
||||
"id": "6:4419123739192764234",
|
||||
"name": "remark",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "6:1490263641107250384",
|
||||
"name": "username",
|
||||
"id": "7:2091607227595340484",
|
||||
"name": "quanpin",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "8:2701112806559265255",
|
||||
"name": "showHead",
|
||||
"type": 1
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
}
|
||||
],
|
||||
"lastEntityId": "3:4156940900268054047",
|
||||
"lastEntityId": "4:6179749773128044271",
|
||||
"lastIndexId": "0:0",
|
||||
"lastRelationId": "0:0",
|
||||
"lastSequenceId": "0:0",
|
||||
"modelVersion": 5,
|
||||
"modelVersionParserMinimum": 5,
|
||||
"retiredEntityUids": [],
|
||||
"retiredEntityUids": [
|
||||
4156940900268054047
|
||||
],
|
||||
"retiredIndexUids": [],
|
||||
"retiredPropertyUids": [
|
||||
840045868537717781,
|
||||
4549217622013661678,
|
||||
4829352141114779787,
|
||||
5444531588574559639,
|
||||
4896943870878862074
|
||||
4896943870878862074,
|
||||
5682400492130737484,
|
||||
404167074012121135,
|
||||
3687999935415577905,
|
||||
5421937431301885220,
|
||||
1118829668259721786,
|
||||
1490263641107250384
|
||||
],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
|
@ -20,6 +20,9 @@
|
||||
android:theme="@style/Theme.KChatAndroid"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".ui.activity.RenameActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".ui.activity.LaunchActivity"
|
||||
android:exported="true">
|
||||
@ -73,9 +76,6 @@
|
||||
<activity
|
||||
android:name=".ui.activity.ServiceDetailActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".ui.activity.SettingActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".ui.activity.ProfileDetailActivity"
|
||||
android:exported="false" />
|
||||
|
1
app/src/main/assets/loading1.json
Normal file
1
app/src/main/assets/loading1.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.9.0","fr":29.9700012207031,"ip":0,"op":79.000003217736,"w":500,"h":500,"nm":"loading-project-003","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[37.981]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[360]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0]},{"t":66.0000026882351,"s":[360]}],"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2,"l":2},"a":{"a":0,"k":[5,3,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[258,258],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"타원 패스 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":24,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"선 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5,3],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[127.163,127.163],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"변형"}],"nm":"타원 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0.1]},{"t":66.0000026882351,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[99.7]},{"t":29.0000011811942,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"패스 다듬어 자르기 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":80.0000032584668,"st":-25.0000010182709,"bm":0}],"markers":[]}
|
@ -1,7 +1,6 @@
|
||||
package com.kaixed.kchat
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import com.kaixed.kchat.data.objectbox.ObjectBox.get
|
||||
import com.kaixed.kchat.data.objectbox.ObjectBox.init
|
||||
import com.tencent.mmkv.MMKV
|
||||
@ -15,10 +14,10 @@ class KchatApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
val rootDir = MMKV.initialize(this)
|
||||
Log.d("mmkv root: ", rootDir)
|
||||
// Log.d("mmkv root: ", rootDir)
|
||||
|
||||
init(this)
|
||||
val started = Admin(get()).start(this)
|
||||
Log.i("ObjectBoxAdmin", "Started: $started")
|
||||
// Log.i("ObjectBoxAdmin", "Started: $started")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.kaixed.kchat.data.objectbox.entity
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/11/4 13:39
|
||||
*/
|
||||
@Entity
|
||||
data class Contact(
|
||||
@Id
|
||||
var id: Long = 0L,
|
||||
var username: String?,
|
||||
var nickname: String?,
|
||||
var avatarUrl: String?,
|
||||
var signature: String?,
|
||||
var remark: String?,
|
||||
var quanpin: String?,
|
||||
var showHeader: Boolean?
|
||||
)
|
@ -2,6 +2,7 @@ package com.kaixed.kchat.data.objectbox.entity
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
@ -9,6 +10,7 @@ import io.objectbox.annotation.Id
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Serializable
|
||||
data class Messages(
|
||||
@Id
|
||||
var msgLocalId: Long = 0L,
|
||||
@ -20,4 +22,5 @@ data class Messages(
|
||||
var takerId: String,
|
||||
var type: String,
|
||||
var show: Boolean = true,
|
||||
// var isShowTimer: Boolean
|
||||
)
|
||||
|
14
app/src/main/java/com/kaixed/kchat/model/item/FriendItem.kt
Normal file
14
app/src/main/java/com/kaixed/kchat/model/item/FriendItem.kt
Normal file
@ -0,0 +1,14 @@
|
||||
package com.kaixed.kchat.model.item
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/11/2 11:14
|
||||
*/
|
||||
data class FriendItem(
|
||||
val nickname: String,
|
||||
val username: String,
|
||||
val remark: String?,
|
||||
var avatarUrl: String? = "",
|
||||
var firstInSection: Boolean = false,
|
||||
var pinyin: String? = ""
|
||||
)
|
@ -1,9 +0,0 @@
|
||||
package com.kaixed.kchat.model.login
|
||||
|
||||
data class Data(
|
||||
val avatarUrl: String,
|
||||
val nickname: String,
|
||||
val signature: String,
|
||||
val status: Any,
|
||||
val username: String,
|
||||
)
|
@ -1,7 +0,0 @@
|
||||
package com.kaixed.kchat.model.login
|
||||
|
||||
data class Login(
|
||||
val code: String,
|
||||
val `data`: Data,
|
||||
val msg: String,
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package com.kaixed.kchat.model.register
|
||||
package com.kaixed.kchat.model.request
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@ -6,6 +6,7 @@ import kotlinx.serialization.Serializable
|
||||
data class RegisterRequest(
|
||||
val avatarUrl: String,
|
||||
val nickname: String,
|
||||
val telephone: String,
|
||||
val password: String,
|
||||
val signature: String,
|
||||
val username: String
|
@ -1,5 +1,6 @@
|
||||
package com.kaixed.kchat.model.friend
|
||||
package com.kaixed.kchat.model.response.friend
|
||||
|
||||
import com.kaixed.kchat.model.friend.FriendItem
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
@ -8,8 +9,8 @@ import kotlinx.serialization.Serializable
|
||||
*/
|
||||
|
||||
@Serializable
|
||||
data class FriendResponse(
|
||||
data class FriendList(
|
||||
val code: String,
|
||||
val message: String,
|
||||
val data: List<FriendItem>,
|
||||
)
|
||||
val data: List<FriendItem>?,
|
||||
)
|
@ -1,5 +1,6 @@
|
||||
package com.kaixed.kchat.model.search
|
||||
package com.kaixed.kchat.model.response.friend
|
||||
|
||||
import com.kaixed.kchat.model.search.User
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
@ -10,5 +11,5 @@ import kotlinx.serialization.Serializable
|
||||
data class SearchFriends(
|
||||
val code: String,
|
||||
val msg: String,
|
||||
val `data`: User
|
||||
val `data`: User?
|
||||
)
|
@ -0,0 +1,12 @@
|
||||
package com.kaixed.kchat.model.response.login
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Data(
|
||||
val avatarUrl: String,
|
||||
val nickname: String,
|
||||
val signature: String,
|
||||
val status: String?,
|
||||
val username: String,
|
||||
)
|
@ -0,0 +1,10 @@
|
||||
package com.kaixed.kchat.model.response.login
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Login(
|
||||
val code: String,
|
||||
val `data`: Data,
|
||||
val msg: String,
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package com.kaixed.kchat.model.register
|
||||
package com.kaixed.kchat.model.response.register
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.kaixed.kchat.model.register
|
||||
package com.kaixed.kchat.model.response.register
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.kaixed.kchat.model.user
|
||||
package com.kaixed.kchat.model.response.search
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.kaixed.kchat.model.user
|
||||
package com.kaixed.kchat.model.response.search
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.kaixed.kchat.model.user
|
||||
package com.kaixed.kchat.model.response.search
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -1,11 +0,0 @@
|
||||
package com.kaixed.kchat.model.setting
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/10/9 20:35
|
||||
*/
|
||||
data class FunctionItem(
|
||||
val itemName: String,
|
||||
val remark: String,
|
||||
)
|
||||
|
@ -1,10 +0,0 @@
|
||||
package com.kaixed.kchat.model.setting
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/10/9 20:33
|
||||
*/
|
||||
data class NormalItem(
|
||||
val name: String,
|
||||
val group: String,
|
||||
)
|
@ -1,19 +0,0 @@
|
||||
package com.kaixed.kchat.model.setting
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/10/8 13:53
|
||||
*/
|
||||
sealed class SettingItem {
|
||||
data class NormalItem(
|
||||
val name: String,
|
||||
val group: String,
|
||||
) : SettingItem()
|
||||
|
||||
data class FunctionItem(
|
||||
val itemName: String,
|
||||
val remark: String,
|
||||
) : SettingItem()
|
||||
|
||||
data class TitleItem(val title: String) : SettingItem()
|
||||
}
|
@ -11,7 +11,8 @@ object NetworkInterface {
|
||||
const val WEBSOCKET_SERVER_URL = "wss://$URL"
|
||||
const val WEBSOCKET = "/websocket/single/"
|
||||
const val USER_INFO = "/users/info/"
|
||||
const val USER_LOGIN = "/users/login"
|
||||
const val USER_LOGIN_BY_USERNAME = "/users/login/username"
|
||||
const val USER_LOGIN_BY_TELEPHONE = "/users/login/telephone"
|
||||
const val USER_REGISTER = "/users/register"
|
||||
|
||||
const val USER_MESSAGES_COUNT = "/users/%s/%s/msgCounts"
|
||||
|
@ -1,18 +1,24 @@
|
||||
package com.kaixed.kchat.network
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/5/27 8:58
|
||||
*/
|
||||
object OkhttpHelper {
|
||||
private var client: OkHttpClient? = null
|
||||
private val client: OkHttpClient by lazy {
|
||||
OkHttpClient.Builder()
|
||||
// .connectTimeout(10, TimeUnit.SECONDS)
|
||||
// .writeTimeout(10, TimeUnit.SECONDS)
|
||||
// .readTimeout(30, TimeUnit.SECONDS)
|
||||
.pingInterval(15, TimeUnit.SECONDS)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun getInstance(): OkHttpClient {
|
||||
if (client == null) {
|
||||
client = OkHttpClient()
|
||||
}
|
||||
return client!!
|
||||
return client
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,9 @@ import com.google.gson.Gson
|
||||
import com.kaixed.kchat.model.friend.AcceptContactRequest
|
||||
import com.kaixed.kchat.model.friend.ContactRequestResponse
|
||||
import com.kaixed.kchat.model.friend.FriendItem
|
||||
import com.kaixed.kchat.model.friend.FriendResponse
|
||||
import com.kaixed.kchat.model.response.ApplyFriend
|
||||
import com.kaixed.kchat.model.search.SearchFriends
|
||||
import com.kaixed.kchat.model.response.friend.FriendList
|
||||
import com.kaixed.kchat.model.response.friend.SearchFriends
|
||||
import com.kaixed.kchat.network.NetworkInterface.ACCEPT_CONTACT_REQUEST
|
||||
import com.kaixed.kchat.network.NetworkInterface.ADD_FRIEND
|
||||
import com.kaixed.kchat.network.NetworkInterface.FRIEND_LIST
|
||||
@ -81,9 +81,7 @@ class ContactRepo {
|
||||
val contactResponse =
|
||||
Json.decodeFromString<AcceptContactRequest>(responseBody)
|
||||
acceptFriendMutableLiveData.postValue(contactResponse)
|
||||
} ?: run {
|
||||
acceptFriendMutableLiveData.postValue(null)
|
||||
}
|
||||
} ?: acceptFriendMutableLiveData.postValue(null)
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -107,9 +105,7 @@ class ContactRepo {
|
||||
val applyFriend =
|
||||
Json.decodeFromString<ApplyFriend>(responseBody)
|
||||
mutableLiveData.postValue(applyFriend)
|
||||
} ?: run {
|
||||
mutableLiveData.postValue(null)
|
||||
}
|
||||
} ?: mutableLiveData.postValue(null)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
@ -135,9 +131,7 @@ class ContactRepo {
|
||||
response.body?.string()?.let { responseBody ->
|
||||
val searchFriends = Json.decodeFromString<SearchFriends>(responseBody)
|
||||
listMutableLiveData.postValue(searchFriends)
|
||||
} ?: run {
|
||||
listMutableLiveData.postValue(null)
|
||||
}
|
||||
} ?: listMutableLiveData.postValue(null)
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -161,11 +155,9 @@ class ContactRepo {
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
response.body?.string()?.let { responseBody ->
|
||||
val friendList = Gson().fromJson(responseBody, FriendResponse::class.java)
|
||||
val friendList = Gson().fromJson(responseBody, FriendList::class.java)
|
||||
applyFriendMutableLiveData.postValue(friendList.data)
|
||||
} ?: run {
|
||||
applyFriendMutableLiveData.postValue(null)
|
||||
}
|
||||
} ?: applyFriendMutableLiveData.postValue(null)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -1,14 +1,14 @@
|
||||
package com.kaixed.kchat.repository
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.google.gson.Gson
|
||||
import com.kaixed.kchat.model.login.Login
|
||||
import com.kaixed.kchat.model.register.Register
|
||||
import com.kaixed.kchat.model.register.RegisterRequest
|
||||
import com.kaixed.kchat.model.user.UserList
|
||||
import com.kaixed.kchat.model.request.RegisterRequest
|
||||
import com.kaixed.kchat.model.response.login.Login
|
||||
import com.kaixed.kchat.model.response.register.Register
|
||||
import com.kaixed.kchat.model.response.search.UserList
|
||||
import com.kaixed.kchat.network.NetworkInterface.SERVER_URL
|
||||
import com.kaixed.kchat.network.NetworkInterface.USER_LIST
|
||||
import com.kaixed.kchat.network.NetworkInterface.USER_LOGIN
|
||||
import com.kaixed.kchat.network.NetworkInterface.USER_LOGIN_BY_TELEPHONE
|
||||
import com.kaixed.kchat.network.NetworkInterface.USER_LOGIN_BY_USERNAME
|
||||
import com.kaixed.kchat.network.NetworkInterface.USER_REGISTER
|
||||
import com.kaixed.kchat.network.NetworkRequest
|
||||
import kotlinx.serialization.json.Json
|
||||
@ -25,23 +25,25 @@ import java.io.IOException
|
||||
class UserRepo {
|
||||
|
||||
fun register(
|
||||
username: String,
|
||||
password: String,
|
||||
avatarUrl: String,
|
||||
signature: String,
|
||||
nickname: String
|
||||
nickname: String,
|
||||
telephone: String
|
||||
): MutableLiveData<Register?> {
|
||||
val registerMutableLiveData = MutableLiveData<Register?>()
|
||||
|
||||
val registerRequest = RegisterRequest(
|
||||
username = username,
|
||||
username = "",
|
||||
password = password,
|
||||
avatarUrl = avatarUrl,
|
||||
signature = signature,
|
||||
nickname = nickname
|
||||
nickname = nickname,
|
||||
telephone = telephone
|
||||
)
|
||||
|
||||
val json = Json.encodeToString(RegisterRequest.serializer(), registerRequest)
|
||||
val json =
|
||||
Json.encodeToString(RegisterRequest.serializer(), registerRequest)
|
||||
|
||||
NetworkRequest().postAsync(
|
||||
"$SERVER_URL$USER_REGISTER",
|
||||
@ -62,16 +64,25 @@ class UserRepo {
|
||||
return registerMutableLiveData
|
||||
}
|
||||
|
||||
fun login(username: String, password: String): MutableLiveData<Login?> {
|
||||
fun login(
|
||||
username: String,
|
||||
password: String,
|
||||
loginByUsername: Boolean
|
||||
): MutableLiveData<Login?> {
|
||||
val loginMutableLiveData = MutableLiveData<Login?>()
|
||||
|
||||
val url = "$SERVER_URL${
|
||||
if (loginByUsername) USER_LOGIN_BY_USERNAME else USER_LOGIN_BY_TELEPHONE
|
||||
}"
|
||||
|
||||
|
||||
val requestBody = FormBody.Builder()
|
||||
.add("username", username)
|
||||
.add(if (loginByUsername) "username" else "telephone", username)
|
||||
.add("password", password)
|
||||
.build()
|
||||
|
||||
NetworkRequest().postAsync(
|
||||
"$SERVER_URL$USER_LOGIN",
|
||||
url,
|
||||
requestBody,
|
||||
object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
@ -80,7 +91,7 @@ class UserRepo {
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
response.body?.string()?.let { responseBody ->
|
||||
val login = Gson().fromJson(responseBody, Login::class.java)
|
||||
val login = Json.decodeFromString<Login?>(responseBody)
|
||||
loginMutableLiveData.postValue(login)
|
||||
}
|
||||
}
|
||||
@ -100,7 +111,7 @@ class UserRepo {
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
response.body?.string()?.let { responseBody ->
|
||||
val userList = Gson().fromJson(responseBody, UserList::class.java)
|
||||
val userList = Json.decodeFromString<UserList?>(responseBody)
|
||||
listMutableLiveData.postValue(userList)
|
||||
}
|
||||
}
|
||||
@ -108,4 +119,4 @@ class UserRepo {
|
||||
)
|
||||
return listMutableLiveData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ import io.objectbox.Box
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
@ -30,13 +28,15 @@ import okhttp3.WebSocketListener
|
||||
|
||||
class WebSocketService : Service() {
|
||||
|
||||
private val TAG = "WebSocketService"
|
||||
private val HEARTBEAT_ACK = "heartbeat_ack"
|
||||
companion object {
|
||||
private const val TAG = "WebSocketService"
|
||||
private const val WEBSOCKET_CLOSE_CODE = 1000
|
||||
}
|
||||
|
||||
private lateinit var messagesBox: Box<Messages>
|
||||
private lateinit var username: String
|
||||
private val binder = LocalBinder()
|
||||
private val messagesMutableLiveData = MutableLiveData<Messages>()
|
||||
private val HEART_BEAT_RATE = 3000L
|
||||
private var webSocket: WebSocket? = null
|
||||
private var heartbeatJob: Job? = null
|
||||
|
||||
@ -75,12 +75,13 @@ class WebSocketService : Service() {
|
||||
}
|
||||
|
||||
private fun establishConnection() {
|
||||
val request = Request.Builder().url("$WEBSOCKET_SERVER_URL$WEBSOCKET$username").build()
|
||||
val listener = EchoWebSocketListener()
|
||||
val client = OkhttpHelper.getInstance()
|
||||
webSocket = client.newWebSocket(request, listener)
|
||||
|
||||
startHeartbeat()
|
||||
if (webSocket == null) {
|
||||
val request = Request.Builder()
|
||||
.url("$WEBSOCKET_SERVER_URL$WEBSOCKET$username").build()
|
||||
val listener = EchoWebSocketListener()
|
||||
val client = OkhttpHelper.getInstance()
|
||||
webSocket = client.newWebSocket(request, listener)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class EchoWebSocketListener : WebSocketListener() {
|
||||
@ -89,10 +90,6 @@ class WebSocketService : Service() {
|
||||
}
|
||||
|
||||
override fun onMessage(webSocket: WebSocket, text: String) {
|
||||
if (HEARTBEAT_ACK == text) {
|
||||
return
|
||||
}
|
||||
|
||||
val messages = Gson().fromJson(text, Messages::class.java)
|
||||
messages.takerId = messages.senderId
|
||||
messagesMutableLiveData.postValue(messages)
|
||||
@ -115,7 +112,7 @@ class WebSocketService : Service() {
|
||||
}
|
||||
|
||||
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
|
||||
webSocket.close(1000, null)
|
||||
webSocket.close(WEBSOCKET_CLOSE_CODE, null)
|
||||
Log.d(TAG, "WebSocket closing: $reason")
|
||||
establishConnection()
|
||||
}
|
||||
@ -125,19 +122,10 @@ class WebSocketService : Service() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun startHeartbeat() {
|
||||
heartbeatJob = CoroutineScope(IO).launch {
|
||||
while (isActive) {
|
||||
webSocket?.send("heartbeat")
|
||||
delay(HEART_BEAT_RATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
serviceJob.cancel()
|
||||
heartbeatJob?.cancel()
|
||||
webSocket?.close(1000, "App exited")
|
||||
webSocket?.close(WEBSOCKET_CLOSE_CODE, "App exited")
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,20 @@ import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import com.kaixed.kchat.databinding.ActivityApplyAddFriendBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.viewmodel.ApplyFriendViewModel
|
||||
|
||||
class ApplyAddFriendActivity : BaseActivity() {
|
||||
private lateinit var binding: ActivityApplyAddFriendBinding
|
||||
class ApplyAddFriendActivity : BaseActivity<ActivityApplyAddFriendBinding>() {
|
||||
|
||||
private val applyAddFriendViewModel: ApplyFriendViewModel by viewModels()
|
||||
|
||||
override fun inflateBinding(): ActivityApplyAddFriendBinding =
|
||||
ActivityApplyAddFriendBinding.inflate(layoutInflater)
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityApplyAddFriendBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val contactId = intent.getStringExtra("contactId")
|
||||
|
||||
|
@ -9,10 +9,13 @@ import com.bumptech.glide.Glide
|
||||
import com.kaixed.kchat.databinding.ActivityApplyFriendsDetailBinding
|
||||
import com.kaixed.kchat.model.friend.FriendRequestItem
|
||||
import com.kaixed.kchat.model.search.User
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
|
||||
class ApplyFriendsDetailActivity : BaseActivity() {
|
||||
class ApplyFriendsDetailActivity : BaseActivity<ActivityApplyFriendsDetailBinding>() {
|
||||
|
||||
private lateinit var binding: ActivityApplyFriendsDetailBinding
|
||||
override fun inflateBinding(): ActivityApplyFriendsDetailBinding {
|
||||
return ActivityApplyFriendsDetailBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private var request: FriendRequestItem? = null
|
||||
|
||||
@ -22,8 +25,6 @@ class ApplyFriendsDetailActivity : BaseActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityApplyFriendsDetailBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
user = intent.getParcelableExtra("user", User::class.java)
|
||||
request = intent.getParcelableExtra("request", FriendRequestItem::class.java)
|
||||
|
@ -7,19 +7,22 @@ import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import com.kaixed.kchat.databinding.ActivityApproveContactRequestBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.utils.ConstantsUtil.getUsername
|
||||
import com.kaixed.kchat.viewmodel.ContactViewModel
|
||||
|
||||
class ApproveContactRequestActivity : BaseActivity() {
|
||||
class ApproveContactRequestActivity : BaseActivity<ActivityApproveContactRequestBinding>() {
|
||||
|
||||
|
||||
private lateinit var binding: ActivityApproveContactRequestBinding
|
||||
private val contactViewModel: ContactViewModel by viewModels()
|
||||
|
||||
override fun inflateBinding(): ActivityApproveContactRequestBinding {
|
||||
return ActivityApproveContactRequestBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityApproveContactRequestBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setContent()
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
package com.kaixed.kchat.ui.activity
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/10/21 22:32
|
||||
*/
|
||||
open class BaseActivity : AppCompatActivity() {
|
||||
|
||||
fun toast(msg: String) {
|
||||
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import com.kaixed.kchat.service.WebSocketService.LocalBinder
|
||||
import com.kaixed.kchat.ui.adapter.ChatAdapter
|
||||
import com.kaixed.kchat.ui.adapter.EmojiAdapter
|
||||
import com.kaixed.kchat.ui.adapter.FunctionPanelAdapter
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.ui.i.OnItemClickListener
|
||||
import com.kaixed.kchat.utils.Constants.KEYBOARD_HEIGHT_RATIO
|
||||
import com.kaixed.kchat.utils.ConstantsUtil.getKeyboardHeight
|
||||
@ -44,9 +45,7 @@ import io.objectbox.query.QueryBuilder
|
||||
import org.json.JSONObject
|
||||
import java.util.LinkedList
|
||||
|
||||
class ChatActivity : BaseActivity(), OnItemClickListener {
|
||||
|
||||
private lateinit var binding: ActivityChatBinding
|
||||
class ChatActivity : BaseActivity<ActivityChatBinding>(), OnItemClickListener {
|
||||
|
||||
private var chatAdapter: ChatAdapter? = null
|
||||
|
||||
@ -86,11 +85,13 @@ class ChatActivity : BaseActivity(), OnItemClickListener {
|
||||
private const val UNBLOCK_DELAY_TIME = 200L
|
||||
}
|
||||
|
||||
override fun inflateBinding(): ActivityChatBinding {
|
||||
return ActivityChatBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityChatBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
initData()
|
||||
|
||||
@ -271,7 +272,9 @@ class ChatActivity : BaseActivity(), OnItemClickListener {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
if (recyclerView.canScrollVertically(-1) && hasHistory && !loading) {
|
||||
|
||||
loadMoreMessages()
|
||||
|
||||
}
|
||||
// val layoutManager = checkNotNull(recyclerView.layoutManager as LinearLayoutManager?)
|
||||
// val firstVisiblePosition = layoutManager.findLastVisibleItemPosition()
|
||||
@ -443,7 +446,9 @@ class ChatActivity : BaseActivity(), OnItemClickListener {
|
||||
val messagesSize = messagesList.size
|
||||
|
||||
messagesList.addAll(messagesSize, messages1)
|
||||
chatAdapter!!.notifyItemRangeInserted(messagesSize, newMessages.size)
|
||||
binding.recycleChatList.post {
|
||||
chatAdapter!!.notifyItemRangeInserted(messagesSize, newMessages.size)
|
||||
}
|
||||
}
|
||||
|
||||
loading = false
|
||||
|
@ -1,52 +0,0 @@
|
||||
package com.kaixed.kchat.ui.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.kaixed.kchat.databinding.ActivityFriendListBinding
|
||||
import com.kaixed.kchat.model.friend.FriendItem
|
||||
import com.kaixed.kchat.ui.adapter.FriendListAdapter
|
||||
import com.kaixed.kchat.utils.ConstantsUtil.getUsername
|
||||
import com.kaixed.kchat.viewmodel.FriendListViewModel
|
||||
|
||||
class FriendListActivity : BaseActivity() {
|
||||
private lateinit var binding: ActivityFriendListBinding
|
||||
private val friendListViewModel: FriendListViewModel by viewModels()
|
||||
private var friendList: MutableList<FriendItem> = mutableListOf()
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityFriendListBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
getFriendList(getUsername())
|
||||
|
||||
if (friendList.isEmpty()) {
|
||||
binding.tvNothing.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.tvNothing.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.recycleFriendList.layoutManager =
|
||||
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||
binding.recycleFriendList.adapter = FriendListAdapter(friendList, this)
|
||||
}
|
||||
|
||||
private fun getFriendList(username: String) {
|
||||
friendListViewModel.getFriendList(username).observe(this) { value ->
|
||||
value?.let {
|
||||
friendList.addAll(value)
|
||||
binding.recycleFriendList.adapter?.notifyDataSetChanged()
|
||||
|
||||
if (friendList.isEmpty()) {
|
||||
binding.tvNothing.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.tvNothing.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import com.kaixed.kchat.databinding.ActivityLaunchBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.utils.Constants.MMKV_COMMON_DATA
|
||||
import com.kaixed.kchat.utils.Constants.MMKV_USER_SESSION
|
||||
import com.kaixed.kchat.utils.Constants.STATUS_BAR_HEIGHT
|
||||
@ -12,20 +13,20 @@ import com.kaixed.kchat.utils.Constants.USER_LOGIN_STATUS
|
||||
import com.tencent.mmkv.MMKV
|
||||
|
||||
|
||||
class LaunchActivity : BaseActivity() {
|
||||
class LaunchActivity : BaseActivity<ActivityLaunchBinding>() {
|
||||
|
||||
private lateinit var binding: ActivityLaunchBinding
|
||||
override fun inflateBinding(): ActivityLaunchBinding {
|
||||
return ActivityLaunchBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityLaunchBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val mmkvData: MMKV = MMKV.mmkvWithID(MMKV_COMMON_DATA)
|
||||
mmkvData.putInt(STATUS_BAR_HEIGHT, getStatusBarHeight())
|
||||
|
||||
val mmkv = MMKV.mmkvWithID(MMKV_USER_SESSION)
|
||||
val mmkv = MMKV.defaultMMKV()
|
||||
|
||||
if (mmkv.decodeBool(USER_LOGIN_STATUS)) {
|
||||
navigateToMain()
|
||||
|
@ -9,10 +9,10 @@ import android.text.TextWatcher
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kaixed.kchat.R
|
||||
import com.kaixed.kchat.databinding.ActivityLoginBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.utils.Constants.KEYBOARD_HEIGHT_RATIO
|
||||
import com.kaixed.kchat.utils.Constants.MMKV_COMMON_DATA
|
||||
import com.kaixed.kchat.utils.Constants.MMKV_USER_SESSION
|
||||
@ -21,27 +21,29 @@ import com.kaixed.kchat.utils.DrawableUtil.createDrawable
|
||||
import com.kaixed.kchat.viewmodel.LoginViewModel
|
||||
import com.tencent.mmkv.MMKV
|
||||
|
||||
class LoginActivity : AppCompatActivity() {
|
||||
class LoginActivity : BaseActivity<ActivityLoginBinding>() {
|
||||
|
||||
private lateinit var binding: ActivityLoginBinding
|
||||
override fun inflateBinding(): ActivityLoginBinding {
|
||||
return ActivityLoginBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private val mViewModel: LoginViewModel by viewModels()
|
||||
|
||||
private var mmkv: MMKV? = null
|
||||
private val mmkv by lazy { MMKV.mmkvWithID(MMKV_USER_SESSION) }
|
||||
|
||||
private var previousKeyboardHeight = 0
|
||||
private var loginByUsername = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityLoginBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
mmkv = MMKV.mmkvWithID(MMKV_USER_SESSION)
|
||||
|
||||
binding.etUsername.addTextChangedListener(textWatcher)
|
||||
binding.etPassword.addTextChangedListener(textWatcher)
|
||||
|
||||
initView()
|
||||
setListener()
|
||||
|
||||
binding.tvLogin.setOnClickListener {
|
||||
val username = binding.etUsername.text.toString().trim()
|
||||
val password = binding.etPassword.text.toString().trim()
|
||||
@ -49,30 +51,51 @@ class LoginActivity : AppCompatActivity() {
|
||||
if (username.isEmpty() || password.isEmpty()) {
|
||||
Toast.makeText(this, "请输入用户名或密码", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
mViewModel.login(username, password).observe(this) { loginResult ->
|
||||
if (loginResult == null) {
|
||||
runOnUiThread {
|
||||
Toast.makeText(
|
||||
this@LoginActivity,
|
||||
"登录异常",
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
mViewModel.login(username, password, loginByUsername).observe(this) { loginResult ->
|
||||
loginResult?.let {
|
||||
if (it.code == "200") {
|
||||
mmkv.apply {
|
||||
encode("username", loginResult.data.username)
|
||||
encode("nickname", loginResult.data.nickname)
|
||||
encode("avatarUrl", loginResult.data.avatarUrl)
|
||||
}
|
||||
MMKV.defaultMMKV().encode("userLoginStatus", true)
|
||||
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show()
|
||||
navigateToMain()
|
||||
} else {
|
||||
Toast.makeText(this, "登录异常", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else if ("200" == loginResult.code) {
|
||||
mmkv!!.encode("username", loginResult.data.username)
|
||||
mmkv!!.encode("nickname", loginResult.data.nickname)
|
||||
mmkv!!.encode("nickname", loginResult.data.avatarUrl)
|
||||
mmkv!!.encode("userLoginStatus", true)
|
||||
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show()
|
||||
navigateToMain()
|
||||
}
|
||||
} ?: Toast.makeText(this, "登录异常", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
getKeyboardHeight()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
setView()
|
||||
}
|
||||
|
||||
private fun setListener() {
|
||||
binding.ivClose.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
binding.tvChangeLoginWay.setOnClickListener {
|
||||
loginByUsername = !loginByUsername
|
||||
setView()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setView() {
|
||||
binding.tvTitle.text = if (loginByUsername) "用户名登录" else "手机号登录"
|
||||
binding.etUsername.hint = if (loginByUsername) "请填写用户名" else "请填写手机号"
|
||||
binding.tvUsername.text = if (loginByUsername) "用户名" else "手机号"
|
||||
binding.tvChangeLoginWay.text = if (loginByUsername) "手机号登录" else "用户名登录"
|
||||
binding.tvTip.text =
|
||||
if (loginByUsername) "上述账号仅用于登陆验证" else "上述手机号仅用于登陆验证"
|
||||
}
|
||||
|
||||
private fun getKeyboardHeight() {
|
||||
val rootLayout = binding.root
|
||||
|
||||
@ -95,34 +118,36 @@ class LoginActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SimpleTextWatcher : TextWatcher {
|
||||
private val textWatcher = object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
}
|
||||
|
||||
private var textWatcher: TextWatcher = object : SimpleTextWatcher() {
|
||||
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
super.afterTextChanged(s)
|
||||
if (s.isNotEmpty()) {
|
||||
if (binding.etUsername.text.isNotEmpty() && binding.etPassword.text.isNotEmpty()) {
|
||||
binding.tvLogin.setTextColor(
|
||||
|
||||
val isInputValid =
|
||||
binding.etUsername.text.isNotEmpty() && binding.etPassword.text.isNotEmpty()
|
||||
|
||||
binding.tvLogin.apply {
|
||||
setTextColor(
|
||||
if (isInputValid) {
|
||||
ContextCompat.getColor(
|
||||
this@LoginActivity,
|
||||
R.color.white
|
||||
)
|
||||
)
|
||||
binding.tvLogin.background =
|
||||
createDrawable(
|
||||
ContextCompat.getColor(this@LoginActivity, R.color.green),
|
||||
dpToPx(this@LoginActivity, 8)
|
||||
} else {
|
||||
Color.parseColor("#B4B4B4")
|
||||
}
|
||||
)
|
||||
background = createDrawable(
|
||||
if (isInputValid) {
|
||||
ContextCompat.getColor(
|
||||
this@LoginActivity,
|
||||
R.color.green
|
||||
)
|
||||
} else {
|
||||
binding.tvLogin.setTextColor(Color.parseColor("#B4B4B4"))
|
||||
binding.tvLogin.background =
|
||||
createDrawable(Color.parseColor("#E1E1E1"), dpToPx(this@LoginActivity, 8))
|
||||
}
|
||||
} else {
|
||||
Color.parseColor("#E1E1E1")
|
||||
},
|
||||
dpToPx(this@LoginActivity, 8)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,13 @@ import androidx.core.view.WindowCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.kaixed.kchat.R
|
||||
import com.kaixed.kchat.databinding.ActivityMainBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.ui.fragment.ContactFragment
|
||||
import com.kaixed.kchat.ui.fragment.DiscoveryFragment
|
||||
import com.kaixed.kchat.ui.fragment.HomeFragment
|
||||
import com.kaixed.kchat.ui.fragment.MineFragment
|
||||
|
||||
class MainActivity : BaseActivity(), View.OnClickListener {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
class MainActivity : BaseActivity<ActivityMainBinding>(), View.OnClickListener {
|
||||
private var colorMain = 0
|
||||
private var colorBlack = 0
|
||||
|
||||
@ -27,13 +27,15 @@ class MainActivity : BaseActivity(), View.OnClickListener {
|
||||
|
||||
private val fragments = mutableMapOf<Int, Fragment>()
|
||||
|
||||
override fun inflateBinding(): ActivityMainBinding {
|
||||
return ActivityMainBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
// 设置透明状态栏
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
colorMain = ContextCompat.getColor(this, R.color.green)
|
||||
colorBlack = ContextCompat.getColor(this, R.color.black)
|
||||
@ -73,7 +75,6 @@ class MainActivity : BaseActivity(), View.OnClickListener {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun initView() {
|
||||
binding.clHome.setOnClickListener(this)
|
||||
binding.clHome.tag = KEY_HOME_FRAGMENT
|
||||
@ -88,7 +89,6 @@ class MainActivity : BaseActivity(), View.OnClickListener {
|
||||
binding.clMine.tag = KEY_MINE_FRAGMENT
|
||||
}
|
||||
|
||||
|
||||
override fun onClick(view: View) {
|
||||
val key = view.tag as Int
|
||||
showFragment(key)
|
||||
|
@ -1,28 +0,0 @@
|
||||
package com.kaixed.kchat.ui.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.kaixed.kchat.databinding.ActivityProfileBinding
|
||||
import com.kaixed.kchat.ui.fragment.MyBottomSheetFragment
|
||||
|
||||
|
||||
class ProfileActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityProfileBinding
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityProfileBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
binding.clProfile.setOnClickListener {
|
||||
startActivity(Intent(this@ProfileActivity, ProfileDetailActivity::class.java))
|
||||
}
|
||||
|
||||
binding.rlSetting.setOnClickListener {
|
||||
val bottomSheetFragment = MyBottomSheetFragment()
|
||||
bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.tag)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +1,36 @@
|
||||
package com.kaixed.kchat.ui.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.kaixed.kchat.databinding.ActivityProfileDetailBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.utils.ConstantsUtil.getNickName
|
||||
|
||||
class ProfileDetailActivity : BaseActivity<ActivityProfileDetailBinding>() {
|
||||
|
||||
override fun inflateBinding(): ActivityProfileDetailBinding {
|
||||
return ActivityProfileDetailBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
class ProfileDetailActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityProfileDetailBinding
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityProfileDetailBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
binding.ciAvatar.setOnItemClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
setListener()
|
||||
|
||||
binding.ciNickname.setItemDesc(getNickName())
|
||||
}
|
||||
|
||||
private fun setListener() {
|
||||
binding.ciNickname.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(this, RenameActivity::class.java)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,16 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import com.kaixed.kchat.R
|
||||
import com.kaixed.kchat.databinding.ActivityRegisterBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.utils.DensityUtil.dpToPx
|
||||
import com.kaixed.kchat.utils.DrawableUtil.createDrawable
|
||||
import com.kaixed.kchat.viewmodel.UserViewModel
|
||||
|
||||
class RegisterActivity : BaseActivity() {
|
||||
class RegisterActivity : BaseActivity<ActivityRegisterBinding>() {
|
||||
|
||||
private lateinit var binding: ActivityRegisterBinding
|
||||
override fun inflateBinding(): ActivityRegisterBinding {
|
||||
return ActivityRegisterBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private var tvContinueEnable: Boolean = false
|
||||
|
||||
@ -32,8 +35,6 @@ class RegisterActivity : BaseActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityRegisterBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
initView()
|
||||
|
||||
@ -47,13 +48,13 @@ class RegisterActivity : BaseActivity() {
|
||||
|
||||
binding.tvContinue.setOnClickListener {
|
||||
if (tvContinueEnable) {
|
||||
val username = binding.etUsername.text.toString().trim()
|
||||
val telephone = binding.etUsername.text.toString().trim()
|
||||
val nickname = binding.etNickname.text.toString().trim()
|
||||
val password = binding.etPassword.text.toString().trim()
|
||||
val avatarUrl = ""
|
||||
val signature = ""
|
||||
|
||||
mViewModel.register(username, nickname, password, avatarUrl, signature)
|
||||
mViewModel.register(nickname, password, avatarUrl, signature, telephone)
|
||||
.observe(this) { registerResult ->
|
||||
Log.d("haha", registerResult.toString())
|
||||
when (registerResult?.code) {
|
||||
|
@ -0,0 +1,40 @@
|
||||
package com.kaixed.kchat.ui.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import com.kaixed.kchat.databinding.ActivityRenameBinding
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.utils.ConstantsUtil.getNickName
|
||||
import com.kaixed.kchat.utils.WidgetUtil
|
||||
|
||||
class RenameActivity : BaseActivity<ActivityRenameBinding>() {
|
||||
|
||||
override fun inflateBinding(): ActivityRenameBinding {
|
||||
return ActivityRenameBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
||||
val nickname = getNickName()
|
||||
var enable = false
|
||||
|
||||
binding.etNickname.setText(nickname)
|
||||
|
||||
binding.etNickname.addTextChangedListener(
|
||||
afterTextChanged = { et ->
|
||||
enable = et.toString() != nickname
|
||||
binding.ctb.setBtnEnable(et.toString() != nickname)
|
||||
}
|
||||
)
|
||||
|
||||
binding.ctb.setOnBtnClickListener {
|
||||
if (enable) {
|
||||
toast("保存成功")
|
||||
WidgetUtil.showLoadingDialog(this, "正在保存")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
@ -14,27 +15,28 @@ import android.view.Window
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import com.bumptech.glide.Glide
|
||||
import com.kaixed.kchat.databinding.ActivitySearchFriendsBinding
|
||||
import com.kaixed.kchat.databinding.DialogLoadingBinding
|
||||
import com.kaixed.kchat.model.search.User
|
||||
import com.kaixed.kchat.ui.base.BaseActivity
|
||||
import com.kaixed.kchat.viewmodel.SearchFriendsViewModel
|
||||
|
||||
class SearchFriendsActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivitySearchFriendsBinding
|
||||
class SearchFriendsActivity : BaseActivity<ActivitySearchFriendsBinding>() {
|
||||
private var isSearching = false
|
||||
private lateinit var userItem: User
|
||||
private lateinit var loadingDialog: Dialog
|
||||
|
||||
override fun inflateBinding(): ActivitySearchFriendsBinding {
|
||||
return ActivitySearchFriendsBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private val searchFriendsViewModel: SearchFriendsViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivitySearchFriendsBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
initView()
|
||||
|
||||
@ -62,6 +64,7 @@ class SearchFriendsActivity : AppCompatActivity() {
|
||||
binding.clSearchUser.visibility = View.GONE
|
||||
} else {
|
||||
binding.clSearchUser.visibility = View.VISIBLE
|
||||
binding.tvNothing.visibility = View.INVISIBLE
|
||||
|
||||
val spannableString = SpannableString("搜索:$it")
|
||||
val colorSpan = ForegroundColorSpan(Color.parseColor("#2BA245"))
|
||||
@ -90,11 +93,20 @@ class SearchFriendsActivity : AppCompatActivity() {
|
||||
searchFriendsViewModel.searchFriends(username).observe(this) { value ->
|
||||
loadingDialog.dismiss()
|
||||
value?.let {
|
||||
userItem = value.data
|
||||
if (::userItem.isInitialized) {
|
||||
setVisibility(true)
|
||||
setContent()
|
||||
if (value.code == "200") {
|
||||
value.data?.let {
|
||||
userItem = value.data
|
||||
if (::userItem.isInitialized) {
|
||||
setVisibility(true)
|
||||
setContent()
|
||||
}
|
||||
} ?: run {
|
||||
setVisibility(false)
|
||||
binding.tvNothing.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -110,6 +122,7 @@ class SearchFriendsActivity : AppCompatActivity() {
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setCancelable(false)
|
||||
dialog.setContentView(binding.root)
|
||||
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
package com.kaixed.kchat.ui.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.kaixed.kchat.databinding.ActivitySettingBinding
|
||||
import com.kaixed.kchat.model.setting.SettingItem
|
||||
import com.kaixed.kchat.ui.adapter.SettingListAdapter
|
||||
|
||||
class SettingActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivitySettingBinding
|
||||
private lateinit var settingItems: MutableList<SettingItem>
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivitySettingBinding.inflate(layoutInflater)
|
||||
enableEdgeToEdge()
|
||||
setContentView(binding.root)
|
||||
|
||||
settingItems = getSettingItems()
|
||||
binding.rvSetting.layoutManager =
|
||||
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||
binding.rvSetting.adapter = SettingListAdapter(settingItems)
|
||||
}
|
||||
|
||||
private fun getSettingItems(): MutableList<SettingItem> {
|
||||
return mutableListOf(
|
||||
SettingItem.NormalItem("账号与安全", "安全"),
|
||||
SettingItem.TitleItem(""),
|
||||
SettingItem.NormalItem("青少年模式", "模式"),
|
||||
SettingItem.NormalItem("关怀模式", "模式"),
|
||||
SettingItem.TitleItem(""),
|
||||
SettingItem.NormalItem("新消息通知", "杂"),
|
||||
SettingItem.NormalItem("聊天", "杂"),
|
||||
SettingItem.NormalItem("设备", "杂"),
|
||||
SettingItem.NormalItem("通用", "杂"),
|
||||
SettingItem.TitleItem("隐私"),
|
||||
SettingItem.NormalItem("朋友权限", "隐私"),
|
||||
SettingItem.NormalItem("个人信息与权限", "隐私"),
|
||||
SettingItem.NormalItem("个人信息收集清单", "隐私"),
|
||||
SettingItem.NormalItem("第三方信息共享清单", "隐私"),
|
||||
SettingItem.TitleItem(""),
|
||||
SettingItem.NormalItem("插件", "插件"),
|
||||
SettingItem.TitleItem(""),
|
||||
SettingItem.NormalItem("关于", "帮助"),
|
||||
SettingItem.NormalItem("帮助与反馈", "帮助"),
|
||||
SettingItem.TitleItem(""),
|
||||
SettingItem.NormalItem("切换账户", "账户"),
|
||||
SettingItem.NormalItem("退出", "账户")
|
||||
)
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package com.kaixed.kchat.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -142,8 +141,6 @@ class ChatAdapter(
|
||||
is RedPacketViewHolder -> {
|
||||
holder.bindData(singleMessage)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
holder.itemView.setOnLongClickListener {
|
||||
@ -152,19 +149,18 @@ class ChatAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TipViewHolder(val binding: ChatRecycleItemTipBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindData(message: Messages) {
|
||||
if (message.show)
|
||||
if (message.show) {
|
||||
binding.tvTip.text = binding.root.context.getString(
|
||||
R.string.withdraw_message_format,
|
||||
message.senderId
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CustomViewHolder(val binding: ChatRecycleItemCustomBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindData(message: Messages, context: Context) {
|
||||
@ -176,7 +172,6 @@ class ChatAdapter(
|
||||
message.content,
|
||||
DensityUtil.dpToPx(context, 18)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private fun setViewPosition(
|
||||
@ -198,14 +193,18 @@ class ChatAdapter(
|
||||
}
|
||||
|
||||
constraintSet.connect(
|
||||
avatarId, avatarConnectionStart,
|
||||
ConstraintSet.PARENT_ID, avatarConnectionStart,
|
||||
avatarId,
|
||||
avatarConnectionStart,
|
||||
ConstraintSet.PARENT_ID,
|
||||
avatarConnectionStart,
|
||||
margin
|
||||
)
|
||||
|
||||
constraintSet.connect(
|
||||
messageId, avatarConnectionStart,
|
||||
avatarId, avatarConnectionEnd,
|
||||
messageId,
|
||||
avatarConnectionStart,
|
||||
avatarId,
|
||||
avatarConnectionEnd,
|
||||
margin
|
||||
)
|
||||
|
||||
@ -213,43 +212,36 @@ class ChatAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ImageViewHolder(val binding: ChatRecycleItemImageBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindData(message: Messages) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class VoiceViewHolder(val binding: ChatRecycleItemVoiceBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindData(message: Messages) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class LocationViewHolder(val binding: ChatRecycleItemLocationBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindData(message: Messages) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class EmojiViewHolder(val binding: ChatRecycleItemEmojiBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindData(message: Messages) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class RedPacketViewHolder(val binding: ChatRecycleItemRedPacketBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindData(message: Messages) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val message = messages[position]
|
||||
return when (MessageType.fromValue(message.type.toInt())) {
|
||||
|
@ -5,28 +5,45 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.bumptech.glide.Glide
|
||||
import com.kaixed.kchat.databinding.ContactRecycleFooterItemBinding
|
||||
import com.kaixed.kchat.databinding.FriendRecycleFooterItemBinding
|
||||
import com.kaixed.kchat.databinding.FriendRecycleItemBinding
|
||||
import com.kaixed.kchat.model.friend.FriendItem
|
||||
import com.kaixed.kchat.model.item.FriendItem
|
||||
import com.kaixed.kchat.ui.activity.ChatActivity
|
||||
import com.kaixed.kchat.utils.Pinyin4jUtil
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/10/14 14:47
|
||||
*/
|
||||
class FriendListAdapter(private val items: MutableList<FriendItem>, private val context: Context) :
|
||||
class FriendListAdapter(private var items: MutableList<FriendItem>, private val context: Context) :
|
||||
RecyclerView.Adapter<ViewHolder>() {
|
||||
|
||||
class ItemViewHolder(val binding: FriendRecycleItemBinding) : ViewHolder(binding.root)
|
||||
|
||||
class FooterViewHolder(val binding: ContactRecycleFooterItemBinding) : ViewHolder(binding.root)
|
||||
class FooterViewHolder(val binding: FriendRecycleFooterItemBinding) : ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
const val TYPE_ITEM: Int = 0
|
||||
const val TYPE_FOOTER: Int = 1
|
||||
private const val TAG = "FriendListAdapter"
|
||||
}
|
||||
|
||||
fun updateItems(newItems: List<FriendItem>) {
|
||||
val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
|
||||
override fun getOldListSize() = items.size
|
||||
override fun getNewListSize() = newItems.size
|
||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
|
||||
items[oldItemPosition].username == newItems[newItemPosition].username
|
||||
|
||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
|
||||
items[oldItemPosition] == newItems[newItemPosition]
|
||||
})
|
||||
items = newItems.toMutableList()
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
private val defaultItems = listOf(
|
||||
@ -40,7 +57,7 @@ class FriendListAdapter(private val items: MutableList<FriendItem>, private val
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return when (viewType) {
|
||||
TYPE_FOOTER -> {
|
||||
val binding = ContactRecycleFooterItemBinding.inflate(
|
||||
val binding = FriendRecycleFooterItemBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
@ -68,8 +85,17 @@ class FriendListAdapter(private val items: MutableList<FriendItem>, private val
|
||||
|
||||
is ItemViewHolder -> {
|
||||
val item = items[position]
|
||||
// Log.d(TAG, "${item.nickname} ${item.firstInSection}")
|
||||
holder.binding.tvNickname.text = item.nickname
|
||||
|
||||
if (item.firstInSection) {
|
||||
holder.binding.tvLetter.text =
|
||||
Pinyin4jUtil.toPinyin(item.nickname)[0].toString().uppercase()
|
||||
holder.binding.tvLetter.visibility = ViewGroup.VISIBLE
|
||||
} else {
|
||||
holder.binding.tvLetter.visibility = ViewGroup.GONE
|
||||
}
|
||||
|
||||
if (position <= defaultItems.size - 1) {
|
||||
holder.binding.ifvAvatar.setImageResource(defaultItems[position])
|
||||
holder.binding.ifvAvatar.setBackgroundColor(context.getColor(com.kaixed.kchat.R.color.gray))
|
||||
|
@ -1,99 +0,0 @@
|
||||
package com.kaixed.kchat.ui.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.kaixed.kchat.databinding.ItemSettingFunctionBinding
|
||||
import com.kaixed.kchat.databinding.ItemSettingNormalBinding
|
||||
import com.kaixed.kchat.databinding.ItemSettingTitleBinding
|
||||
import com.kaixed.kchat.model.setting.SettingItem
|
||||
import com.kaixed.kchat.utils.Constants.MESSAGE_TYPE_FUNCTION
|
||||
import com.kaixed.kchat.utils.Constants.MESSAGE_TYPE_NORMAL
|
||||
import com.kaixed.kchat.utils.Constants.MESSAGE_TYPE_TITLE
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/10/8 13:53
|
||||
*/
|
||||
class SettingListAdapter(private val items: MutableList<SettingItem>) :
|
||||
RecyclerView.Adapter<ViewHolder>() {
|
||||
|
||||
class NormalViewHolder(val binding: ItemSettingNormalBinding) : ViewHolder(binding.root)
|
||||
class TitleViewHolder(val binding: ItemSettingTitleBinding) : ViewHolder(binding.root)
|
||||
class FunctionViewHolder(val binding: ItemSettingFunctionBinding) : ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return when (viewType) {
|
||||
|
||||
MESSAGE_TYPE_TITLE -> {
|
||||
val binding = ItemSettingTitleBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
TitleViewHolder(binding)
|
||||
}
|
||||
|
||||
MESSAGE_TYPE_NORMAL -> {
|
||||
val binding = ItemSettingNormalBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
NormalViewHolder(binding)
|
||||
}
|
||||
|
||||
MESSAGE_TYPE_FUNCTION -> {
|
||||
val binding = ItemSettingFunctionBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
FunctionViewHolder(binding)
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("Invalid view type")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is TitleViewHolder -> bindTitleViewHolder(holder, position)
|
||||
is NormalViewHolder -> bindNormalViewHolder(holder, position)
|
||||
is FunctionViewHolder -> bindFunctionViewHolder(holder, position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindTitleViewHolder(holder: TitleViewHolder, position: Int) {
|
||||
val item = items[position] as SettingItem.TitleItem
|
||||
holder.binding.tvItemName.text = item.title
|
||||
holder.binding.tvItemName.visibility = if (item.title.isEmpty()) View.GONE else VISIBLE
|
||||
holder.binding.view.visibility = if (item.title.isEmpty()) VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun bindNormalViewHolder(holder: NormalViewHolder, position: Int) {
|
||||
val item = items[position] as SettingItem.NormalItem
|
||||
holder.binding.tvItemName.text = item.name
|
||||
|
||||
holder.binding.viewItemDecoration.visibility =
|
||||
if (position != items.size - 1 && items[position + 1] is SettingItem.TitleItem) View.GONE else VISIBLE
|
||||
}
|
||||
|
||||
private fun bindFunctionViewHolder(holder: FunctionViewHolder, position: Int) {
|
||||
}
|
||||
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (items[position]) {
|
||||
is SettingItem.TitleItem -> MESSAGE_TYPE_TITLE
|
||||
is SettingItem.NormalItem -> MESSAGE_TYPE_NORMAL
|
||||
is SettingItem.FunctionItem -> MESSAGE_TYPE_FUNCTION
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
}
|
27
app/src/main/java/com/kaixed/kchat/ui/base/BaseActivity.kt
Normal file
27
app/src/main/java/com/kaixed/kchat/ui/base/BaseActivity.kt
Normal file
@ -0,0 +1,27 @@
|
||||
package com.kaixed.kchat.ui.base
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.viewbinding.ViewBinding
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/11/4 10:43
|
||||
*/
|
||||
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
|
||||
protected lateinit var binding: VB
|
||||
|
||||
abstract fun inflateBinding(): VB
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = inflateBinding()
|
||||
setContentView(binding.root)
|
||||
}
|
||||
|
||||
fun toast(msg: String) {
|
||||
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
@ -6,19 +6,21 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.kaixed.kchat.R
|
||||
import com.kaixed.kchat.databinding.FragmentContactBinding
|
||||
import com.kaixed.kchat.model.friend.FriendItem
|
||||
import com.kaixed.kchat.model.item.FriendItem
|
||||
import com.kaixed.kchat.ui.adapter.FriendListAdapter
|
||||
import com.kaixed.kchat.ui.base.BaseFragment
|
||||
import com.kaixed.kchat.utils.ConstantsUtil.getUsername
|
||||
import com.kaixed.kchat.viewmodel.FriendListViewModel
|
||||
|
||||
|
||||
class ContactFragment : BaseFragment<FragmentContactBinding>() {
|
||||
|
||||
private val friendListViewModel: FriendListViewModel by viewModels()
|
||||
|
||||
private val friendAdapter: FriendListAdapter by lazy {
|
||||
FriendListAdapter(friendList, requireContext())
|
||||
}
|
||||
|
||||
private var friendList: MutableList<FriendItem> = mutableListOf()
|
||||
|
||||
companion object {
|
||||
@ -35,68 +37,27 @@ class ContactFragment : BaseFragment<FragmentContactBinding>() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
getDefaultItem()
|
||||
getFriendList(getUsername())
|
||||
|
||||
binding.recycleFriendList.layoutManager =
|
||||
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||
binding.recycleFriendList.adapter = FriendListAdapter(friendList, requireContext())
|
||||
binding.recycleFriendList.adapter = friendAdapter
|
||||
getFriendList()
|
||||
}
|
||||
|
||||
|
||||
private fun getFriendList(username: String) {
|
||||
friendListViewModel.getFriendList(username).observe(requireActivity()) { value ->
|
||||
value?.let {
|
||||
friendList.addAll(value)
|
||||
binding.recycleFriendList.adapter?.notifyDataSetChanged()
|
||||
private fun getFriendList() {
|
||||
friendListViewModel.friendListLiveData.observe(viewLifecycleOwner) { friends ->
|
||||
friends?.let {
|
||||
friendList.addAll(friends)
|
||||
friendAdapter.updateItems(friendList)
|
||||
}
|
||||
}
|
||||
friendListViewModel.loadFriendList(getUsername())
|
||||
}
|
||||
|
||||
private fun getDefaultItem() {
|
||||
friendList.add(
|
||||
FriendItem(
|
||||
username = "",
|
||||
avatarUrl = "",
|
||||
nickname = "新的朋友",
|
||||
remark = "",
|
||||
signature = ""
|
||||
)
|
||||
)
|
||||
friendList.add(
|
||||
FriendItem(
|
||||
username = "",
|
||||
avatarUrl = "",
|
||||
nickname = "群聊",
|
||||
remark = "",
|
||||
signature = ""
|
||||
)
|
||||
)
|
||||
friendList.add(
|
||||
FriendItem(
|
||||
username = "",
|
||||
avatarUrl = "",
|
||||
nickname = "标签",
|
||||
remark = "",
|
||||
signature = ""
|
||||
)
|
||||
)
|
||||
friendList.add(
|
||||
FriendItem(
|
||||
username = "",
|
||||
avatarUrl = "",
|
||||
nickname = "公众号",
|
||||
remark = "",
|
||||
signature = ""
|
||||
)
|
||||
)
|
||||
friendList.add(
|
||||
FriendItem(
|
||||
username = "",
|
||||
avatarUrl = "",
|
||||
nickname = "服务号",
|
||||
remark = "",
|
||||
signature = ""
|
||||
)
|
||||
)
|
||||
friendList.add(FriendItem("新的朋友", "", "新的朋友", ""))
|
||||
friendList.add(FriendItem("群聊", "", "群聊", ""))
|
||||
friendList.add(FriendItem("标签", "", "标签", ""))
|
||||
friendList.add(FriendItem("公众号", "", "公众号", ""))
|
||||
friendList.add(FriendItem("服务号", "", "服务号", ""))
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.kaixed.kchat.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -9,6 +10,10 @@ import com.kaixed.kchat.ui.base.BaseFragment
|
||||
|
||||
class DiscoveryFragment : BaseFragment<FragmentDiscoveryBinding>() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "DiscoveryFragment"
|
||||
}
|
||||
|
||||
override fun inflateBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?
|
||||
@ -18,6 +23,7 @@ class DiscoveryFragment : BaseFragment<FragmentDiscoveryBinding>() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
Log.d(TAG,"我加载了")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,9 +28,7 @@ import com.kaixed.kchat.service.WebSocketService
|
||||
import com.kaixed.kchat.service.WebSocketService.LocalBinder
|
||||
import com.kaixed.kchat.ui.activity.AddFriendsActivity
|
||||
import com.kaixed.kchat.ui.activity.ContactUpdatesActivity
|
||||
import com.kaixed.kchat.ui.activity.FriendListActivity
|
||||
import com.kaixed.kchat.ui.activity.MessageActivity
|
||||
import com.kaixed.kchat.ui.activity.ProfileActivity
|
||||
import com.kaixed.kchat.ui.activity.SearchActivity
|
||||
import com.kaixed.kchat.ui.adapter.ChatListAdapter
|
||||
import com.kaixed.kchat.ui.adapter.MyGridAdapter
|
||||
@ -94,11 +92,6 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(), OnChatListItemClickLis
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.ifvAvatar.setOnClickListener {
|
||||
val intent =
|
||||
Intent(context, ProfileActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun flipImage(v: View) {
|
||||
@ -310,12 +303,12 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(), OnChatListItemClickLis
|
||||
}
|
||||
|
||||
6 -> {
|
||||
val intent1 =
|
||||
Intent(
|
||||
context,
|
||||
FriendListActivity::class.java
|
||||
)
|
||||
startActivity(intent1)
|
||||
// val intent1 =
|
||||
// Intent(
|
||||
// context,
|
||||
// FriendListActivity::class.java
|
||||
// )
|
||||
// startActivity(intent1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
package com.kaixed.kchat.ui.fragment
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.kaixed.kchat.R
|
||||
|
||||
|
||||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.root_preferences, rootKey)
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?,
|
||||
): View {
|
||||
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||
view.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white))
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.kaixed.kchat.ui.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -25,9 +26,10 @@ class CustomItem @JvmOverloads constructor(
|
||||
ItemCustomBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
|
||||
init {
|
||||
|
||||
attrs?.let {
|
||||
val typedArray = context.obtainStyledAttributes(it, R.styleable.CustomItem, 0, 0)
|
||||
|
||||
// 获取自定义属性
|
||||
val itemName = typedArray.getString(R.styleable.CustomItem_itemName) ?: ""
|
||||
val itemIconSize = typedArray.getDimension(R.styleable.CustomItem_iconSize, 0f)
|
||||
val itemIcon = typedArray.getResourceId(R.styleable.CustomItem_itemIcon, -1)
|
||||
@ -36,72 +38,96 @@ class CustomItem @JvmOverloads constructor(
|
||||
val itemDesc = typedArray.getString(R.styleable.CustomItem_itemDesc) ?: ""
|
||||
val itemRedTip = typedArray.getBoolean(R.styleable.CustomItem_itemRedTip, false)
|
||||
|
||||
val isShowTopDivider =
|
||||
typedArray.getBoolean(R.styleable.CustomItem_isTopDividerVisible, false)
|
||||
val isShowBottomDivider =
|
||||
typedArray.getBoolean(R.styleable.CustomItem_isBottomDividerVisible, false)
|
||||
|
||||
binding.viewRedTip.visibility = if (itemRedTip) View.VISIBLE else View.GONE
|
||||
|
||||
if (itemDesc.isNotEmpty()) {
|
||||
binding.tvItemDesc.visibility = View.VISIBLE
|
||||
binding.tvItemDesc.text = itemDesc
|
||||
} else {
|
||||
binding.tvItemDesc.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (itemLeftIcon != -1) {
|
||||
binding.ivItemLeftIcon.visibility = View.VISIBLE
|
||||
binding.ivItemLeftIcon.setImageResource(itemLeftIcon)
|
||||
} else {
|
||||
binding.ivItemIcon.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (itemIcon != -1) {
|
||||
binding.ivItemIcon.visibility = View.VISIBLE
|
||||
binding.ivItemIcon.setImageResource(itemIcon)
|
||||
|
||||
val displayMetrics = context.resources.displayMetrics
|
||||
|
||||
if (itemIconRound.toInt() != 0) {
|
||||
val requestOptions =
|
||||
RequestOptions().transform(RoundedCorners(itemIconRound.toInt()))
|
||||
Glide.with(context).load(itemIcon).apply(requestOptions)
|
||||
.into(binding.ivItemIcon)
|
||||
binding.ivItemIcon.clipToOutline = true
|
||||
}
|
||||
|
||||
if (itemIconSize.toInt() != 0) {
|
||||
binding.ivItemIcon.layoutParams.width =
|
||||
(itemIconSize * displayMetrics.density).toInt()
|
||||
binding.ivItemIcon.layoutParams.height =
|
||||
(itemIconSize * displayMetrics.density).toInt()
|
||||
} else {
|
||||
binding.ivItemIcon.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
binding.ivItemIcon.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (itemName.isNotEmpty()) {
|
||||
binding.tvItemName.text = itemName
|
||||
}
|
||||
|
||||
binding.decorationTop.visibility =
|
||||
if (isShowTopDivider) View.VISIBLE else View.GONE
|
||||
|
||||
binding.decorationBottom.visibility =
|
||||
if (isShowBottomDivider) View.VISIBLE else View.GONE
|
||||
// 设置视图
|
||||
setupRedTip(itemRedTip)
|
||||
setupItemDesc(itemDesc)
|
||||
setupLeftIcon(itemLeftIcon)
|
||||
setupItemIcon(itemIcon, itemIconSize, itemIconRound)
|
||||
setupItemName(itemName)
|
||||
setupDividers(typedArray)
|
||||
|
||||
typedArray.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
// 设置红点显示
|
||||
private fun setupRedTip(itemRedTip: Boolean) {
|
||||
binding.viewRedTip.visibility = if (itemRedTip) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// 设置描述
|
||||
private fun setupItemDesc(itemDesc: String) {
|
||||
if (itemDesc.isNotEmpty()) {
|
||||
binding.tvItemDesc.visibility = View.VISIBLE
|
||||
binding.tvItemDesc.text = itemDesc
|
||||
} else {
|
||||
binding.tvItemDesc.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
// 设置左侧图标
|
||||
private fun setupLeftIcon(itemLeftIcon: Int) {
|
||||
if (itemLeftIcon != -1) {
|
||||
binding.ivItemLeftIcon.visibility = View.VISIBLE
|
||||
binding.ivItemLeftIcon.setImageResource(itemLeftIcon)
|
||||
} else {
|
||||
binding.ivItemLeftIcon.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
// 设置主图标
|
||||
private fun setupItemIcon(itemIcon: Int, itemIconSize: Float, itemIconRound: Float) {
|
||||
if (itemIcon != -1) {
|
||||
binding.ivItemIcon.visibility = View.VISIBLE
|
||||
binding.ivItemIcon.setImageResource(itemIcon)
|
||||
|
||||
if (itemIconSize > 0) {
|
||||
binding.ivItemIcon.layoutParams.width = itemIconSize.toInt()
|
||||
binding.ivItemIcon.layoutParams.height = itemIconSize.toInt()
|
||||
}
|
||||
|
||||
if (itemIconRound > 0) {
|
||||
val requestOptions =
|
||||
RequestOptions().transform(RoundedCorners(itemIconRound.toInt()))
|
||||
Glide.with(context).load(itemIcon).apply(requestOptions)
|
||||
.into(binding.ivItemIcon)
|
||||
binding.ivItemIcon.clipToOutline = true
|
||||
}
|
||||
} else {
|
||||
binding.ivItemIcon.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
// 设置项名称
|
||||
private fun setupItemName(itemName: String) {
|
||||
if (itemName.isNotEmpty()) {
|
||||
binding.tvItemName.text = itemName
|
||||
}
|
||||
}
|
||||
|
||||
// 设置分割线
|
||||
private fun setupDividers(typedArray: TypedArray) {
|
||||
val isShowTopDivider =
|
||||
typedArray.getBoolean(R.styleable.CustomItem_isTopDividerVisible, false)
|
||||
val isShowBottomDivider =
|
||||
typedArray.getBoolean(R.styleable.CustomItem_isBottomDividerVisible, false)
|
||||
|
||||
binding.decorationTop.visibility = if (isShowTopDivider) View.VISIBLE else View.GONE
|
||||
binding.decorationBottom.visibility = if (isShowBottomDivider) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// 设置点击事件
|
||||
fun setOnItemClickListener(listener: OnClickListener) {
|
||||
binding.root.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
// 设置红点的可见性
|
||||
fun setRedTipVisibility(visible: Boolean) {
|
||||
binding.viewRedTip.visibility = if (visible) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// 设置描述
|
||||
fun setItemDesc(str: String) {
|
||||
binding.tvItemDesc.text = str
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package com.kaixed.kchat.ui.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import com.kaixed.kchat.R
|
||||
import com.kaixed.kchat.databinding.PreferenceCustomLayoutBinding
|
||||
|
||||
class CustomPreference @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
) : Preference(context, attrs, defStyleAttr) {
|
||||
|
||||
private var isShowTopDivider = false
|
||||
private var isShowBottomDivider = false
|
||||
|
||||
init {
|
||||
layoutResource = R.layout.preference_custom_layout
|
||||
|
||||
attrs?.let {
|
||||
val typedArray = context.obtainStyledAttributes(it, R.styleable.CustomPreference, 0, 0)
|
||||
val isShowTopDivider =
|
||||
typedArray.getBoolean(R.styleable.CustomPreference_isShowTopDivider, false)
|
||||
val isShowBottomDivider =
|
||||
typedArray.getBoolean(R.styleable.CustomPreference_isShowBottomDivider, false)
|
||||
typedArray.recycle()
|
||||
|
||||
this.isShowTopDivider = isShowTopDivider
|
||||
this.isShowBottomDivider = isShowBottomDivider
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
holder.isDividerAllowedAbove = false
|
||||
holder.isDividerAllowedBelow = false
|
||||
|
||||
val binding = PreferenceCustomLayoutBinding.bind(holder.itemView)
|
||||
|
||||
|
||||
binding.tvItemName.text = title
|
||||
|
||||
binding.decorationTop.visibility = if (isShowTopDivider) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
binding.decorationBottom.visibility = if (isShowBottomDivider) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package com.kaixed.kchat.ui.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.preference.PreferenceCategory
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import com.kaixed.kchat.R
|
||||
import com.kaixed.kchat.databinding.PreferenceCategoryCustomLayoutBinding
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/10/10 14:45
|
||||
*/
|
||||
class CustomPreferenceCategory @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
) : PreferenceCategory(context, attrs, defStyleAttr) {
|
||||
|
||||
private var title = ""
|
||||
|
||||
init {
|
||||
layoutResource = R.layout.preference_category_custom_layout
|
||||
|
||||
attrs?.let {
|
||||
val typedArray =
|
||||
context.obtainStyledAttributes(it, R.styleable.CustomPreferenceCategory, 0, 0)
|
||||
val title = typedArray.getString(R.styleable.CustomPreferenceCategory_itemTitle)
|
||||
typedArray.recycle()
|
||||
if (title != null) {
|
||||
Log.d("haha", title)
|
||||
this.title = title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
|
||||
val binding = PreferenceCategoryCustomLayoutBinding.bind(holder.itemView)
|
||||
|
||||
Log.d("haha1", title)
|
||||
|
||||
if (title.isNotEmpty()) {
|
||||
binding.tvTitle.text = title
|
||||
binding.decoration.visibility = View.GONE
|
||||
binding.tvTitle.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.decoration.visibility = View.VISIBLE
|
||||
binding.tvTitle.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
@ -2,10 +2,12 @@ package com.kaixed.kchat.ui.widget
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.kaixed.kchat.R
|
||||
import com.kaixed.kchat.databinding.ViewTitleBarBinding
|
||||
|
||||
@ -27,6 +29,8 @@ class CustomTitleBar @JvmOverloads constructor(
|
||||
val typedArray = context.obtainStyledAttributes(it, R.styleable.CustomTitleBar, 0, 0)
|
||||
val titleName = typedArray.getString(R.styleable.CustomTitleBar_titleName) ?: ""
|
||||
val titleIcon = typedArray.getResourceId(R.styleable.CustomTitleBar_titleIcon, -1)
|
||||
val btnName = typedArray.getString(R.styleable.CustomTitleBar_btnName) ?: ""
|
||||
|
||||
|
||||
if (titleIcon != -1) {
|
||||
binding.ivSetting.visibility = View.VISIBLE
|
||||
@ -41,6 +45,9 @@ class CustomTitleBar @JvmOverloads constructor(
|
||||
} else {
|
||||
binding.tvTitleName.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.tvSave.visibility = if (btnName.isNotEmpty()) View.VISIBLE else View.INVISIBLE
|
||||
|
||||
typedArray.recycle()
|
||||
}
|
||||
|
||||
@ -52,4 +59,15 @@ class CustomTitleBar @JvmOverloads constructor(
|
||||
fun setOnSettingClickListener(listener: OnClickListener?) {
|
||||
binding.ivSetting.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
fun setBtnEnable(enable: Boolean) {
|
||||
val colorEnable = ContextCompat.getColor(context, R.color.white)
|
||||
val color = Color.parseColor("#BFBFBF")
|
||||
binding.tvSave.setTextColor(if (enable) colorEnable else color)
|
||||
binding.tvSave.setBackgroundResource(if (enable) R.drawable.bac_ctb_save_enable else R.drawable.bac_ctb_save)
|
||||
}
|
||||
|
||||
fun setOnBtnClickListener(listener: OnClickListener?) {
|
||||
binding.tvSave.setOnClickListener(listener)
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,11 @@ object Constants {
|
||||
|
||||
// mmkv
|
||||
const val MMKV_USER_SESSION: String = "userSession"
|
||||
const val USER_LOGIN_STATUS: String = "userLoginStatus"
|
||||
const val MMKV_COMMON_DATA: String = "commonData"
|
||||
|
||||
const val USERNAME_KEY = "username"
|
||||
|
||||
const val MESSAGE_TYPE_NORMAL: Int = 1
|
||||
const val MESSAGE_TYPE_FUNCTION: Int = 2
|
||||
const val MESSAGE_TYPE_TITLE: Int = 2
|
||||
|
||||
const val NICKNAME_KEY = "nickname"
|
||||
const val USER_LOGIN_STATUS: String = "userLoginStatus"
|
||||
const val STATUS_BAR_HEIGHT = "status_bar_height"
|
||||
const val KEYBOARD_HEIGHT = "keyboardHeight"
|
||||
|
||||
|
@ -4,6 +4,7 @@ import com.kaixed.kchat.utils.Constants.KEYBOARD_DEFAULT_HEIGHT
|
||||
import com.kaixed.kchat.utils.Constants.KEYBOARD_HEIGHT
|
||||
import com.kaixed.kchat.utils.Constants.MMKV_COMMON_DATA
|
||||
import com.kaixed.kchat.utils.Constants.MMKV_USER_SESSION
|
||||
import com.kaixed.kchat.utils.Constants.NICKNAME_KEY
|
||||
import com.kaixed.kchat.utils.Constants.STATUS_BAR_DEFAULT_HEIGHT
|
||||
import com.kaixed.kchat.utils.Constants.STATUS_BAR_HEIGHT
|
||||
import com.kaixed.kchat.utils.Constants.USERNAME_KEY
|
||||
@ -15,12 +16,18 @@ import com.tencent.mmkv.MMKV
|
||||
*/
|
||||
object ConstantsUtil {
|
||||
|
||||
fun getKeyboardHeight(): Int = MMKV.mmkvWithID(MMKV_COMMON_DATA)
|
||||
.getInt(KEYBOARD_HEIGHT, KEYBOARD_DEFAULT_HEIGHT)
|
||||
private val commonDataMMKV by lazy { MMKV.mmkvWithID(MMKV_COMMON_DATA) }
|
||||
private val userSessionMMKV by lazy { MMKV.mmkvWithID(MMKV_USER_SESSION) }
|
||||
|
||||
fun getUsername(): String = MMKV.mmkvWithID(MMKV_USER_SESSION)
|
||||
.getString(USERNAME_KEY, "").toString()
|
||||
fun getKeyboardHeight(): Int =
|
||||
commonDataMMKV.getInt(KEYBOARD_HEIGHT, KEYBOARD_DEFAULT_HEIGHT)
|
||||
|
||||
fun getStatusBarHeight(): Int = MMKV.mmkvWithID(MMKV_COMMON_DATA)
|
||||
.getInt(STATUS_BAR_HEIGHT, STATUS_BAR_DEFAULT_HEIGHT)
|
||||
fun getUsername(): String =
|
||||
userSessionMMKV.getString(USERNAME_KEY, "") ?: ""
|
||||
|
||||
fun getStatusBarHeight(): Int =
|
||||
commonDataMMKV.getInt(STATUS_BAR_HEIGHT, STATUS_BAR_DEFAULT_HEIGHT)
|
||||
|
||||
fun getNickName(): String =
|
||||
userSessionMMKV.getString(NICKNAME_KEY, "") ?: ""
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import android.content.Context
|
||||
object DensityUtil {
|
||||
|
||||
// 防止实例化,使用 object 即单例
|
||||
fun dpToPx(mContext: Context, dp: Int): Int =
|
||||
(mContext.resources.displayMetrics.density * dp).toInt()
|
||||
fun dpToPx(context: Context, dp: Int): Int =
|
||||
(context.resources.displayMetrics.density * dp).toInt()
|
||||
|
||||
fun pxToDp(mContext: Context, px: Int): Int =
|
||||
(px / mContext.resources.displayMetrics.density).toInt()
|
||||
|
51
app/src/main/java/com/kaixed/kchat/utils/Pinyin4jUtil.kt
Normal file
51
app/src/main/java/com/kaixed/kchat/utils/Pinyin4jUtil.kt
Normal file
@ -0,0 +1,51 @@
|
||||
package com.kaixed.kchat.utils
|
||||
|
||||
import com.kaixed.kchat.utils.Utils.isChinese
|
||||
import com.kaixed.kchat.utils.Utils.isEnglish
|
||||
import net.sourceforge.pinyin4j.PinyinHelper
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/11/2 14:30
|
||||
*/
|
||||
object Pinyin4jUtil {
|
||||
fun toPinyin(chineseText: String): String {
|
||||
val pinyinBuilder = StringBuilder()
|
||||
|
||||
val format = HanyuPinyinOutputFormat()
|
||||
format.toneType = HanyuPinyinToneType.WITHOUT_TONE
|
||||
|
||||
for (char in chineseText) {
|
||||
val pinyinArray = PinyinHelper.toHanyuPinyinStringArray(char, format)
|
||||
if (pinyinArray != null && pinyinArray.isNotEmpty()) {
|
||||
val pinyinWithoutTone = pinyinArray[0]
|
||||
pinyinBuilder.append(pinyinWithoutTone)
|
||||
} else {
|
||||
pinyinBuilder.append(char)
|
||||
}
|
||||
}
|
||||
return pinyinBuilder.toString()
|
||||
}
|
||||
|
||||
fun compare(name1: String, name2: String): Int {
|
||||
val nickname1 = toPinyin(name1)
|
||||
val nickname2 = toPinyin(name2)
|
||||
if (nickname1 == nickname2) {
|
||||
return 0
|
||||
}
|
||||
if (!isEnglishOrChinese(nickname1[0].toString()) && isEnglishOrChinese(nickname2[0].toString())) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if (isEnglishOrChinese(nickname1[0].toString()) && !isEnglishOrChinese(nickname2[0].toString())) {
|
||||
return -1
|
||||
}
|
||||
return if (toPinyin(nickname1) > toPinyin(nickname2)) 1 else -1
|
||||
}
|
||||
|
||||
private fun isEnglishOrChinese(str: String): Boolean {
|
||||
return isChinese(str) || isEnglish(str)
|
||||
}
|
||||
}
|
16
app/src/main/java/com/kaixed/kchat/utils/Utils.kt
Normal file
16
app/src/main/java/com/kaixed/kchat/utils/Utils.kt
Normal file
@ -0,0 +1,16 @@
|
||||
package com.kaixed.kchat.utils
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/11/2 13:21
|
||||
*/
|
||||
object Utils {
|
||||
|
||||
fun isChinese(str: String?): Boolean {
|
||||
return str?.matches(".*[\\u4E00-\\u9FFF].*".toRegex()) ?: false
|
||||
}
|
||||
|
||||
fun isEnglish(str: String?): Boolean {
|
||||
return str != null && str.matches("^[a-zA-Z]+$".toRegex())
|
||||
}
|
||||
}
|
31
app/src/main/java/com/kaixed/kchat/utils/WidgetUtil.kt
Normal file
31
app/src/main/java/com/kaixed/kchat/utils/WidgetUtil.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package com.kaixed.kchat.utils
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Window
|
||||
import com.kaixed.kchat.databinding.DialogLoadingBinding
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/11/5 21:26
|
||||
*/
|
||||
object WidgetUtil {
|
||||
fun showLoadingDialog(context: Context, str: String): Dialog {
|
||||
val binding = DialogLoadingBinding.inflate(LayoutInflater.from(context))
|
||||
val dialog = Dialog(context)
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setCancelable(false)
|
||||
dialog.setContentView(binding.root)
|
||||
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
val params = binding.root.layoutParams
|
||||
params.height = DensityUtil.dpToPx(context, 150)
|
||||
params.width = DensityUtil.dpToPx(context, 150)
|
||||
binding.root.layoutParams = params
|
||||
binding.tvLoading.text = str
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.kaixed.kchat.model.friend.AcceptContactRequest
|
||||
import com.kaixed.kchat.model.friend.ContactRequestResponse
|
||||
import com.kaixed.kchat.model.search.SearchFriends
|
||||
import com.kaixed.kchat.model.response.friend.SearchFriends
|
||||
import com.kaixed.kchat.repository.ContactRepo
|
||||
|
||||
/**
|
||||
|
@ -1,9 +1,12 @@
|
||||
package com.kaixed.kchat.viewmodel
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.kaixed.kchat.model.friend.FriendItem
|
||||
import com.kaixed.kchat.model.item.FriendItem
|
||||
import com.kaixed.kchat.repository.ContactRepo
|
||||
import com.kaixed.kchat.utils.Pinyin4jUtil
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
@ -12,6 +15,44 @@ import com.kaixed.kchat.repository.ContactRepo
|
||||
class FriendListViewModel : ViewModel() {
|
||||
private val contactRepo = ContactRepo()
|
||||
|
||||
fun getFriendList(username: String): MutableLiveData<List<FriendItem>?> =
|
||||
contactRepo.getContactList(username)
|
||||
companion object {
|
||||
private const val TAG = "FriendListViewModel"
|
||||
}
|
||||
|
||||
private val _friendListLiveData = MutableLiveData<List<FriendItem>?>()
|
||||
val friendListLiveData: LiveData<List<FriendItem>?> get() = _friendListLiveData
|
||||
|
||||
fun loadFriendList(username: String) {
|
||||
contactRepo.getContactList(username).observeForever { friendList ->
|
||||
|
||||
val uiFriendList = friendList?.map { networkItem ->
|
||||
mapToFriendItem(networkItem)
|
||||
}?.sortedWith { f1, f2 ->
|
||||
Pinyin4jUtil.compare(f1.nickname, f2.nickname)
|
||||
}?.toMutableList() // 确保是可变列表,以便后续更新 firstInSection
|
||||
|
||||
val startTime = System.currentTimeMillis()
|
||||
|
||||
uiFriendList?.forEachIndexed { index, item ->
|
||||
item.firstInSection =
|
||||
(index == 0 || item.pinyin?.get(index) != uiFriendList[index - 1].pinyin?.get(
|
||||
index - 1
|
||||
))
|
||||
}
|
||||
val duration = System.currentTimeMillis() - startTime
|
||||
Log.d(TAG, "Execution time: ${duration}ms")
|
||||
_friendListLiveData.value = uiFriendList
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapToFriendItem(response: com.kaixed.kchat.model.friend.FriendItem): FriendItem {
|
||||
val pinyin = Pinyin4jUtil.toPinyin(response.nickname)
|
||||
return FriendItem(
|
||||
nickname = response.nickname,
|
||||
username = response.username,
|
||||
remark = response.remark,
|
||||
avatarUrl = response.avatarUrl,
|
||||
pinyin = pinyin
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package com.kaixed.kchat.viewmodel
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.kaixed.kchat.model.login.Login
|
||||
import com.kaixed.kchat.model.response.login.Login
|
||||
import com.kaixed.kchat.repository.UserRepo
|
||||
|
||||
/**
|
||||
@ -12,6 +12,6 @@ import com.kaixed.kchat.repository.UserRepo
|
||||
class LoginViewModel : ViewModel() {
|
||||
private val userRepo: UserRepo = UserRepo()
|
||||
|
||||
fun login(username: String, password: String): MutableLiveData<Login?> =
|
||||
userRepo.login(username, password)
|
||||
fun login(username: String, password: String, loginByUsername :Boolean): MutableLiveData<Login?> =
|
||||
userRepo.login(username, password, loginByUsername)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package com.kaixed.kchat.viewmodel
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.kaixed.kchat.model.search.SearchFriends
|
||||
import com.kaixed.kchat.model.response.friend.SearchFriends
|
||||
import com.kaixed.kchat.repository.ContactRepo
|
||||
|
||||
/**
|
||||
|
@ -2,8 +2,8 @@ package com.kaixed.kchat.viewmodel
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.kaixed.kchat.model.register.Register
|
||||
import com.kaixed.kchat.model.user.UserList
|
||||
import com.kaixed.kchat.model.response.register.Register
|
||||
import com.kaixed.kchat.model.response.search.UserList
|
||||
import com.kaixed.kchat.repository.UserRepo
|
||||
|
||||
/**
|
||||
@ -17,12 +17,12 @@ class UserViewModel : ViewModel() {
|
||||
userRepo.getUserListByNickname(username)
|
||||
|
||||
fun register(
|
||||
username: String,
|
||||
password: String,
|
||||
nickname: String,
|
||||
avatarUrl: String,
|
||||
signature: String,
|
||||
telephone: String
|
||||
): MutableLiveData<Register?> =
|
||||
userRepo.register(username, password, nickname, avatarUrl, signature)
|
||||
userRepo.register( password, nickname, avatarUrl, signature, telephone)
|
||||
|
||||
}
|
||||
|
8
app/src/main/res/drawable/bac_ctb_save.xml
Normal file
8
app/src/main/res/drawable/bac_ctb_save.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#E1E1E1" />
|
||||
|
||||
<corners android:radius="6dp" />
|
||||
|
||||
</shape>
|
8
app/src/main/res/drawable/bac_ctb_save_enable.xml
Normal file
8
app/src/main/res/drawable/bac_ctb_save_enable.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#07C160" />
|
||||
|
||||
<corners android:radius="6dp" />
|
||||
|
||||
</shape>
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size android:width="2dp" />
|
||||
<size android:width="1dp" />
|
||||
<!-- <solid android:color="#1772F6"/>-->
|
||||
<solid android:color="@color/green" />
|
||||
</shape>
|
||||
|
@ -9,22 +9,32 @@
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.activity.LoginActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_close"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:src="@drawable/ic_close"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="50dp"
|
||||
android:text="手机号/用户名登录"
|
||||
android:text="手机号登录"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="24sp"
|
||||
android:textSize="21sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@id/iv_close" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_height="0.2dp"
|
||||
android:layout_marginTop="50dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title" />
|
||||
|
||||
@ -34,9 +44,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="账号"
|
||||
android:text="手机号"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="19sp"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/view" />
|
||||
|
||||
@ -49,6 +59,7 @@
|
||||
android:background="@null"
|
||||
android:hint="请填写手机号或用户名"
|
||||
android:textCursorDrawable="@drawable/cursor"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/view1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_username"
|
||||
@ -57,7 +68,7 @@
|
||||
<View
|
||||
android:id="@+id/view1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_height="0.2dp"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:background="#D8D8D8"
|
||||
@ -71,7 +82,7 @@
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="密码"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="19sp"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/view1" />
|
||||
|
||||
@ -79,28 +90,38 @@
|
||||
android:id="@+id/et_password"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_marginStart="35dp"
|
||||
android:background="@null"
|
||||
android:hint="请填写密码"
|
||||
android:inputType="textPassword"
|
||||
android:textCursorDrawable="@drawable/cursor"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/view2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_password"
|
||||
app:layout_constraintStart_toStartOf="@id/et_username"
|
||||
app:layout_constraintTop_toBottomOf="@id/view1" />
|
||||
|
||||
|
||||
<View
|
||||
android:id="@+id/view2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_height="0.2dp"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:background="#D8D8D8"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_password" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_change_login_way"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="用户名登录"
|
||||
android:textColor="@color/normal"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_username"
|
||||
app:layout_constraintTop_toBottomOf="@id/view2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_tip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="15dp"
|
||||
|
@ -20,7 +20,6 @@
|
||||
android:background="@color/white"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
@ -53,7 +52,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="主页"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="10sp"
|
||||
android:textSize="11sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/iv_home" />
|
||||
@ -86,7 +85,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="联系人"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="10sp"
|
||||
android:textSize="11sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/iv_contact" />
|
||||
@ -112,13 +111,23 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:background="@drawable/icon_red_dot"
|
||||
app:layout_constraintCircle="@id/iv_discovery"
|
||||
app:layout_constraintCircleAngle="45"
|
||||
app:layout_constraintCircleRadius="15dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_discovery"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发现"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="10sp"
|
||||
android:textSize="11sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/iv_discovery" />
|
||||
@ -152,14 +161,11 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="我的"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="10sp"
|
||||
android:textSize="11sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/iv_mine" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -1,334 +0,0 @@
|
||||
<?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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.activity.ProfileActivity">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cl_profile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="15dp"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/ifv_avatar"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="55dp"
|
||||
android:src="@drawable/ic_avatar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:roundPercent="0.3" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_nickname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="糕菜菜"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintStart_toEndOf="@id/ifv_avatar"
|
||||
app:layout_constraintTop_toTopOf="@id/ifv_avatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="kid: kaixed"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/ifv_avatar"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_nickname"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_nickname" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cl_profile_right_arrow"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_arrow_right"
|
||||
app:layout_constraintBottom_toBottomOf="@id/ifv_avatar"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_qrcode"
|
||||
app:layout_constraintBottom_toBottomOf="@id/cl_profile_right_arrow"
|
||||
app:layout_constraintEnd_toStartOf="@id/cl_profile_right_arrow"
|
||||
app:layout_constraintTop_toTopOf="@id/cl_profile_right_arrow" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_setting_items"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/cl_profile">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp"
|
||||
android:background="#E5E5E5" />
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingStart="15dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_service"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/mine_icon_service" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_service"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toEndOf="@id/iv_service"
|
||||
android:text="服务"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_arrow_right" />
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp"
|
||||
android:background="#E5E5E5" />
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingStart="15dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_collection"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/mine_icon_collection" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toEndOf="@id/iv_collection"
|
||||
android:text="收藏"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_arrow_right" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:background="#E5E5E5" />
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingStart="15dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_friend_circle"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/mine_icon_friend_circle" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toEndOf="@id/iv_friend_circle"
|
||||
android:text="朋友圈"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_arrow_right" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:background="#E5E5E5" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingStart="15dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_wallet"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/mine_icon_wallet" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toEndOf="@id/iv_wallet"
|
||||
android:text="卡包"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_arrow_right" />
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:background="#E5E5E5" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingStart="15dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_emoji"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/mine_icon_emoji" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toEndOf="@id/iv_emoji"
|
||||
android:text="表情"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_arrow_right" />
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp"
|
||||
android:background="#E5E5E5" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_setting"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingStart="15dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_setting"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/mine_icon_setting" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_setting"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toEndOf="@id/iv_setting"
|
||||
android:text="设置"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<View
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@id/tv_setting"
|
||||
android:background="@drawable/icon_red_dot" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/icon_arrow_right" />
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#E5E5E5" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -28,8 +28,8 @@
|
||||
android:id="@+id/ci_avatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:iconRound="5dp"
|
||||
app:iconSize="30dp"
|
||||
app:iconRound="4dp"
|
||||
app:iconSize="45dp"
|
||||
app:itemIcon="@drawable/ic_avatar"
|
||||
app:itemName="头像" />
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
<com.kaixed.kchat.ui.widget.CustomItem
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:iconSize="10dp"
|
||||
app:iconSize="21dp"
|
||||
app:isTopDividerVisible="true"
|
||||
app:itemIcon="@drawable/icon_qrcode"
|
||||
app:itemName="二维码名片" />
|
||||
|
47
app/src/main/res/layout/activity_rename.xml
Normal file
47
app/src/main/res/layout/activity_rename.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.RenameActivity">
|
||||
|
||||
<com.kaixed.kchat.ui.widget.CustomTitleBar
|
||||
android:id="@+id/ctb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:btnName="保存" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_nickname"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:background="@null"
|
||||
android:inputType="text"
|
||||
android:maxWidth="200dp"
|
||||
android:maxLines="1"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:textColor="@color/black"
|
||||
android:textCursorDrawable="@drawable/cursor" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.7dp"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:background="@color/green" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="好的名字可以让你的好友更容易记住你。"
|
||||
android:textColor="#A5A5A5"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
@ -14,7 +14,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_margin="15dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardCornerRadius="7dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardMaxElevation="0dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_cancel"
|
||||
@ -64,31 +64,39 @@
|
||||
app:layout_constraintStart_toEndOf="@id/cv_search"
|
||||
app:layout_constraintTop_toTopOf="@id/cv_search" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.2dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:background="@color/gray"
|
||||
app:layout_constraintTop_toBottomOf="@id/cv_search" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cl_search_user"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
android:background="@color/white"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="15dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/cv_search">
|
||||
app:layout_constraintTop_toBottomOf="@id/view">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/ifv"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="#2BA245"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:roundPercent="0.1" />
|
||||
|
||||
|
||||
<ImageView
|
||||
android:layout_width="35dp"
|
||||
android:layout_height="35dp"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/search_add_friends"
|
||||
app:layout_constraintBottom_toBottomOf="@id/ifv"
|
||||
app:layout_constraintEnd_toEndOf="@id/ifv"
|
||||
@ -100,16 +108,28 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="搜索:"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="18sp"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/ifv"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_nothing"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:background="@color/white"
|
||||
android:gravity="center"
|
||||
android:text="该用户不存在"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/view" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
|
@ -1,29 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="25dp"
|
||||
android:paddingVertical="25dp">
|
||||
android:paddingVertical="25dp"
|
||||
app:cardCornerRadius="5dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_fileName="loading.json"
|
||||
app:lottie_loop="true" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#353434"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_loading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:maxWidth="100dp"
|
||||
android:text="正在查找联系人..."
|
||||
android:textColor="@color/black"
|
||||
android:textSize="17sp" />
|
||||
</LinearLayout>
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/lottie"
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="70dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_loading"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_fileName="loading1.json"
|
||||
app:lottie_loop="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_loading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginBottom="@dimen/margin"
|
||||
android:gravity="center_horizontal"
|
||||
android:maxWidth="100dp"
|
||||
android:text="正在查找联系人..."
|
||||
android:textColor="@color/white"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/lottie" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
@ -15,7 +15,6 @@
|
||||
android:id="@+id/cl_profile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="15dp"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
@ -33,10 +32,11 @@
|
||||
android:id="@+id/tv_nickname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:text="糕菜菜"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="15sp"
|
||||
android:textSize="19sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@id/ifv_avatar"
|
||||
app:layout_constraintTop_toTopOf="@id/ifv_avatar" />
|
||||
|
||||
@ -70,6 +70,14 @@
|
||||
app:layout_constraintEnd_toStartOf="@id/cl_profile_right_arrow"
|
||||
app:layout_constraintTop_toTopOf="@id/cl_profile_right_arrow" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_marginTop="15dp"
|
||||
android:background="#D5D5D5"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/ifv_avatar" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
@ -82,18 +90,33 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cl_profile">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="#D5D5D5" />
|
||||
|
||||
|
||||
<com.kaixed.kchat.ui.widget.CustomItem
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:itemLeftIcon="@drawable/ic_mine_pay"
|
||||
app:itemName="服务" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:background="#D5D5D5" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="#D5D5D5" />
|
||||
|
||||
<com.kaixed.kchat.ui.widget.CustomItem
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:itemLeftIcon="@drawable/ic_mine_favorites"
|
||||
app:itemName="收藏" />
|
||||
|
||||
@ -121,14 +144,29 @@
|
||||
app:itemLeftIcon="@drawable/ic_mine_emoji"
|
||||
app:itemName="表情" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:background="#D5D5D5" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="#D5D5D5" />
|
||||
|
||||
|
||||
<com.kaixed.kchat.ui.widget.CustomItem
|
||||
android:id="@+id/ci_setting"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:isTopDividerVisible="false"
|
||||
app:itemLeftIcon="@drawable/ic_mine_setting"
|
||||
app:itemName="设置" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:background="#D5D5D5" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -3,8 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:paddingStart="15dp">
|
||||
android:background="@color/white">
|
||||
|
||||
<View
|
||||
android:id="@+id/view_top"
|
||||
@ -14,6 +13,18 @@
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_nickname"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_letter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_letter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#EDEDED"
|
||||
android:paddingVertical="8dp"
|
||||
android:paddingStart="15dp"
|
||||
android:text="A"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
@ -21,10 +32,11 @@
|
||||
android:layout_width="35dp"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:src="@drawable/ic_avatar"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/view_top"
|
||||
app:roundPercent="0.2" />
|
||||
|
||||
<TextView
|
||||
@ -35,9 +47,9 @@
|
||||
android:text="kaixed"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@id/ifv_avatar"
|
||||
app:layout_constraintStart_toEndOf="@+id/ifv_avatar"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="@id/ifv_avatar" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view_bottom"
|
||||
|
@ -9,7 +9,7 @@
|
||||
<View
|
||||
android:id="@+id/decoration_top"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_height="0.2dp"
|
||||
android:background="#E5E5E5"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_item_name"
|
||||
@ -56,10 +56,10 @@
|
||||
android:id="@+id/tv_item_desc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="aaaa"
|
||||
android:textColor="#797979"
|
||||
android:textSize="17sp"
|
||||
android:textSize="15sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/iv_arrow_right"
|
||||
@ -91,7 +91,7 @@
|
||||
<View
|
||||
android:id="@+id/decoration_bottom"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_height="0.2dp"
|
||||
android:background="#E5E5E5"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -32,9 +32,24 @@
|
||||
android:layout_height="22dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/ic_setting"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginEnd="15dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_save"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:background="@drawable/bac_ctb_save"
|
||||
android:paddingHorizontal="13dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="保存"
|
||||
android:textColor="#BFBFBF"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -26,6 +26,7 @@
|
||||
<declare-styleable name="CustomTitleBar">
|
||||
<attr name="titleName" format="string" />
|
||||
<attr name="titleIcon" format="reference" />
|
||||
<attr name="btnName" format="string" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="ShSwitchView">
|
||||
|
5
app/src/main/res/values/dimens.xml
Normal file
5
app/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="margin">15dp</dimen>
|
||||
<dimen name="divider_height">0.2dp</dimen>
|
||||
</resources>
|
@ -12,9 +12,10 @@ kotlinxSerializationJson = "1.6.3"
|
||||
lottie = "6.5.2"
|
||||
material = "1.12.0"
|
||||
activity = "1.9.3"
|
||||
constraintlayout = "2.1.4"
|
||||
constraintlayout = "2.2.0"
|
||||
mmkv = "1.3.9"
|
||||
okhttp = "4.12.0"
|
||||
pinyin4j = "2.5.1"
|
||||
preference = "1.2.1"
|
||||
shapedrawable = "3.2"
|
||||
shapeview = "9.2"
|
||||
@ -29,6 +30,7 @@ objectbox = "4.0.2"
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesCore" }
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" }
|
||||
pinyin4j = { module = "com.belerweb:pinyin4j", version.ref = "pinyin4j" }
|
||||
shapedrawable = { module = "com.github.getActivity:ShapeDrawable", version.ref = "shapedrawable" }
|
||||
shapeview = { module = "com.github.getActivity:ShapeView", version.ref = "shapeview" }
|
||||
therouter-ksp = { module = "cn.therouter:apt", version.ref = "therouter" }
|
||||
|
Loading…
Reference in New Issue
Block a user