Просмотр исходного кода

feat: 完成注册信息填写

DoggyZhang 4 месяцев назад
Родитель
Сommit
e4b76fbf4e
21 измененных файлов с 595 добавлено и 145 удалено
  1. 1 1
      app/src/main/java/com/adealink/weparty/commonui/widget/CommonButton.kt
  2. 8 0
      app/src/main/java/com/adealink/weparty/module/profile/viewmodel/IProfileViewModel.kt
  3. 9 2
      app/src/main/java/com/adealink/weparty/ui/category/data/CategoryData.kt
  4. 1 0
      app/src/main/res/values/dimens.xml
  5. 20 7
      module/account/src/main/java/com/adealink/weparty/account/register/RegisterProfileActivity.kt
  6. 71 0
      module/account/src/main/java/com/adealink/weparty/account/register/adapter/CategoryListItemViewBinder.kt
  7. 10 3
      module/account/src/main/java/com/adealink/weparty/account/register/dialog/ModifyAvatarDialog.kt
  8. 30 7
      module/account/src/main/java/com/adealink/weparty/account/register/fragment/CompleteUserInfoFragment.kt
  9. 138 0
      module/account/src/main/java/com/adealink/weparty/account/register/fragment/SelectCategoryFragment.kt
  10. 6 1
      module/account/src/main/java/com/adealink/weparty/account/register/viewmodel/RegisterProfileViewModel.kt
  11. 12 0
      module/account/src/main/res/drawable/account_register_category_item_bg.xml
  12. 36 0
      module/account/src/main/res/drawable/account_register_category_item_selected_bg.xml
  13. 14 13
      module/account/src/main/res/layout/fragment_register_complete_userinfo.xml
  14. 102 0
      module/account/src/main/res/layout/fragment_register_select_category.xml
  15. 2 3
      module/account/src/main/res/layout/fragment_register_select_gender.xml
  16. 46 0
      module/account/src/main/res/layout/layout_register_category_item.xml
  17. 4 0
      module/account/src/main/res/values/strings.xml
  18. 1 3
      module/profile/src/main/java/com/adealink/weparty/profile/edit/EditProfileActivity.kt
  19. 0 101
      module/profile/src/main/java/com/adealink/weparty/profile/edit/viewmodel/EditProfileViewModel.kt
  20. 84 0
      module/profile/src/main/java/com/adealink/weparty/profile/viewmodel/ProfileViewModel.kt
  21. 0 4
      module/profile/src/main/java/com/adealink/weparty/profile/viewmodel/ProfileViewModelFactory.kt

+ 1 - 1
app/src/main/java/com/adealink/weparty/commonui/widget/CommonButton.kt

