fix: 修改短按录音崩溃的问题

This commit is contained in:
xiaoyan 2023-01-09 13:53:30 +08:00
commit cdc5e8a95f
46 changed files with 750 additions and 368 deletions

View File

@ -2,6 +2,7 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
id 'kotlin-parcelize'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
// id 'com.google.dagger.hilt.android'
@ -61,14 +62,17 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation "androidx.compose.material3:material3:1.0.0-alpha04"
//
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
//
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-common-java8:2.4.1"
//
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
@ -76,7 +80,7 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
//room
//room
implementation 'com.tencent.wcdb:room:1.1-19' // room-runtime wcdb-android
api 'androidx.sqlite:sqlite:2.2.0'
implementation 'androidx.room:room-runtime:2.4.3'
@ -86,6 +90,10 @@ dependencies {
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler room
kapt 'androidx.room:room-compiler:2.4.3'
kapt 'androidx.room:room-ktx:2.4.3'
//
implementation "androidx.room:room-paging:2.4.3"
implementation "androidx.paging:paging-runtime-ktx:3.1.1"
androidTestImplementation "android.arch.persistence.room:testing:1.1.1"
// implementation "android.arch.lifecycle:extensions:1.1.1"
// annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
@ -96,6 +104,8 @@ dependencies {
implementation 'me.rosuh:AndroidFilePicker:0.8.2'
// https://github.com/Gredicer/datetimepicker
implementation 'com.github.Gredicer:datetimepicker:V1.0.0'
//
implementation 'com.yanzhenjie.recyclerview:x:1.3.2'
// implementation 'androidx.appcompat:appcompat:1.5.1'

BIN
app/release/app-release.apk Normal file

Binary file not shown.

View File

@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.navinfo.volvo",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
}

View File

@ -23,7 +23,7 @@
android:configChanges="locale"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:icon="@mipmap/volvo_logo_small"
android:requestLegacyExternalStorage="true"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
@ -34,6 +34,7 @@
android:name=".ui.message.MessageActivity"
android:exported="false"
android:label="@string/title_activity_second"
android:screenOrientation="portrait"
android:theme="@style/Theme.NavinfoVolvo.NoActionBar">
<meta-data
android:name="android.app.lib_name"

View File

@ -5,7 +5,4 @@ import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
open class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
}
}

View File

@ -10,7 +10,7 @@ import java.util.*
class RecorderLifecycleObserver: DefaultLifecycleObserver {
private var mediaRecorder: MediaRecorder? = null
private lateinit var recorderAudioPath: String
private var recorderAudioPath: String = "${SystemConstant.SoundFolder}/${DateUtils.date2Str(Date(), DateUtils.FORMAT_YMDHMS)}.m4a"
fun initAndStartRecorder() {
recorderAudioPath = "${SystemConstant.SoundFolder}/${DateUtils.date2Str(Date(), DateUtils.FORMAT_YMDHMS)}.m4a"
@ -22,17 +22,22 @@ class RecorderLifecycleObserver: DefaultLifecycleObserver {
setOutputFile(recorderAudioPath)
try {
prepare()
start()
} catch (e: Exception) {
XLog.e("prepare() failed")
}
start()
}
}
fun stopAndReleaseRecorder(): String {
mediaRecorder?.stop()
mediaRecorder?.release()
mediaRecorder = null
try {
mediaRecorder?.stop()
} catch (exception: Exception) {
XLog.e(exception.message)
} finally {
mediaRecorder?.release()
mediaRecorder = null
}
return recorderAudioPath
}

View File

@ -1,19 +1,44 @@
package com.navinfo.volvo.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.paging.PagingSource
import androidx.room.*
import com.navinfo.volvo.database.entity.GreetingMessage
import kotlinx.coroutines.flow.Flow
@Dao
interface GreetingMessageDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg check: GreetingMessage)
@Query("SELECT * FROM GreetingMessage where id =:id")
fun findCheckManagerById(id: Long): GreetingMessage?
@Insert
fun insert(message: GreetingMessage): Long
@Query("SELECT * FROM GreetingMessage")
fun findList(): List<GreetingMessage>
@Update(onConflict = OnConflictStrategy.REPLACE)
fun update(message: GreetingMessage)
@Query("SELECT count(id) FROM GreetingMessage WHERE read = 0")
fun countUnreadByFlow(): Flow<Long>
/**
* 分页查询
*/
@Query("SELECT * FROM GreetingMessage order by sendDate DESC")
fun findAllByDataSource(): PagingSource<Int, GreetingMessage>
/**
* 检查某条数据是否存在
*/
@Query("SELECT id From GreetingMessage WHERE id = :id LIMIT 1")
fun getMessageId(id: Long): Long
@Transaction
suspend fun insertOrUpdate(list: List<GreetingMessage>) {
for (message in list) {
val id = getMessageId(message.id)
if (id == 0L) {
insert(message)
}else{
update(message)
}
}
}
}

View File

@ -1,15 +1,15 @@
package com.navinfo.volvo.database.entity
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import org.jetbrains.annotations.NotNull
@Entity(tableName = "GreetingMessage")
@TypeConverters(AttachmentConverters::class)
data class GreetingMessage @JvmOverloads constructor(
@PrimaryKey(autoGenerate = true)
var uuid:Long = 0,
var uuid: Long = 0,
var id: Long = 0,
var searchValue: String? = "",
var createBy: String? = "",
@ -35,10 +35,10 @@ data class GreetingMessage @JvmOverloads constructor(
var sendVins: String? = "",
var sendType: String? = "",
var del: String? = "",
var version: String? = "",
var version: String? = "1",
// /**
// * 附件列表
// */
// var attachment: MutableList<Attachment> = mutableListOf()
) {
}
// var attachment: MutableList<Attachment> = mutableListOf(),
var read: Boolean = false,
)

View File

@ -5,6 +5,7 @@ import androidx.room.Room
import com.navinfo.volvo.database.AppDatabase
import com.navinfo.volvo.database.dao.GreetingMessageDao
import com.navinfo.volvo.database.dao.UserDao
import com.navinfo.volvo.utils.SystemConstant
import com.tencent.wcdb.database.SQLiteCipherSpec
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory
import dagger.Module
@ -31,7 +32,7 @@ class DatabaseModule {
.writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
.asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
return Room.databaseBuilder(context, AppDatabase::class.java, "NavinfoVolvoDb")
return Room.databaseBuilder(context, AppDatabase::class.java, "${SystemConstant.ROOT_PATH}/NavinfoVolvoDb.db")
// [WCDB] Specify open helper to use WCDB database implementation instead
// of the Android framework.

View File

@ -0,0 +1,15 @@
package com.navinfo.volvo.di.module
import com.navinfo.volvo.repository.database.DatabaseRepository
import com.navinfo.volvo.repository.database.DatabaseRepositoryImp
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@InstallIn(SingletonComponent::class)
@Module
abstract class DatabaseRepositoryModule {
@Binds
abstract fun bingDatabaseRepository(databaseRepositoryImp: DatabaseRepositoryImp): DatabaseRepository
}

View File

@ -1,15 +0,0 @@
package com.navinfo.volvo.di.module
import com.navinfo.volvo.repository.NetworkDataSource
import com.navinfo.volvo.repository.NetworkDataSourceImp
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@InstallIn(SingletonComponent::class)
@Module
abstract class NetworkDataModule {
@Binds
abstract fun bindNetworkData(networkDataSourceImp: NetworkDataSourceImp): NetworkDataSource
}

View File

@ -0,0 +1,15 @@
package com.navinfo.volvo.di.module
import com.navinfo.volvo.repository.network.NetworkRepository
import com.navinfo.volvo.repository.network.NetworkRepositoryImp
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@InstallIn(SingletonComponent::class)
@Module
abstract class NetworkRepositoryModule {
@Binds
abstract fun bindNetworkRepository(networkRepositoryImp: NetworkRepositoryImp): NetworkRepository
}

View File

@ -4,7 +4,7 @@ import android.app.Application
import android.content.Context
import com.google.gson.Gson
import com.navinfo.volvo.Constant
import com.navinfo.volvo.repository.service.NetworkService
import com.navinfo.volvo.repository.network.NetworkService
import com.navinfo.volvo.tools.GsonUtil
import dagger.Lazy
import dagger.Module
@ -15,7 +15,6 @@ import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@ -101,4 +100,5 @@ class NetworkUtilModule {
fun provideNetworkService(retrofit: Retrofit): NetworkService {
return retrofit.create(NetworkService::class.java)
}
}

View File

@ -3,8 +3,10 @@ package com.navinfo.volvo.di.module
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.navinfo.volvo.di.key.ViewModelKey
import com.navinfo.volvo.ui.fragments.home.MessageViewModel
import com.navinfo.volvo.ui.MainActivityViewModel
import com.navinfo.volvo.ui.fragments.home.HomeViewModel
import com.navinfo.volvo.ui.fragments.login.LoginViewModel
import com.navinfo.volvo.ui.fragments.message.ObtainMessageViewModel
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
@ -18,6 +20,11 @@ abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory
@IntoMap
@Binds
@ViewModelKey(MainActivityViewModel::class)
abstract fun bindMainViewModel(viewModel: MainActivityViewModel): ViewModel
@IntoMap
@Binds
@ViewModelKey(LoginViewModel::class)
@ -25,6 +32,13 @@ abstract class ViewModelModule {
@IntoMap
@Binds
@ViewModelKey(MessageViewModel::class)
abstract fun bindMessageFragmentViewModel(viewModel: MessageViewModel): ViewModel
@ViewModelKey(HomeViewModel::class)
abstract fun bindMessageFragmentViewModel(viewModel: HomeViewModel): ViewModel
@IntoMap
@Binds
@ViewModelKey(ObtainMessageViewModel::class)
abstract fun bindObtainMessageFragmentViewModel(viewModel: ObtainMessageViewModel): ViewModel
}

View File

@ -0,0 +1,9 @@
package com.navinfo.volvo.model
/**
* 登录用户信息
*/
data class LoginUser(
var name: String,
var password: String
)

View File

@ -0,0 +1,3 @@
package com.navinfo.volvo.model
data class VolvoModel(val version: String, val model: String, val num:String)

View File

@ -0,0 +1,12 @@
package com.navinfo.volvo.repository.database
import androidx.paging.PagingData
import com.navinfo.volvo.database.entity.GreetingMessage
import kotlinx.coroutines.flow.Flow
/**
* 数据库操作接口
*/
interface DatabaseRepository {
fun getMessageByPaging(): Flow<PagingData<GreetingMessage>>
}

View File

@ -0,0 +1,26 @@
package com.navinfo.volvo.repository.database
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.navinfo.volvo.database.AppDatabase
import com.navinfo.volvo.database.dao.GreetingMessageDao
import com.navinfo.volvo.database.entity.GreetingMessage
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class DatabaseRepositoryImp @Inject constructor(
private val messageDao: GreetingMessageDao,
private val database: AppDatabase
) : DatabaseRepository {
companion object {
const val PAGE_SIZE = 20
}
override fun getMessageByPaging(): Flow<PagingData<GreetingMessage>> {
return Pager(PagingConfig(PAGE_SIZE)) {
messageDao.findAllByDataSource()
}.flow
}
}

View File

@ -1,10 +1,13 @@
package com.navinfo.volvo.repository
package com.navinfo.volvo.repository.network
import com.navinfo.volvo.http.DefaultResponse
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
import com.navinfo.volvo.util.NetResult
interface NetworkDataSource {
/**
* 网络访问接口
*/
interface NetworkRepository {
suspend fun getCardList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>>
}

View File

@ -1,13 +1,10 @@
package com.navinfo.volvo.repository
package com.navinfo.volvo.repository.network
import com.navinfo.volvo.database.AppDatabase
import com.navinfo.volvo.database.dao.GreetingMessageDao
import com.navinfo.volvo.di.scope.IoDispatcher
import com.navinfo.volvo.database.entity.GreetingMessage
import com.navinfo.volvo.http.DefaultResponse
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
import com.navinfo.volvo.repository.service.NetworkService
import com.navinfo.volvo.tools.GsonUtil
import com.navinfo.volvo.util.NetResult
import kotlinx.coroutines.CoroutineDispatcher
@ -17,11 +14,11 @@ import okhttp3.RequestBody.Companion.toRequestBody
import javax.inject.Inject
class NetworkDataSourceImp @Inject constructor(
class NetworkRepositoryImp @Inject constructor(
private val netWorkService: NetworkService,
private val messageDao: GreetingMessageDao,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
) : NetworkDataSource {
) : NetworkRepository {
override suspend fun getCardList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>> =
withContext(ioDispatcher) {
@ -31,9 +28,9 @@ class NetworkDataSourceImp @Inject constructor(
val result = netWorkService.queryCardListByApp(stringBody)
if (result.isSuccessful) {
val body = result.body()
val list: MutableList<GreetingMessage> =
listOf(body!!.data!!.rows) as MutableList<GreetingMessage>
messageDao.insert(*list.map { it }.toTypedArray())
if(body!!.data != null && body.data!!.rows != null){
messageDao.insertOrUpdate(body.data!!.rows)
}
NetResult.Success(body)
} else {
NetResult.Success(null)

View File

@ -1,4 +1,4 @@
package com.navinfo.volvo.repository.service
package com.navinfo.volvo.repository.network
import com.navinfo.volvo.http.DefaultResponse
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse

View File

@ -0,0 +1,11 @@
package com.navinfo.volvo.ui
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import javax.inject.Inject
abstract class BaseActivity : AppCompatActivity() {
@Inject
lateinit var viewModelFactoryProvider: ViewModelProvider.Factory
}

View File

@ -1,10 +1,12 @@
package com.navinfo.volvo.ui
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.activity.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
@ -28,20 +30,23 @@ import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.navinfo.volvo.R
import com.navinfo.volvo.databinding.ActivityMainBinding
import com.navinfo.volvo.ui.message.MessageActivity
import com.navinfo.volvo.utils.SystemConstant
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
class MainActivity : BaseActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel by viewModels<MainActivityViewModel> { viewModelFactoryProvider }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setupNavigation()
XXPermissions.with(this)
// 申请单个权限
@ -61,6 +66,7 @@ class MainActivity : AppCompatActivity() {
}
// 在SD卡创建项目目录
createRootFolder()
setupNavigation()
}
override fun onDenied(permissions: MutableList<String>, never: Boolean) {
@ -84,16 +90,29 @@ class MainActivity : AppCompatActivity() {
val navController = findNavController(R.id.nav_host_fragment_activity_main)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_message, R.id.navigation_dashboard, R.id.navigation_notifications,
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications,
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
lifecycleScope.launch {
viewModel.getUnreadCount().collect {
runOnUiThread {
if (it == 0L) {
navView.removeBadge(R.id.navigation_home)
} else {
var badge = navView.getOrCreateBadge(R.id.navigation_home);
badge.number = it.toInt()
}
}
}
}
navController.addOnDestinationChangedListener { controller, destination, arguments ->
if (destination.id == R.id.navigation_message
if (destination.id == R.id.navigation_home
|| destination.id == R.id.navigation_dashboard
|| destination.id == R.id.navigation_notifications
|| destination.id == R.id.navigation_obtain_message
) {
runOnUiThread {
navView.visibility = View.VISIBLE
@ -106,6 +125,11 @@ class MainActivity : AppCompatActivity() {
}
}
}
binding.newMessageFab.setOnClickListener {
// val intent: Intent = Intent(this@MainActivity, MessageActivity::class.java)
// startActivity(intent)
navController.navigate(R.id.navigation_obtain_message)
}
}
override fun onSupportNavigateUp() =

View File

@ -0,0 +1,17 @@
package com.navinfo.volvo.ui
import androidx.lifecycle.ViewModel
import androidx.paging.PagingData
import com.navinfo.volvo.database.dao.GreetingMessageDao
import com.navinfo.volvo.database.entity.GreetingMessage
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class MainActivityViewModel @Inject constructor(
private val messageDao: GreetingMessageDao,
) : ViewModel() {
fun getUnreadCount(): Flow<Long> = messageDao.countUnreadByFlow()
}

View File

@ -1,54 +0,0 @@
package com.navinfo.volvo.ui.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.navinfo.volvo.R
import com.navinfo.volvo.database.entity.GreetingMessage
class MessageAdapter : RecyclerView.Adapter<MessageAdapter.MyViewHolder>() {
var itemList: MutableList<GreetingMessage> = mutableListOf()
fun addItem(message: GreetingMessage) {
itemList.add(message)
notifyItemInserted(itemList.size - 1)
}
fun setItem(messageList: MutableList<GreetingMessage>){
itemList = messageList
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.adapter_message, parent, false)
var viewHolder = MyViewHolder(view)
viewHolder.itemView.setOnClickListener {
}
return viewHolder
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val message = itemList[position]
holder.toName.text = message.toWho
holder.messageText.text = message.name
holder.sendTime.text = message.sendDate
}
override fun getItemCount(): Int {
return itemList.size
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var image: ImageView = itemView.findViewById(R.id.message_head_icon)
var toName: TextView = itemView.findViewById(R.id.message_to_username)
var sendTime: TextView = itemView.findViewById(R.id.message_send_time)
var status: TextView = itemView.findViewById(R.id.message_status)
var messageText: TextView = itemView.findViewById(R.id.message_text)
}
}

View File

@ -1,4 +1,4 @@
package com.navinfo.volvo.ui
package com.navinfo.volvo.ui.fragments
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider

View File

@ -0,0 +1,81 @@
package com.navinfo.volvo.ui.fragments.home
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.navinfo.volvo.R
import com.navinfo.volvo.database.entity.GreetingMessage
import com.navinfo.volvo.databinding.AdapterHomeBinding
class HomeAdapter(fragment: Fragment) :
PagingDataAdapter<GreetingMessage, HomeAdapter.MyViewHolder>(DiffCallback()) {
val fragment = fragment
// var itemList = ArrayList<GreetingMessage>()
//
// fun addItem(message: GreetingMessage) {
// itemList.add(message)
// notifyItemInserted(itemList.size - 1)
// }
//
// fun setItems(messageList: List<GreetingMessage>) {
// itemList.clear()
// itemList.addAll(messageList)
// notifyDataSetChanged()
// }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val mDataBinding: AdapterHomeBinding =
DataBindingUtil.inflate(
LayoutInflater.from(fragment.context),
R.layout.adapter_home,
parent,
false
)
return MyViewHolder(mDataBinding)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.onBind(position)
}
// override fun getItemCount(): Int {
// return itemList.size
// }
inner class MyViewHolder(private val mDataBinding: AdapterHomeBinding) :
RecyclerView.ViewHolder(mDataBinding.root) {
fun onBind(position: Int) {
var row = getItem(position)
mDataBinding.greetingMessage = row
Glide.with(fragment)
.asBitmap().fitCenter()
.load(row!!.imageUrl)
.placeholder(R.mipmap.volvo_logo_small)
.error(R.mipmap.volvo_logo_small)
.into(mDataBinding.messageHeadIcon)
}
}
class DiffCallback : DiffUtil.ItemCallback<GreetingMessage>() {
override fun areItemsTheSame(oldItem: GreetingMessage, newItem: GreetingMessage): Boolean {
return oldItem.uuid == newItem.uuid
}
override fun areContentsTheSame(
oldItem: GreetingMessage,
newItem: GreetingMessage
): Boolean {
return oldItem == newItem
}
}
}

View File

@ -4,50 +4,47 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.navinfo.volvo.R
import com.navinfo.volvo.databinding.FragmentHomeBinding
import com.navinfo.volvo.tools.DisplayUtil
import com.navinfo.volvo.ui.BaseFragment
import com.navinfo.volvo.ui.adapter.MessageAdapter
import com.navinfo.volvo.ui.fragments.message.ObtainMessageViewModel
import com.navinfo.volvo.ui.fragments.BaseFragment
import com.yanzhenjie.recyclerview.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
@AndroidEntryPoint
class MessageFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListener {
class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListener {
private var _binding: FragmentHomeBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private val viewModel by viewModels<MessageViewModel> { viewModelFactoryProvider }
private val viewModel by viewModels<HomeViewModel> { viewModelFactoryProvider }
private lateinit var messageAdapter: HomeAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// val homeViewModel =
// ViewModelProvider(this)[MessageViewModel::class.java]
// val obtainMessageViewModel =
// ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
initView()
return root
}
private fun initView() {
val recyclerview: SwipeRecyclerView = binding.homeMessageRecyclerview
// mDataBinding.homeViewModel = viewModel
messageAdapter = HomeAdapter(this)
val recyclerview: SwipeRecyclerView = binding.homeRecyclerview
recyclerview.adapter = null //先设置null否则会报错
//创建菜单选项
//注意:使用滑动菜单不能开启滑动删除,否则只有滑动删除没有滑动菜单
@ -71,28 +68,32 @@ class MessageFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickList
rightMenu.addMenuItem(shareItem)
}
val layoutManager = LinearLayoutManager(context)
val adapter = MessageAdapter()
recyclerview.layoutManager = layoutManager
recyclerview.addItemDecoration(DividerItemDecoration(context, layoutManager.orientation))
recyclerview.setSwipeMenuCreator(mSwipeMenuCreator)
recyclerview.setOnItemClickListener(this)
recyclerview.useDefaultLoadMore()
recyclerview.setLoadMoreListener {
// recyclerview.useDefaultLoadMore()
// recyclerview.setLoadMoreListener {
//
// }
lifecycleScope.launch {
viewModel.messageList.collectLatest {
messageAdapter.submitData(it)
}
}
recyclerview.adapter = adapter
// homeViewModel.getMessageList().observe(viewLifecycleOwner, Observer { contacts ->
// adapter.setItem(contacts)
// })
// messageAdapter.withLoadStateFooter(
// footer = RecLoadStateAdapter { messageAdapter.retry() }
// )
// messageAdapter.withLoadStateHeader()
recyclerview.adapter = messageAdapter
}
override fun onStart() {
super.onStart()
getMessageList()
}
private fun getMessageList() {
viewModel.getMessageList()
viewModel.getNetMessageList()
}

View File

@ -0,0 +1,57 @@
package com.navinfo.volvo.ui.fragments.home
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.navinfo.volvo.database.dao.GreetingMessageDao
import com.navinfo.volvo.database.entity.GreetingMessage
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
import com.navinfo.volvo.repository.database.DatabaseRepository
import com.navinfo.volvo.repository.network.NetworkRepository
import com.navinfo.volvo.util.NetResult
import com.navinfo.volvo.util.asLiveData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import javax.inject.Inject
class HomeViewModel @Inject constructor(
private val netRepository: NetworkRepository,
private val dataRepository: DatabaseRepository
) : ViewModel() {
private val _isLoading = MutableLiveData<Boolean>()
val isLoading = _isLoading.asLiveData()
// private val _messageList = MutableLiveData<List<GreetingMessage>>()
// val messageList = _messageList.asLiveData()
val messageList: Flow<PagingData<GreetingMessage>>
get() = dataRepository.getMessageByPaging()
fun getNetMessageList() {
_isLoading.postValue(true)
viewModelScope.launch {
val messagePost = NetworkMessageListPost(who = "", toWho = "")
when (val result = netRepository.getCardList(messagePost)) {
is NetResult.Success -> {
_isLoading.value = false
// if (result.data != null) {
// val list = (result.data.data as NetworkMessageListResponse).rows
// _messageList.value = list
// }
}
is NetResult.Error -> {
_isLoading.value = false
}
is NetResult.Loading -> {
_isLoading.postValue(true)
}
}
}
}
}

View File

@ -1,48 +0,0 @@
package com.navinfo.volvo.ui.fragments.home
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.volvo.database.entity.GreetingMessage
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
import com.navinfo.volvo.repository.NetworkDataSource
import com.navinfo.volvo.util.NetResult
import com.navinfo.volvo.util.asLiveData
import kotlinx.coroutines.launch
import javax.inject.Inject
class MessageViewModel @Inject constructor(
private val repository: NetworkDataSource
) : ViewModel() {
private val _isLoading = MutableLiveData<Boolean>()
val isLoading = _isLoading.asLiveData()
private val _messageList = MutableLiveData<List<GreetingMessage>>()
val messageList = _messageList.asLiveData()
fun getMessageList() {
_isLoading.postValue(true)
viewModelScope.launch {
val messagePost = NetworkMessageListPost(who = "北京测试", toWho = "volvo测试")
when (val result = repository.getCardList(messagePost)) {
is NetResult.Success -> {
_isLoading.value = false
if (result.data != null) {
val list = (result.data.data as NetworkMessageListResponse).rows
_messageList.value = list
}
}
is NetResult.Error -> {
_isLoading.value = false
}
is NetResult.Loading -> {
_isLoading.postValue(true)
}
}
}
}
}

View File

@ -0,0 +1,51 @@
//package com.navinfo.volvo.ui.fragments.home
//
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import androidx.core.view.isVisible
//import androidx.paging.LoadState
//import androidx.paging.LoadStateAdapter
//import androidx.recyclerview.widget.RecyclerView
//import com.example.picsapp.R
//import com.example.picsapp.databinding.LoadStateViewBinding
//
//class RecLoadStateAdapter(
// private val retry: () -> Unit
//) : LoadStateAdapter<RecLoadStateAdapter.LoadStateViewHolder>() {
//
// override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): LoadStateViewHolder {
//
// val binding = LoadStateViewBinding
// .inflate(LayoutInflater.from(parent.context), parent, false)
//
// return LoadStateViewHolder(binding)
// }
//
// override fun onBindViewHolder(holder: LoadStateViewHolder, loadState: LoadState) {
// holder.onBind(loadState)
//
// }
//
//
//
// inner class LoadStateViewHolder(private val binding: LoadStateViewBinding) : RecyclerView.ViewHolder(binding.root){
// fun onBind(loadState: LoadState) {
// val progress = binding.loadStateProgress
// val btnRetry = binding.loadStateRetry
// val txtErrorMessage = binding.loadStateErrorMessage
//
// btnRetry.isVisible = loadState !is LoadState.Loading
// txtErrorMessage.isVisible = loadState !is LoadState.Loading
// progress.isVisible = loadState is LoadState.Loading
//
// if (loadState is LoadState.Error){
// txtErrorMessage.text = loadState.error.localizedMessage
// }
//
// btnRetry.setOnClickListener {
// retry.invoke()
// }
// }
// }
//}

View File

@ -4,14 +4,12 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.viewModels
import androidx.navigation.Navigation
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.navinfo.volvo.R
import com.navinfo.volvo.databinding.FragmentLoginBinding
import com.navinfo.volvo.ui.BaseFragment
import com.navinfo.volvo.ui.fragments.BaseFragment
import dagger.hilt.android.AndroidEntryPoint
@ -19,11 +17,8 @@ import dagger.hilt.android.AndroidEntryPoint
class LoginFragment : BaseFragment() {
// private var loginViewModel:LoginViewModel by viewModel(get())
private var viewBinding: FragmentLoginBinding? = null
private lateinit var viewBinding: FragmentLoginBinding
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = viewBinding!!
private val viewModel by viewModels<LoginViewModel> { viewModelFactoryProvider }
@ -32,20 +27,21 @@ class LoginFragment : BaseFragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false)
viewBinding.lifecycleOwner = this
initView()
return viewBinding.root
}
private fun initView() {
viewBinding.loginFragmentRegisterButton.setOnClickListener {
viewBinding = FragmentLoginBinding.inflate(inflater, container, false)
val root: View = binding.root
binding.loginFragmentRegisterButton.setOnClickListener {
}
binding.loginFragmentLoginButton.setOnClickListener {
viewBinding.loginFragmentLoginButton.setOnClickListener {
// viewModel.login(viewBinding.loginFragmentUserLayout)
findNavController().navigate(R.id.action_login_to_home)
}
return root
}
override fun onDestroyView() {
viewBinding = null
super.onDestroyView()
}
}

View File

@ -6,14 +6,12 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.navinfo.volvo.database.AppDatabase
import com.navinfo.volvo.database.entity.User
import com.navinfo.volvo.util.SharedPreferenceHelper
import javax.inject.Inject
class LoginViewModel @Inject constructor(private val dataBase: AppDatabase) : ViewModel() {
class LoginViewModel @Inject constructor(private val sharedPreferenceHelper: SharedPreferenceHelper) : ViewModel() {
private val _user = MutableLiveData<User>().apply {
}
val user: LiveData<User> = _user
// val user: LiveData<User> = _user
fun liveDataOnclick(view: View) {

View File

@ -2,7 +2,6 @@ package com.navinfo.volvo.ui.fragments.message
import android.content.DialogInterface
import android.graphics.Paint
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
@ -17,18 +16,13 @@ import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.Navigation
import androidx.navigation.fragment.findNavController
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.easytools.tools.DateUtils
import com.easytools.tools.DeviceUtils
import com.easytools.tools.DisplayUtils
import com.easytools.tools.FileIOUtils
import com.easytools.tools.FileUtils
import com.easytools.tools.ResourceUtils
import com.easytools.tools.ToastUtils
import com.elvishew.xlog.XLog
@ -51,6 +45,7 @@ import com.navinfo.volvo.database.entity.AttachmentType
import com.navinfo.volvo.database.entity.GreetingMessage
import com.navinfo.volvo.databinding.FragmentObtainMessageBinding
import com.navinfo.volvo.http.DownloadCallback
import com.navinfo.volvo.model.VolvoModel
import com.navinfo.volvo.ui.markRequiredInRed
import com.navinfo.volvo.util.PhotoLoader
import com.navinfo.volvo.utils.EasyMediaFile
@ -62,8 +57,8 @@ import top.zibin.luban.Luban
import top.zibin.luban.OnCompressListener
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.*
import kotlin.streams.toList
//@RuntimePermissions
@ -81,6 +76,7 @@ class ObtainMessageFragment: Fragment() {
private val dateSendFormat = "yyyy-MM-dd HH:mm:ss"
private val dateShowFormat = "yyyy-MM-dd HH:mm"
private var startRecordTime = System.currentTimeMillis()
// This property is only valid between onCreateView and
// onDestroyView.
@ -186,13 +182,12 @@ class ObtainMessageFragment: Fragment() {
binding.imgAudioDelete.setOnClickListener {
obtainMessageViewModel.updateMessageAudio("")
}
val sendToArray = mutableListOf<String>("绑定车辆1(LYVXFEFEXNL754427)")
val sendToArray = mutableListOf<VolvoModel>(VolvoModel("XC60", "智雅", "LYVXFEFEXNL754427"))
binding.edtSendTo.adapter = ArrayAdapter<String>(requireContext(),
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray)
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray.stream().map { it -> "${it.version} ${it.model} ${it.num}" }.toList())
binding.edtSendTo.onItemSelectedListener = object: OnItemSelectedListener {
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2]
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2].num
}
override fun onNothingSelected(p0: AdapterView<*>?) {
@ -326,10 +321,15 @@ class ObtainMessageFragment: Fragment() {
MotionEvent.ACTION_DOWN-> {
// 申请权限
recorderLifecycleObserver.initAndStartRecorder()
ToastUtils.showToast("开始录音!")
startRecordTime = System.currentTimeMillis()
false
}
MotionEvent.ACTION_UP -> {
if (System.currentTimeMillis() - startRecordTime<2000) {
ToastUtils.showToast("录音时间太短!")
recorderLifecycleObserver.stopAndReleaseRecorder()
return
}
val recorderAudioPath = recorderLifecycleObserver.stopAndReleaseRecorder()
if (File(recorderAudioPath).exists()) {
obtainMessageViewModel.updateMessageAudio(recorderAudioPath)
@ -556,9 +556,12 @@ class ObtainMessageFragment: Fragment() {
val cal = Calendar.getInstance()
cal.time = Date()
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE)+1)
if (cal.time.time < sendDate.time) { // 发送时间设置小于当前时间1分钟前Toast提示用户并自动设置发送时间
if (sendDate.time < cal.time.time) { // 发送时间设置小于当前时间1分钟后Toast提示用户并自动设置发送时间
messageData?.sendDate = DateUtils.date2Str(cal.time, dateSendFormat)
ToastUtils.showToast("自动调整发送时间为1分钟后发送")
messageData.version = "1" // 立即发送
} else {
messageData.version = "0" // 预约发送
}
// 开始网络提交数据
@ -588,6 +591,7 @@ class ObtainMessageFragment: Fragment() {
val confirmCallback = object: ObtainMessageViewModel.MyConfirmCallback {
override fun onSucess() {
findNavController().navigate(R.id.navigation_home)
}
}

View File

@ -23,9 +23,10 @@ import okhttp3.RequestBody
import java.io.File
import java.io.FileInputStream
import java.util.*
import javax.inject.Inject
class ObtainMessageViewModel: ViewModel() {
class ObtainMessageViewModel @Inject constructor(): ViewModel() {
private val msgLiveData: MutableLiveData<GreetingMessage> by lazy {
MutableLiveData<GreetingMessage>()
}
@ -232,7 +233,8 @@ class ObtainMessageViewModel: ViewModel() {
"mediaUrl" to message?.mediaUrl,
"who" to message?.who,
"toWho" to message?.toWho,
"sendDate" to message?.sendDate
"sendDate" to message?.sendDate,
"version" to message?.version
)
val result = NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>)
XLog.d("insertCardByApp:${result.code}")
@ -264,7 +266,8 @@ class ObtainMessageViewModel: ViewModel() {
"mediaUrl" to message?.mediaUrl,
"who" to message?.who,
"toWho" to message?.toWho,
"sendDate" to message?.sendDate
"sendDate" to message?.sendDate,
"version" to message?.version
)
val result = NavinfoVolvoCall.getApi().updateCardByApp(updateData as Map<String, String>)
XLog.d("updateCardByApp:${result.code}")

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
android:useLevel="false">
<solid android:color="#FF0000"/>
<size android:width="12dp"
android:height="12dp"/>
</shape>

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="greetingMessage"
type="com.navinfo.volvo.database.entity.GreetingMessage" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/message_head_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginLeft="8dp"
android:src="@mipmap/volvo_logo_small"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/message_badge"
android:layout_width="12dp"
android:layout_height="12dp"
android:background="@drawable/shape_circular"
android:gravity="center"
android:textColor="#000000"
app:layout_constraintCircle="@id/message_head_icon"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="40dp"
tools:ignore="MissingConstraints" />
<TextView
android:id="@+id/message_to_who"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:ellipsize="end"
android:maxLines="1"
android:text="@{greetingMessage.toWho,default=发送对象的名字很长还很长的}"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintLeft_toRightOf="@id/message_head_icon"
app:layout_constraintRight_toLeftOf="@id/message_send_time"
app:layout_constraintTop_toTopOf="@id/message_head_icon" />
<TextView
android:id="@+id/message_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:ellipsize="end"
android:maxLines="1"
android:text="@{greetingMessage.name,default=消息内容我的消息也很长0121231313123131313}"
app:layout_constraintBottom_toBottomOf="@id/message_head_icon"
app:layout_constraintLeft_toRightOf="@id/message_head_icon"
app:layout_constraintRight_toLeftOf="@id/message_status" />
<TextView
android:id="@+id/message_send_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:text="@{greetingMessage.sendDate,default=l023x01x03x14x34x34}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/message_head_icon" />
<TextView
android:id="@+id/message_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="@{greetingMessage.status,default=消息状态很长的文字}"
app:layout_constraintBottom_toBottomOf="@id/message_head_icon"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -1,54 +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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/message_head_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:src="@mipmap/volvo_logo_small"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/message_to_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="问候对象"
android:ellipsize="end"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintLeft_toRightOf="@id/message_head_icon"
app:layout_constraintTop_toTopOf="@id/message_head_icon" />
<TextView
android:id="@+id/message_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="信息内容"
app:layout_constraintBottom_toBottomOf="@id/message_head_icon"
app:layout_constraintLeft_toRightOf="@id/message_head_icon" />
<TextView
android:id="@+id/message_send_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:text="日期"
app:layout_constraintTop_toTopOf="@id/message_head_icon"
app:layout_constraintEnd_toEndOf="parent"
/>
<TextView
android:id="@+id/message_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="状态"
app:layout_constraintBottom_toBottomOf="@id/message_head_icon"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,10 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<com.yanzhenjie.recyclerview.SwipeRecyclerView
android:id="@+id/home_message_recyclerview"
xmlns:android="http://schemas.android.com/apk/res/android"
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragments.home.MessageFragment">
</com.yanzhenjie.recyclerview.SwipeRecyclerView>
tools:context=".ui.fragments.home.HomeFragment">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/home_search"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="5dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入查询内容" />
</com.google.android.material.textfield.TextInputLayout>
<com.yanzhenjie.recyclerview.SwipeRecyclerView
android:id="@+id/home_recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/home_search" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,78 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.navinfo.volvo.ui.fragments.login.LoginFragment">
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="loginUser"
type="com.navinfo.volvo.model.LoginUser" />
</data>
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/login_fragment_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.2"
app:roundPercent="0.2" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/login_fragment_user_layout"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:scrollbarAlwaysDrawHorizontalTrack="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.4">
android:layout_height="match_parent"
tools:context="com.navinfo.volvo.ui.fragments.login.LoginFragment">
<com.google.android.material.textfield.TextInputEditText
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/login_fragment_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/volvo_logo_small"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.2"
app:roundPercent="0.2" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/login_fragment_user_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="用户名" />
</com.google.android.material.textfield.TextInputLayout>
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:scrollbarAlwaysDrawHorizontalTrack="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.4">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
app:layout_constraintTop_toBottomOf="@id/login_fragment_user_layout">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{loginUser.name}"
android:hint="请输入用户名" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码" />
</com.google.android.material.textfield.TextInputLayout>
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
app:layout_constraintTop_toBottomOf="@id/login_fragment_user_layout">
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/login_fragment_register_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="注册"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/login_fragment_login_button"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.7" />
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:text="@{loginUser.password}"
android:hint="请输入密码" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/login_fragment_login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="登录"
app:layout_constraintBaseline_toBaselineOf="@id/login_fragment_register_button"
app:layout_constraintLeft_toRightOf="@id/login_fragment_register_button"
app:layout_constraintRight_toRightOf="parent" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/login_fragment_register_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="注册"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/login_fragment_login_button"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.7" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/login_fragment_login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="登录"
app:layout_constraintBaseline_toBaselineOf="@id/login_fragment_register_button"
app:layout_constraintLeft_toRightOf="@id/login_fragment_register_button"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -365,7 +365,7 @@
android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.ElevatedButton"
app:icon="@drawable/ic_baseline_access_time_24"
android:text="现在"
android:text="选择时间"
android:padding="@dimen/default_widget_padding"></com.google.android.material.button.MaterialButton>
</LinearLayout>
<com.nhaarman.supertooltips.ToolTipRelativeLayout

View File

@ -2,7 +2,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_message"
android:id="@+id/navigation_home"
android:icon="@drawable/ic_home_black_24dp"
android:title="@string/title_home" />
<item
@ -25,6 +25,6 @@
<item
android:id="@+id/navigation_obtain_message"
android:icon="@drawable/ic_baseline_mail_24"
android:title="消息" />
android:title="我的" />
</menu>

View File

@ -12,7 +12,7 @@
tools:layout="@layout/fragment_login">
<action
android:id="@+id/action_login_to_home"
app:destination="@id/navigation_message"
app:destination="@id/navigation_home"
app:enterAnim="@anim/from_left"
app:exitAnim="@anim/to_right"
app:popEnterAnim="@anim/from_right"
@ -21,8 +21,8 @@
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/navigation_message"
android:name="com.navinfo.volvo.ui.fragments.home.MessageFragment"
android:id="@+id/navigation_home"
android:name="com.navinfo.volvo.ui.fragments.home.HomeFragment"
android:label="@string/title_home"
tools:layout="@layout/fragment_home"></fragment>
@ -48,5 +48,16 @@
android:id="@+id/navigation_obtain_message"
android:name="com.navinfo.volvo.ui.fragments.message.ObtainMessageFragment"
android:label="问候编辑"
tools:layout="@layout/fragment_obtain_message" />
tools:layout="@layout/fragment_obtain_message" >
<action
android:id="@+id/action_login_to_home"
app:destination="@id/navigation_home"
app:enterAnim="@anim/from_left"
app:exitAnim="@anim/to_right"
app:popEnterAnim="@anim/from_right"
app:popExitAnim="@anim/to_left"
app:popUpTo="@id/navigation_obtain_message"
app:popUpToInclusive="true" />
</fragment>
</navigation>

View File

@ -1,9 +1,18 @@
<resources>
<string name="app_name">NavinfoVolvo</string>
<string name="title_home">Home</string>
<string name="app_name">VolvoMessage</string>
<string name="title_home">问候</string>
<string name="title_dashboard">Dashboard</string>
<string name="title_notifications">Notifications</string>
<string name="delete">删除</string>
<string name="share">分享</string>
<string name="my">我的</string>
<string name="title_activity_second">SecondActivity</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<string name="hello_first_fragment">Hello first fragment</string>
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
</resources>

View File

@ -9,4 +9,5 @@
<color name="white">#FFFFFFFF</color>
<color name="red">#FFFF0000</color>
<color name="gray">#5E5E5E</color>
<color name="gray1">#D2CACA</color>
</resources>

View File

@ -1,6 +1,6 @@
<resources>
<string name="app_name">NavinfoVolvo</string>
<string name="title_home">Home</string>
<string name="app_name">VolvoMessage</string>
<string name="title_home">Message</string>
<string name="title_dashboard">Dashboard</string>
<string name="title_notifications">Notifications</string>
<string name="delete">Del</string>