@@ -74,8 +74,8 @@ class CommonButton @JvmOverloads constructor(
                     .gradientRadius(buttonRadius)
                     .cornerRadius(buttonRadius.toInt())
                     .gradientColors(
-                        getCompatColor(R.color.color_FF2A86E6),
                         getCompatColor(R.color.color_FF48E6C2),
+                        getCompatColor(R.color.color_FF2A86E6),
                         null
                     )
                     .gradientType(GradientDrawable.LINEAR_GRADIENT)

+ 8 - 0
app/src/main/java/com/adealink/weparty/module/profile/viewmodel/IProfileViewModel.kt

@@ -1,6 +1,7 @@
 package com.adealink.weparty.module.profile.viewmodel
 
 import androidx.lifecycle.LiveData
+import com.adealink.frame.base.Rlt
 import com.adealink.weparty.module.profile.data.UserInfo
 
 interface IProfileViewModel {
@@ -11,4 +12,11 @@ interface IProfileViewModel {
     fun getMyUserInfo(): UserInfo?
 
     fun getUserInfoBy(uid: String, cache: Boolean)
+
+    fun updateProfile(
+        newAvatarPath: String? = null,
+        newNickName: String? = null,
+        newGender: Int? = null,
+        newAge: String? = null,
+    ): LiveData<Rlt<Any>>
 }

+ 9 - 2
app/src/main/java/com/adealink/weparty/ui/category/data/CategoryData.kt

@@ -10,5 +10,12 @@ data class CategoryListTitleData(
 ) : CategoryItemData()
 
 data class CategoryListItemData(
-    val data: PlaymateCategoryData
-) : CategoryItemData()
+    val data: PlaymateCategoryData,
+    var selected: Boolean = false
+) : CategoryItemData() {
+    override fun areContentsTheSame(newItem: Any): Boolean {
+        val other = (newItem as? CategoryListItemData) ?: return false
+        return data == other.data
+                && selected == other.selected
+    }
+}

+ 1 - 0
app/src/main/res/values/dimens.xml

@@ -1,6 +1,7 @@
 <resources>
     <dimen name="common_top_bar_height">45dp</dimen>
     <dimen name="common_button_height">48dp</dimen>
+    <dimen name="common_button_margin_bottom">24dp</dimen>
 
     <dimen name="wheel_item_width">160dp</dimen>
     <dimen name="wheel_item_height">40dp</dimen>

+ 20 - 7
module/account/src/main/java/com/adealink/weparty/account/register/RegisterProfileActivity.kt

@@ -9,6 +9,7 @@ import com.adealink.weparty.account.R
 import com.adealink.weparty.account.databinding.ActivityRegisterProfileBinding
 import com.adealink.weparty.account.login.manager.loginManager
 import com.adealink.weparty.account.register.fragment.CompleteUserInfoFragment
+import com.adealink.weparty.account.register.fragment.SelectCategoryFragment
 import com.adealink.weparty.account.register.fragment.SelectGenderFragment
 import com.adealink.weparty.account.register.viewmodel.RegisterProfileViewModel
 import com.adealink.weparty.account.viewModel.AccountViewModelFactory
@@ -35,7 +36,7 @@ class RegisterProfileActivity : BaseActivity() {
     override fun initViews() {
         super.initViews()
         setContentView(binding.root)
-        inflateGenderSelectFragment()
+        inflateSelectGenderFragment()
     }
 
     override fun observeViewModel() {
@@ -43,17 +44,17 @@ class RegisterProfileActivity : BaseActivity() {
             inflateCompleteUserInfoFragment()
         }
         viewModel.completeUserInfoFinish.observeWithoutCache(this) {
-
+            inflateSelectCategoryFragment()
         }
     }
 
-    private fun inflateGenderSelectFragment() {
-        val fragment = supportFragmentManager.findFragmentByTag(TAG_GENDER_SELECT_FRAGMENT)
+    private fun inflateSelectGenderFragment() {
+        val fragment = supportFragmentManager.findFragmentByTag(TAG_SELECT_GENDER_FRAGMENT)
         if (fragment?.isDetached == true) {
             return
         }
         supportFragmentManager.beginTransaction()
-            .replace(R.id.fl_content, SelectGenderFragment(), TAG_GENDER_SELECT_FRAGMENT)
+            .replace(R.id.fl_content, SelectGenderFragment(), TAG_SELECT_GENDER_FRAGMENT)
             .commitAllowingStateLoss()
     }
 
@@ -67,9 +68,19 @@ class RegisterProfileActivity : BaseActivity() {
             .commitAllowingStateLoss()
     }
 
+    private fun inflateSelectCategoryFragment() {
+        val fragment = supportFragmentManager.findFragmentByTag(TAG_SELECT_CATEGORY_FRAGMENT)
+        if (fragment?.isDetached == true) {
+            return
+        }
+        supportFragmentManager.beginTransaction()
+            .replace(R.id.fl_content, SelectCategoryFragment(), TAG_SELECT_CATEGORY_FRAGMENT)
+            .commitAllowingStateLoss()
+    }
+
     override fun onBackPressed() {
         if (supportFragmentManager.findFragmentByTag(TAG_COMPLETE_USERINFO_FRAGMENT) != null) {
-            inflateGenderSelectFragment()
+            inflateSelectGenderFragment()
             return
         }
         super.onBackPressed()
@@ -78,8 +89,10 @@ class RegisterProfileActivity : BaseActivity() {
     }
 
     companion object {
-        const val TAG_GENDER_SELECT_FRAGMENT = "GenderSelectFragment"
+        const val TAG_SELECT_GENDER_FRAGMENT = "SelectGenderFragment"
         const val TAG_COMPLETE_USERINFO_FRAGMENT = "CompleteUserInfoFragment"
+
+        const val TAG_SELECT_CATEGORY_FRAGMENT = "SelectCategoryFragment"
     }
 
 }

+ 71 - 0
module/account/src/main/java/com/adealink/weparty/account/register/adapter/CategoryListItemViewBinder.kt

@@ -0,0 +1,71 @@
+package com.adealink.weparty.account.register.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.core.graphics.toColorInt
+import com.adealink.frame.util.onClick
+import com.adealink.weparty.account.R
+import com.adealink.weparty.account.databinding.LayoutRegisterCategoryItemBinding
+import com.adealink.weparty.commonui.drawabletoolbox.GradientBorderBuilder
+import com.adealink.weparty.commonui.drawabletoolbox.GradientBorderDrawable
+import com.adealink.weparty.commonui.ext.dpf
+import com.adealink.weparty.commonui.ext.gone
+import com.adealink.weparty.commonui.ext.show
+import com.adealink.weparty.commonui.recycleview.adapter.BindingViewHolder
+import com.adealink.weparty.commonui.recycleview.adapter.multitype.ItemViewBinder
+import com.adealink.weparty.ui.category.data.CategoryListItemData
+
+class CategoryListItemViewBinder(val listener: OnSelectListener) :
+    ItemViewBinder<CategoryListItemData, BindingViewHolder<LayoutRegisterCategoryItemBinding>>() {
+
+    override fun onBindViewHolder(
+        holder: BindingViewHolder<LayoutRegisterCategoryItemBinding>,
+        item: CategoryListItemData,
+    ) {
+        holder.binding.root.onClick {
+            listener.onSelect(item, holder.layoutPosition)
+        }
+        holder.binding.ivImg.setImageUrl(item.data.icon)
+        holder.binding.tvTab.text = item.data.name
+        if (item.selected) {
+            holder.binding.root.setBackgroundResource(R.drawable.account_register_category_item_selected_bg)
+            holder.binding.ivItemFrame.show()
+        } else {
+            holder.binding.root.setBackgroundResource(R.drawable.account_register_category_item_bg)
+            holder.binding.ivItemFrame.gone()
+        }
+    }
+
+    override fun onCreateViewHolder(
+        inflater: LayoutInflater,
+        parent: ViewGroup,
+    ): BindingViewHolder<LayoutRegisterCategoryItemBinding> {
+        val binding = LayoutRegisterCategoryItemBinding.inflate(inflater, parent, false)
+        binding.ivItemFrame.background = SELECT_DRAWABLE
+        return BindingViewHolder(binding)
+    }
+
+    interface OnSelectListener {
+        fun onSelect(item: CategoryListItemData, pos: Int)
+    }
+
+    companion object {
+        val SELECT_DRAWABLE: GradientBorderDrawable = GradientBorderBuilder()
+            .setRadii(
+                floatArrayOf(
+                    50.dpf(),
+                    50.dpf(),
+                    50.dpf(),
+                    50.dpf(),
+                    50.dpf(),
+                    50.dpf(),
+                    50.dpf(),
+                    50.dpf()
+                )
+            )
+            .setBorderWidth(1.dpf())
+            .setBorderAngle(315)
+            .setBorderColors(intArrayOf("#4ED2FF".toColorInt(), "#B1EF5D".toColorInt()))
+            .build()
+    }
+}

+ 10 - 3
module/account/src/main/java/com/adealink/weparty/account/register/dialog/ModifyAvatarDialog.kt

@@ -15,9 +15,9 @@ class ModifyAvatarDialog : BottomDialogFragment(R.layout.dialog_register_modify_
     private val binding by viewBinding(DialogRegisterModifyAvatarBinding::bind)
 
     private val viewModel by activityViewModels<RegisterProfileViewModel> { AccountViewModelFactory() }
-        private lateinit var takePhotoComp: TakePhotoComp
-        private lateinit var takeFromAlbumComp: TakeFromAlbumComp
-        override fun initViews() {
+    private lateinit var takePhotoComp: TakePhotoComp
+    private lateinit var takeFromAlbumComp: TakeFromAlbumComp
+    override fun initViews() {
         super.initViews()
         binding.tvTakePhoto.onClick {
             takePhoto()
@@ -30,6 +30,13 @@ class ModifyAvatarDialog : BottomDialogFragment(R.layout.dialog_register_modify_
         }
     }
 
+    override fun observeViewModel() {
+        super.observeViewModel()
+        viewModel.avatarPathLD.observe(viewLifecycleOwner) {
+            dismiss()
+        }
+    }
+
     override fun initComponents() {
         super.initComponents()
         TakePhotoComp(this).also {

+ 30 - 7
module/account/src/main/java/com/adealink/weparty/account/register/fragment/CompleteUserInfoFragment.kt

@@ -1,10 +1,11 @@
 package com.adealink.weparty.account.register.fragment
 
-import android.view.KeyEvent
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.updateLayoutParams
 import androidx.fragment.app.activityViewModels
 import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.base.fastLazy
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.util.DisplayUtil.getStatusBarHeight
 import com.adealink.frame.util.formatTime
@@ -15,11 +16,15 @@ import com.adealink.weparty.account.register.dialog.ModifyAvatarDialog
 import com.adealink.weparty.account.register.viewmodel.RegisterProfileViewModel
 import com.adealink.weparty.account.viewModel.AccountViewModelFactory
 import com.adealink.weparty.commonui.BaseFragment
+import com.adealink.weparty.commonui.toast.util.showFailedToast
+import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.commonui.widget.wheel.WheelDatePickerDialog
+import com.adealink.weparty.module.profile.ProfileModule
 
 class CompleteUserInfoFragment : BaseFragment(R.layout.fragment_register_complete_userinfo) {
     private val binding by viewBinding(FragmentRegisterCompleteUserinfoBinding::bind)
     private val viewModel by activityViewModels<RegisterProfileViewModel> { AccountViewModelFactory() }
+    private val profileViewModel by fastLazy { ProfileModule.getProfileViewModel(this) }
     override fun initViews() {
         super.initViews()
         binding.topBar.updateLayoutParams<ConstraintLayout.LayoutParams> {
@@ -70,16 +75,34 @@ class CompleteUserInfoFragment : BaseFragment(R.layout.fragment_register_complet
                 }
             }
         }.show(
-            childFragmentManager
+            childFragmentManager, "modifyBirthday"
         )
     }
 
     private fun nextStep() {
+        val nickName = binding.etNameInput.text?.toString()?.trim()
+        if (nickName.isNullOrEmpty()) {
+            showToast(R.string.account_register_nickname_is_null)
+            return
+        }
+        showLoading()
+        profileViewModel?.updateProfile(
+            newAvatarPath = viewModel.avatarPath,
+            newNickName = nickName,
+            newGender = viewModel.gender?.gender,
+            // TODO: 设置生日
+//            newAge = viewModel.birthday?.toString()
+        )?.observe(viewLifecycleOwner) { rlt ->
+            dismissLoading()
+            when (rlt) {
+                is Rlt.Failed -> {
+                    showFailedToast(rlt)
+                }
 
+                is Rlt.Success<*> -> {
+                    viewModel.notifyCompleteUserInfoFinish()
+                }
+            }
+        }
     }
-
-    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
-        return super.onKeyDown(keyCode, event)
-    }
-
 }

+ 138 - 0
module/account/src/main/java/com/adealink/weparty/account/register/fragment/SelectCategoryFragment.kt

@@ -0,0 +1,138 @@
+package com.adealink.weparty.account.register.fragment
+
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.view.updateLayoutParams
+import androidx.fragment.app.activityViewModels
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.base.AppBase
+import com.adealink.frame.base.fastLazy
+import com.adealink.frame.mvvm.view.viewBinding
+import com.adealink.frame.router.Router
+import com.adealink.frame.util.DisplayUtil.getStatusBarHeight
+import com.adealink.frame.util.onClick
+import com.adealink.weparty.AppModule
+import com.adealink.weparty.account.R
+import com.adealink.weparty.account.databinding.FragmentRegisterSelectCategoryBinding
+import com.adealink.weparty.account.register.adapter.CategoryListItemViewBinder
+import com.adealink.weparty.account.register.viewmodel.RegisterProfileViewModel
+import com.adealink.weparty.account.viewModel.AccountViewModelFactory
+import com.adealink.weparty.commonui.BaseFragment
+import com.adealink.weparty.commonui.ext.dp
+import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
+import com.adealink.weparty.commonui.recycleview.itemdecoration.GridSpacingMultiSpanSizeItemDecoration
+import com.adealink.weparty.module.playmate.PlaymateModule
+import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
+import com.adealink.weparty.ui.category.adapter.CategoryListTitleViewBinder
+import com.adealink.weparty.ui.category.data.CategoryItemData
+import com.adealink.weparty.ui.category.data.CategoryListItemData
+import com.adealink.weparty.ui.category.data.CategoryListTitleData
+
+class SelectCategoryFragment : BaseFragment(R.layout.fragment_register_select_category),
+    CategoryListItemViewBinder.OnSelectListener {
+
+    companion object {
+        const val TAG = "SelectCategoryFragment"
+        private const val SPAN_COUNT = 3
+    }
+
+    private val binding by viewBinding(FragmentRegisterSelectCategoryBinding::bind)
+
+    private val viewModel by activityViewModels<RegisterProfileViewModel> { AccountViewModelFactory() }
+
+    private val listAdapter by fastLazy { MultiTypeListAdapter<CategoryItemData>() }
+
+    private val categoryViewModel by fastLazy { PlaymateModule.getPlaymateViewModel(this) }
+
+    private lateinit var listLayoutManger: GridLayoutManager
+
+    private var categoryList = listOf<CategoryItemData>()
+    override fun initViews() {
+        super.initViews()
+        binding.topBar.updateLayoutParams<ConstraintLayout.LayoutParams> {
+            topMargin = activity?.let { act ->
+                getStatusBarHeight(act)
+            } ?: 0
+        }
+        binding.topBar.backCallback = {
+            activity?.onBackPressed()
+        }
+        binding.btnNext.text = getCompatString(R.string.account_register_go_home, AppBase.appName)
+        binding.btnNext.onClick {
+            nextStep()
+        }
+
+        binding.rvCategory.adapter = listAdapter
+        listAdapter.register(CategoryListTitleViewBinder())
+        listAdapter.register(CategoryListItemViewBinder(this))
+        listLayoutManger = GridLayoutManager(context, SPAN_COUNT, RecyclerView.VERTICAL, false)
+        listLayoutManger.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
+            override fun getSpanSize(position: Int): Int {
+                val data = listAdapter.items.getOrNull(position)
+                if (data is CategoryListTitleData) {
+                    return SPAN_COUNT
+                }
+                return 1
+            }
+        }
+        binding.rvCategory.layoutManager = listLayoutManger
+        binding.rvCategory.addItemDecoration(
+            GridSpacingMultiSpanSizeItemDecoration(SPAN_COUNT, 12.dp(), 8.dp(), false)
+        )
+    }
+
+    override fun loadData() {
+        super.loadData()
+        categoryViewModel?.pullAllCategory()
+    }
+
+    override fun observeViewModel() {
+        super.observeViewModel()
+        categoryViewModel?.allCategoryLD?.observe(viewLifecycleOwner) {
+            val onlineList = mutableListOf<PlaymateCategoryData>()
+            val activityList = mutableListOf<PlaymateCategoryData>()
+            for (entry in it.entries) {
+                if (entry.value.isActivity()) {
+                    activityList.add(entry.value)
+                } else {
+                    onlineList.add(entry.value)
+                }
+            }
+            val itemList = mutableListOf<CategoryItemData>()
+            for (data in onlineList) {
+                itemList.add(CategoryListTitleData(data))
+
+                for (subData in data.subCategoryList) {
+                    itemList.add(CategoryListItemData(subData))
+                }
+            }
+            for (data in activityList) {
+                itemList.add(CategoryListTitleData(data))
+
+                for (subData in data.subCategoryList) {
+                    itemList.add(CategoryListItemData(subData))
+                }
+            }
+            submitCategoryList(itemList)
+        }
+    }
+
+    private fun submitCategoryList(list: List<CategoryItemData>) {
+        this.categoryList = list
+        listAdapter.submitList(list)
+    }
+
+    private fun nextStep() {
+        activity?.let { act ->
+            Router.build(act, AppModule.Main.PATH).start()
+            act.finish()
+        }
+    }
+
+    override fun onSelect(item: CategoryListItemData, pos: Int) {
+        item.selected = !item.selected
+        listAdapter.notifyItemChanged(pos)
+    }
+
+}

+ 6 - 1
module/account/src/main/java/com/adealink/weparty/account/register/viewmodel/RegisterProfileViewModel.kt

@@ -8,7 +8,9 @@ import com.adealink.weparty.module.profile.data.Gender
 
 class RegisterProfileViewModel : BaseViewModel() {
     val genderLD = MutableLiveData<Gender>()
+    var gender: Gender? = null
     fun selectGender(gender: Gender) {
+        this.gender = gender
         genderLD.send(gender)
     }
 
@@ -23,17 +25,20 @@ class RegisterProfileViewModel : BaseViewModel() {
 
 
     val birthdayLD = MutableLiveData<Long>()
+    var birthday: Long? = null
     fun selectBirthday(birthday: Long) {
+        this.birthday = birthday
         birthdayLD.send(birthday)
     }
 
     var genderSelectFinish: ExtLiveData<Unit> = ExtMutableLiveData()
-    var completeUserInfoFinish: ExtLiveData<Unit> = ExtMutableLiveData()
 
     fun notifyGenderSelectFinish() {
         genderSelectFinish.send(Unit)
     }
 
+
+    var completeUserInfoFinish: ExtLiveData<Unit> = ExtMutableLiveData()
     fun notifyCompleteUserInfoFinish() {
         completeUserInfoFinish.send(Unit)
     }

+ 12 - 0
module/account/src/main/res/drawable/account_register_category_item_bg.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners
+        android:bottomLeftRadius="12dp"
+        android:bottomRightRadius="12dp"
+        android:topLeftRadius="30dp"
+        android:topRightRadius="12dp" />
+    <solid android:color="@color/white" />
+
+</shape>

+ 36 - 0
module/account/src/main/res/drawable/account_register_category_item_selected_bg.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape android:shape="rectangle">
+
+            <corners
+                android:bottomLeftRadius="12dp"
+                android:bottomRightRadius="12dp"
+                android:topLeftRadius="30dp"
+                android:topRightRadius="12dp" />
+            <solid android:color="@color/white" />
+
+        </shape>
+    </item>
+    <item
+        android:bottom="1dp"
+        android:left="1dp"
+        android:right="1dp"
+        android:top="1dp">
+        <shape android:shape="rectangle">
+
+            <corners
+                android:bottomLeftRadius="12dp"
+                android:bottomRightRadius="12dp"
+                android:topLeftRadius="30dp"
+                android:topRightRadius="12dp" />
+            <gradient
+                android:angle="45"
+                android:endColor="#DEF8DE"
+                android:startColor="#BDF5FF"
+                android:type="linear" />
+
+        </shape>
+    </item>
+</layer-list>
+

+ 14 - 13
module/account/src/main/res/layout/fragment_register_complete_userinfo.xml

@@ -1,11 +1,9 @@
 <?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:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@color/color_FFF1F2F5"
-    android:fitsSystemWindows="true">
+    android:background="@color/color_FFF1F2F5">
 
     <androidx.appcompat.widget.AppCompatImageView
         android:layout_width="0dp"
@@ -32,7 +30,7 @@
         android:ellipsize="end"
         android:gravity="start"
         android:includeFontPadding="false"
-        android:text="@string/common_hi"
+        android:text="@string/account_register_nice"
         android:textColor="@color/color_FF1D2129"
         android:textSize="48sp"
         app:layout_constrainedWidth="true"
@@ -104,10 +102,12 @@
 
                 <androidx.appcompat.widget.AppCompatEditText
                     android:id="@+id/et_name_input"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
+                    android:layout_width="0dp"
+                    android:layout_height="0dp"
                     android:background="@null"
                     android:fontFamily="@font/poppins_semibold"
+                    android:gravity="start|center_vertical"
+                    android:hint="@string/account_register_input_nickname_hint"
                     android:includeFontPadding="false"
                     android:textColor="@color/color_FF1D2129"
                     android:textColorHint="@color/color_FFC9CDD4"
@@ -116,8 +116,7 @@
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintHorizontal_bias="0"
                     app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent"
-                    tools:hint="test" />
+                    app:layout_constraintTop_toTopOf="parent" />
 
             </androidx.constraintlayout.widget.ConstraintLayout>
 
@@ -136,19 +135,21 @@
 
                 <androidx.appcompat.widget.AppCompatTextView
                     android:id="@+id/tv_birthday"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
+                    android:layout_width="0dp"
+                    android:layout_height="0dp"
                     android:background="@null"
                     android:fontFamily="@font/poppins_semibold"
+                    android:gravity="start|center_vertical"
+                    android:hint="@string/account_register_input_birthday_hint"
                     android:includeFontPadding="false"
                     android:textColor="@color/color_FF1D2129"
+                    android:textColorHint="@color/color_FFC9CDD4"
                     android:textSize="16sp"
                     app:layout_constraintBottom_toBottomOf="parent"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintHorizontal_bias="0"
                     app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent"
-                    tools:hint="test" />
+                    app:layout_constraintTop_toTopOf="parent" />
 
                 <androidx.appcompat.widget.AppCompatImageView
                     android:id="@+id/iv_birthday_edit"
@@ -171,7 +172,7 @@
         android:layout_width="0dp"
         android:layout_height="@dimen/common_button_height"
         android:layout_marginHorizontal="22dp"
-        android:layout_marginBottom="12dp"
+        android:layout_marginBottom="@dimen/common_button_margin_bottom"
         android:fontFamily="@font/poppins_semibold"
         android:gravity="center"
         android:includeFontPadding="false"

+ 102 - 0
module/account/src/main/res/layout/fragment_register_select_category.xml

@@ -0,0 +1,102 @@
+<?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="match_parent"
+    android:background="@color/color_FFF1F2F5">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintDimensionRatio="375:400"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/account_register_top_bg" />
+
+    <com.adealink.weparty.commonui.widget.CommonTopBar
+        android:id="@+id/top_bar"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/common_top_bar_height"
+        android:visibility="invisible"
+        app:bar_background="@color/transparent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_hi"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="22dp"
+        android:layout_marginTop="20dp"
+        android:ellipsize="end"
+        android:gravity="start"
+        android:includeFontPadding="false"
+        android:text="@string/common_hi"
+        android:textColor="@color/color_FF1D2129"
+        android:textSize="48sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/top_bar" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_select_gender"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="22dp"
+        android:layout_marginTop="6dp"
+        android:ellipsize="end"
+        android:gravity="start"
+        android:includeFontPadding="false"
+        android:text="@string/account_register_select_gender"
+        android:textColor="@color/color_FF1D2129"
+        android:textSize="24sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_hi" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_select_tips"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="22dp"
+        android:layout_marginTop="6dp"
+        android:ellipsize="end"
+        android:gravity="start"
+        android:includeFontPadding="false"
+        android:text="@string/account_register_select_gender_tips"
+        android:textColor="@color/color_FF4E5969"
+        android:textSize="14sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_select_gender" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/rv_category"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_marginTop="20dp"
+        android:paddingHorizontal="22dp"
+        android:paddingBottom="15dp"
+        app:layout_constraintBottom_toTopOf="@id/btn_next"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_select_tips" />
+
+    <com.adealink.weparty.commonui.widget.CommonButton
+        android:id="@+id/btn_next"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/common_button_height"
+        android:layout_marginHorizontal="22dp"
+        android:layout_marginBottom="@dimen/common_button_margin_bottom"
+        android:fontFamily="@font/poppins_semibold"
+        android:gravity="center"
+        android:includeFontPadding="false"
+        android:text="@string/account_register_go_home"
+        android:textColor="@color/white"
+        android:textSize="16sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 2 - 3
module/account/src/main/res/layout/fragment_register_select_gender.xml

@@ -3,8 +3,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@color/white"
-    android:fitsSystemWindows="true">
+    android:background="@color/white">
 
     <androidx.appcompat.widget.AppCompatImageView
         android:layout_width="0dp"
@@ -152,7 +151,7 @@
         android:layout_width="0dp"
         android:layout_height="@dimen/common_button_height"
         android:layout_marginHorizontal="22dp"
-        android:layout_marginBottom="12dp"
+        android:layout_marginBottom="@dimen/common_button_margin_bottom"
         android:enabled="false"
         android:fontFamily="@font/poppins_semibold"
         android:gravity="center"

+ 46 - 0
module/account/src/main/res/layout/layout_register_category_item.xml

@@ -0,0 +1,46 @@
+<?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:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingVertical="7dp">
+
+    <com.adealink.frame.image.view.NetworkImageView
+        android:id="@+id/iv_img"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:roundAsCircle="true" />
+
+    <View
+        android:id="@+id/iv_item_frame"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@id/iv_img"
+        app:layout_constraintEnd_toEndOf="@id/iv_img"
+        app:layout_constraintStart_toStartOf="@id/iv_img"
+        app:layout_constraintTop_toTopOf="@id/iv_img" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_tab"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingHorizontal="6dp"
+        android:layout_marginTop="5dp"
+        android:ellipsize="end"
+        android:gravity="center"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF1B1919"
+        android:textSize="12sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/iv_img"
+        tools:text="Online Play" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 4 - 0
module/account/src/main/res/values/strings.xml

@@ -48,4 +48,8 @@
    <string name="account_register_take_photo">拍照</string>
    <string name="account_register_from_album">从相册选择</string>
    <string name="account_register_use_default_avatar">使用默认头像</string>
+   <string name="account_register_input_nickname_hint">请输入昵称</string>
+   <string name="account_register_input_birthday_hint">请输入生日</string>
+   <string name="account_register_nickname_is_null">昵称不能为空,请输入昵称</string>
+   <string name="account_register_go_home">进入%s</string>
 </resources>

+ 1 - 3
module/profile/src/main/java/com/adealink/weparty/profile/edit/EditProfileActivity.kt

@@ -20,7 +20,6 @@ import com.adealink.weparty.module.profile.data.Gender
 import com.adealink.weparty.profile.R
 import com.adealink.weparty.profile.databinding.ActivityEditProfileBinding
 import com.adealink.weparty.profile.edit.comp.EditAvatarViewComponent
-import com.adealink.weparty.profile.edit.viewmodel.EditProfileViewModel
 import com.adealink.weparty.profile.viewmodel.ProfileViewModel
 import com.adealink.weparty.profile.viewmodel.ProfileViewModelFactory
 import com.adealink.weparty.R as APP_R
@@ -36,7 +35,6 @@ class EditProfileActivity : BaseActivity() {
 
     private val binding by viewBinding(ActivityEditProfileBinding::inflate)
     private val profileViewModel by viewModels<ProfileViewModel> { ProfileViewModelFactory() }
-    private val editProfileViewModel by viewModels<EditProfileViewModel> { ProfileViewModelFactory() }
     private var inputGender: Gender? = null
 
     private lateinit var avatarComp: EditAvatarViewComponent
@@ -109,7 +107,7 @@ class EditProfileActivity : BaseActivity() {
 
     private fun saveEdit() {
         showLoading()
-        editProfileViewModel.updateProfile(
+        profileViewModel.updateProfile(
             newAvatarPath = avatarComp.getAvatarPath(),
             newNickName = binding.etUserName.text?.toString(),
             newGender = inputGender?.gender,

+ 0 - 101
module/profile/src/main/java/com/adealink/weparty/profile/edit/viewmodel/EditProfileViewModel.kt

@@ -1,101 +0,0 @@
-package com.adealink.weparty.profile.edit.viewmodel
-
-import androidx.lifecycle.LiveData
-import com.adealink.frame.aab.util.getCompatString
-import com.adealink.frame.base.CommonDataNullError
-import com.adealink.frame.base.CommonParamError
-import com.adealink.frame.base.Rlt
-import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
-import com.adealink.frame.mvvm.viewmodel.BaseViewModel
-import com.adealink.frame.oss.data.UploadFile
-import com.adealink.weparty.App
-import com.adealink.weparty.profile.R
-import com.adealink.weparty.profile.data.UpdateMyUserInfoReq
-import com.adealink.weparty.profile.datasource.remote.ProfileHttpService
-import com.adealink.weparty.profile.manager.profileManager
-import kotlinx.coroutines.launch
-
-class EditProfileViewModel : BaseViewModel() {
-
-    private val profileHttpService by lazy {
-        App.instance.networkService.getHttpService(ProfileHttpService::class.java)
-    }
-
-    fun updateProfile(
-        newAvatarPath: String? = null,
-        newNickName: String? = null,
-        newGender: Int? = null,
-        newAge: String? = null,
-    ): LiveData<Rlt<Any>> {
-        val liveData = OnceMutableLiveData<Rlt<Any>>()
-        viewModelScope.launch {
-            val myUserInfo = profileManager.getMyUserInfo()
-            if (myUserInfo == null) {
-                liveData.send(Rlt.Failed(CommonDataNullError()))
-                return@launch
-            }
-
-            val editUserInfo = myUserInfo.copy()
-
-            newNickName?.trim()?.let { newNickName ->
-                if (newNickName.isEmpty()) {
-                    liveData.send(Rlt.Failed(CommonParamError(getCompatString(R.string.toast_profile_edit_name_empty))))
-                    return@launch
-                }
-                editUserInfo.nickName = newNickName
-            }
-
-            newGender?.let { newGender ->
-                editUserInfo.gender = newGender
-            }
-
-            newAge?.trim()?.let { newAge ->
-                if (newAge.isEmpty()) {
-                    liveData.send(Rlt.Failed(CommonParamError(getCompatString(R.string.toast_profile_edit_age_empty))))
-                    return@launch
-                }
-                val age = newAge.toIntOrNull()
-                if (age == null || age < 0) {
-                    liveData.send(Rlt.Failed(CommonParamError(getCompatString(R.string.toast_profile_edit_age_invalid))))
-                    return@launch
-                }
-                editUserInfo.age = age
-            }
-
-            //图片上传放到最后
-            //图片上传放到最后
-            //图片上传放到最后
-            newAvatarPath?.trim()?.takeIf { it.isNotEmpty() }?.let { avatarPath ->
-                val rlt = uploadAvatar(avatarPath)
-                when (rlt) {
-                    is Rlt.Failed -> {
-                        liveData.send(rlt)
-                        return@launch
-                    }
-
-                    is Rlt.Success -> {
-                        editUserInfo.avatar = rlt.data
-                    }
-                }
-            }
-
-            val rlt = profileHttpService.updateUserInfo(
-                UpdateMyUserInfoReq(
-                    avatar = editUserInfo.avatar,
-                    nickname = editUserInfo.nickName,
-                    gender = editUserInfo.gender,
-                    age = editUserInfo.age
-                )
-            )
-            liveData.send(rlt)
-        }
-        return liveData
-    }
-
-    private suspend fun uploadAvatar(avatarPath: String): Rlt<String> {
-        return App.instance.ossService.suspendUploadFile(
-            UploadFile.LocalFile(avatarPath, UploadFile.FileType.IMAGE)
-        )
-    }
-
-}

+ 84 - 0
module/profile/src/main/java/com/adealink/weparty/profile/viewmodel/ProfileViewModel.kt

@@ -2,12 +2,19 @@ package com.adealink.weparty.profile.viewmodel
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.base.CommonDataNullError
+import com.adealink.frame.base.CommonParamError
 import com.adealink.frame.base.Rlt
+import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
 import com.adealink.frame.mvvm.viewmodel.BaseViewModel
+import com.adealink.frame.oss.data.UploadFile
 import com.adealink.weparty.App
 import com.adealink.weparty.module.profile.data.UserInfo
 import com.adealink.weparty.module.profile.listener.IProfileListener
 import com.adealink.weparty.module.profile.viewmodel.IProfileViewModel
+import com.adealink.weparty.profile.R
+import com.adealink.weparty.profile.data.UpdateMyUserInfoReq
 import com.adealink.weparty.profile.datasource.remote.ProfileHttpService
 import com.adealink.weparty.profile.manager.profileManager
 import kotlinx.coroutines.launch
@@ -42,4 +49,81 @@ class ProfileViewModel : BaseViewModel(), IProfileViewModel, IProfileListener {
     override fun getUserInfoBy(uid: String, cache: Boolean) {
 
     }
+
+    override fun updateProfile(
+        newAvatarPath: String?,
+        newNickName: String?,
+        newGender: Int?,
+        newAge: String?,
+    ): LiveData<Rlt<Any>> {
+        val liveData = OnceMutableLiveData<Rlt<Any>>()
+        viewModelScope.launch {
+            val myUserInfo = profileManager.getMyUserInfo()
+            if (myUserInfo == null) {
+                liveData.send(Rlt.Failed(CommonDataNullError()))
+                return@launch
+            }
+
+            val editUserInfo = myUserInfo.copy()
+
+            newNickName?.trim()?.let { newNickName ->
+                if (newNickName.isEmpty()) {
+                    liveData.send(Rlt.Failed(CommonParamError(getCompatString(R.string.toast_profile_edit_name_empty))))
+                    return@launch
+                }
+                editUserInfo.nickName = newNickName
+            }
+
+            newGender?.let { newGender ->
+                editUserInfo.gender = newGender
+            }
+
+            newAge?.trim()?.let { newAge ->
+                if (newAge.isEmpty()) {
+                    liveData.send(Rlt.Failed(CommonParamError(getCompatString(R.string.toast_profile_edit_age_empty))))
+                    return@launch
+                }
+                val age = newAge.toIntOrNull()
+                if (age == null || age < 0) {
+                    liveData.send(Rlt.Failed(CommonParamError(getCompatString(R.string.toast_profile_edit_age_invalid))))
+                    return@launch
+                }
+                editUserInfo.age = age
+            }
+
+            //图片上传放到最后
+            //图片上传放到最后
+            //图片上传放到最后
+            newAvatarPath?.trim()?.takeIf { it.isNotEmpty() }?.let { avatarPath ->
+                val rlt = uploadAvatar(avatarPath)
+                when (rlt) {
+                    is Rlt.Failed -> {
+                        liveData.send(rlt)
+                        return@launch
+                    }
+
+                    is Rlt.Success -> {
+                        editUserInfo.avatar = rlt.data
+                    }
+                }
+            }
+
+            val rlt = profileHttpService.updateUserInfo(
+                UpdateMyUserInfoReq(
+                    avatar = editUserInfo.avatar,
+                    nickname = editUserInfo.nickName,
+                    gender = editUserInfo.gender,
+                    age = editUserInfo.age
+                )
+            )
+            liveData.send(rlt)
+        }
+        return liveData
+    }
+
+    private suspend fun uploadAvatar(avatarPath: String): Rlt<String> {
+        return App.instance.ossService.suspendUploadFile(
+            UploadFile.LocalFile(avatarPath, UploadFile.FileType.IMAGE)
+        )
+    }
 }

+ 0 - 4
module/profile/src/main/java/com/adealink/weparty/profile/viewmodel/ProfileViewModelFactory.kt

@@ -2,7 +2,6 @@ package com.adealink.weparty.profile.viewmodel
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
-import com.adealink.weparty.profile.edit.viewmodel.EditProfileViewModel
 
 @Suppress("UNCHECKED_CAST")
 class ProfileViewModelFactory : ViewModelProvider.NewInstanceFactory() {
@@ -13,9 +12,6 @@ class ProfileViewModelFactory : ViewModelProvider.NewInstanceFactory() {
                 isAssignableFrom(ProfileViewModel::class.java) ->
                     ProfileViewModel()
 
-                isAssignableFrom(EditProfileViewModel::class.java) ->
-                    EditProfileViewModel()
-
                 else ->
                     throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
             } as T