diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c2c39ee..9f7aa29 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,11 +1,9 @@ - - + package="com.gsps.gsp_android"> + - - + + android:theme="@style/Theme.GSP_Android"> + + - + android:exported="false" /> + android:exported="false" /> - - @@ -48,7 +49,7 @@ android:theme="@style/Theme.MaterialComponents.DayNight.DarkActionBar" /> + android:exported="true"> @@ -57,7 +58,7 @@ + android:exported="false" /> \ No newline at end of file diff --git a/app/src/main/java/com/gsps/gsp_android/ui/main/CategoryAdapter.kt b/app/src/main/java/com/gsps/gsp_android/ui/main/CategoryAdapter.kt new file mode 100644 index 0000000..24823e9 --- /dev/null +++ b/app/src/main/java/com/gsps/gsp_android/ui/main/CategoryAdapter.kt @@ -0,0 +1,78 @@ +package com.gsps.gsp_android.ui.main + +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.gsps.gsp_android.databinding.ItemCategoryBinding + +class CategoryAdapter( + val context: Context, + private val itemList: MutableList, + private val mFinishCallback: SetFinish, + private val mResultCallback: SetResult +) : RecyclerView.Adapter() { + private var isNewRadioButtonChecked: Boolean = false + private var lastCheckedPosition = -1 + private var isSomethingChecked = false + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): CategoryHolder { + val binding = + ItemCategoryBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + return CategoryHolder(binding) + } + + override fun onBindViewHolder(holder: CategoryHolder, position: Int) { + val categoryModel = itemList[position] + + if (isNewRadioButtonChecked) { + holder.binding.rbCategory.isChecked = categoryModel.getChecked() + } else if (holder.adapterPosition == 0) { + lastCheckedPosition = 0; + } + + holder.bind(itemList[position]) + } + + override fun getItemCount(): Int { + return itemList.size + } + + inner class CategoryHolder(var binding: ItemCategoryBinding) : + RecyclerView.ViewHolder(binding.root) { + init { + binding.rbCategory.setOnClickListener { + if (lastCheckedPosition == adapterPosition && itemList[adapterPosition].getChecked()) { + isNewRadioButtonChecked = false + isSomethingChecked = false + itemList[adapterPosition].setChecked(false) + notifyDataSetChanged() + } else { + isNewRadioButtonChecked = true + isSomethingChecked = true + itemList[lastCheckedPosition].setChecked(false) + itemList[adapterPosition].setChecked(true) + lastCheckedPosition = adapterPosition + notifyDataSetChanged() + } + + mFinishCallback.setFinish(isSomethingChecked) + if (isSomethingChecked) { + mResultCallback.setResult(itemList[lastCheckedPosition].getCategory()) + } + } + } + + fun bind(item: CategoryModel) { + binding.rbCategory.text = item.getCategory() + binding.rbCategory.isChecked = item.getChecked() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gsps/gsp_android/ui/main/CategoryModel.kt b/app/src/main/java/com/gsps/gsp_android/ui/main/CategoryModel.kt new file mode 100644 index 0000000..b8fc0fb --- /dev/null +++ b/app/src/main/java/com/gsps/gsp_android/ui/main/CategoryModel.kt @@ -0,0 +1,22 @@ +package com.gsps.gsp_android.ui.main + +data class CategoryModel( + private var category: String, + private var isChecked: Boolean +) { + fun getCategory(): String { + return category + } + + fun setCategory(category: String) { + this.category = category + } + + fun getChecked(): Boolean { + return isChecked + } + + fun setChecked(isChecked: Boolean) { + this.isChecked = isChecked + } +} diff --git a/app/src/main/java/com/gsps/gsp_android/ui/main/InterestsFullListAdapter.kt b/app/src/main/java/com/gsps/gsp_android/ui/main/InterestsFullListAdapter.kt index 906e135..ac271cb 100644 --- a/app/src/main/java/com/gsps/gsp_android/ui/main/InterestsFullListAdapter.kt +++ b/app/src/main/java/com/gsps/gsp_android/ui/main/InterestsFullListAdapter.kt @@ -13,7 +13,7 @@ class InterestsFullListAdapter( override fun onCreateViewHolder( parent: ViewGroup, viewType: Int - ): InterestsFullListAdapter.InterestsFullListHolder { + ): InterestsFullListHolder { val binding = InterestsFullListItemBinding.inflate( LayoutInflater.from(parent.context), @@ -23,10 +23,7 @@ class InterestsFullListAdapter( return InterestsFullListHolder(binding) } - override fun onBindViewHolder( - holder: InterestsFullListAdapter.InterestsFullListHolder, - position: Int - ) { + override fun onBindViewHolder(holder: InterestsFullListHolder, position: Int) { holder.bind(itemList[position]) } diff --git a/app/src/main/java/com/gsps/gsp_android/ui/main/MemberInfoCategoryActivity.kt b/app/src/main/java/com/gsps/gsp_android/ui/main/MemberInfoCategoryActivity.kt new file mode 100644 index 0000000..bf85e92 --- /dev/null +++ b/app/src/main/java/com/gsps/gsp_android/ui/main/MemberInfoCategoryActivity.kt @@ -0,0 +1,60 @@ +package com.gsps.gsp_android.ui.main + +import android.content.Intent +import android.widget.LinearLayout +import androidx.recyclerview.widget.StaggeredGridLayoutManager +import com.gsps.gsp_android.R +import com.gsps.gsp_android.databinding.ActivityMemberInfoCategoryBinding +import com.gsps.gsp_android.ui.base.BaseActivity + +class MemberInfoCategoryActivity : + BaseActivity(R.layout.activity_member_info_category), + SetFinish, SetResult { + var category: String = "" + override fun initView() { + initCategory() + + val categoryList: MutableList = mutableListOf( + CategoryModel("디자인", false), + CategoryModel("건설", false), + CategoryModel("인쇄&공예", false), + CategoryModel("사무", false), + CategoryModel("환경&에너지", false), + CategoryModel("경영&회계", false), + CategoryModel("화학&바이오", false), + CategoryModel("영업판매", false), + CategoryModel("섬유&의복", false), + CategoryModel("기획&마케팅", false), + CategoryModel("보건&의료", false), + CategoryModel("전기&전자", false), + CategoryModel("사회복지", false), + CategoryModel("재료", false) + ) + binding.categoryContainer.adapter = CategoryAdapter(this, categoryList, this, this) + binding.categoryContainer.layoutManager = + StaggeredGridLayoutManager(5, LinearLayout.HORIZONTAL) + + binding.btnFinish.setOnClickListener { + val intent = Intent() + intent.putExtra("category", category) + setResult(RESULT_OK, intent) + finish() + } + + binding.btnGoBack.setOnClickListener { + finish() + } + } + + override fun setFinish(status: Boolean) { + binding.btnFinish.isEnabled = status + } + + override fun setResult(category: String) { + this.category = category + } + + fun initCategory() { + this.category = "" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gsps/gsp_android/ui/main/MemberInfoWritingActivity.kt b/app/src/main/java/com/gsps/gsp_android/ui/main/MemberInfoWritingActivity.kt new file mode 100644 index 0000000..270b044 --- /dev/null +++ b/app/src/main/java/com/gsps/gsp_android/ui/main/MemberInfoWritingActivity.kt @@ -0,0 +1,170 @@ +package com.gsps.gsp_android.ui.main + +import android.content.ContentValues +import android.content.Intent +import android.content.pm.PackageManager +import android.graphics.ImageDecoder +import android.net.Uri +import android.os.Build +import android.provider.MediaStore +import android.view.View +import android.widget.Toast +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import com.gsps.gsp_android.R +import com.gsps.gsp_android.databinding.ActivityMemberInfoWritingBinding +import com.gsps.gsp_android.ui.base.BaseActivity +import java.text.SimpleDateFormat + + +class MemberInfoWritingActivity : + BaseActivity(R.layout.activity_member_info_writing) { + companion object { + private const val REQUEST_CAMERA = 1000 + private lateinit var permissions: Array + } + + private var imageUri: Uri? = null + + private val categoryResultLauncher: ActivityResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if (it.resultCode == RESULT_OK && it.data != null) { + binding.tvCategory.text = it.data?.getStringExtra("category") + } + } + + private val cameraResultLauncher: ActivityResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + binding.llPictureBox.visibility = View.GONE + + when (it.resultCode) { + RESULT_OK -> { + binding.ivMain.setImageURI(imageUri) + } + else -> { + imageUri?.let { uri -> contentResolver.delete(uri, null, null) } + } + } + } + + private val albumResultLauncher: ActivityResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + binding.llPictureBox.visibility = View.GONE + + if (it.resultCode == RESULT_OK && it.data != null) { + val currentImageUri = it.data!!.data + currentImageUri?.let { + val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val source = + ImageDecoder.createSource(this.contentResolver, currentImageUri) + ImageDecoder.decodeBitmap(source) + } else { + MediaStore.Images.Media.getBitmap(this.contentResolver, currentImageUri) + } + binding.ivMain.setImageBitmap(bitmap) + } + } + } + + override fun initView() { + permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + arrayOf(android.Manifest.permission.CAMERA) + } else { + arrayOf( + android.Manifest.permission.CAMERA, + android.Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } + + binding.btnGoBack.setOnClickListener { + finish() + } + + binding.tvCategory.setOnClickListener { + val intent = Intent(this, MemberInfoCategoryActivity::class.java) + categoryResultLauncher.launch(intent) + } + + binding.clPictures.setOnClickListener { + binding.llPictureBox.apply { + when (this.visibility) { + View.GONE -> this.visibility = View.VISIBLE + View.VISIBLE -> this.visibility = View.GONE + View.INVISIBLE -> this.visibility = View.VISIBLE + } + } + } + + binding.btnCamera.setOnClickListener { + if (permissionCheck()) { + val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) + + if (intent.resolveActivity(packageManager) != null) { + imageUri = saveImageInExternalPublicStorage() + intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri) + cameraResultLauncher.launch(intent) + } + } + } + + binding.btnAlbum.setOnClickListener { + if (permissionCheck()) { + val intent = Intent(Intent.ACTION_PICK) + intent.type = "image/*" + albumResultLauncher.launch(intent) + } + } + } + + private fun permissionCheck(): Boolean { + for (permission in permissions) { + val permissionCheck = + ContextCompat.checkSelfPermission(this, permission) + if (permissionCheck != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, permissions, REQUEST_CAMERA) + return false + } + } + return true + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + when (requestCode) { + REQUEST_CAMERA -> { + for (grant in grantResults) { + if (grant != PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, "권한을 승인해주세요", Toast.LENGTH_LONG).show() + } + } + } + } + } + + private fun saveImageInExternalPublicStorage(): Uri? { + val timeStamp: String = + SimpleDateFormat("yyyyMMdd_HHmmss").format(System.currentTimeMillis()) + val resolver = applicationContext.contentResolver + val imageCollection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + } else { + MediaStore.Images.Media.EXTERNAL_CONTENT_URI + } + val imageFileName = "BRIDGE_$timeStamp.jpg" + val imageDetails = + ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, imageFileName) } + val imageContentUri = resolver.insert(imageCollection, imageDetails) + + if (imageContentUri != null) { + resolver.update(imageContentUri, imageDetails, null, null) + } + + return imageContentUri + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gsps/gsp_android/ui/main/SetFinish.kt b/app/src/main/java/com/gsps/gsp_android/ui/main/SetFinish.kt new file mode 100644 index 0000000..d182fac --- /dev/null +++ b/app/src/main/java/com/gsps/gsp_android/ui/main/SetFinish.kt @@ -0,0 +1,5 @@ +package com.gsps.gsp_android.ui.main + +interface SetFinish { + fun setFinish(status: Boolean) +} \ No newline at end of file diff --git a/app/src/main/java/com/gsps/gsp_android/ui/main/SetResult.kt b/app/src/main/java/com/gsps/gsp_android/ui/main/SetResult.kt new file mode 100644 index 0000000..6cfb438 --- /dev/null +++ b/app/src/main/java/com/gsps/gsp_android/ui/main/SetResult.kt @@ -0,0 +1,5 @@ +package com.gsps.gsp_android.ui.main + +interface SetResult { + fun setResult(category: String) +} \ No newline at end of file diff --git a/app/src/main/res/drawable/select_picture_box_background.xml b/app/src/main/res/drawable/select_picture_box_background.xml new file mode 100644 index 0000000..bcf13ac --- /dev/null +++ b/app/src/main/res/drawable/select_picture_box_background.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_member_info_category.xml b/app/src/main/res/layout/activity_member_info_category.xml new file mode 100644 index 0000000..8a9d3f7 --- /dev/null +++ b/app/src/main/res/layout/activity_member_info_category.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_member_info_writing.xml b/app/src/main/res/layout/activity_member_info_writing.xml new file mode 100644 index 0000000..2caf7f0 --- /dev/null +++ b/app/src/main/res/layout/activity_member_info_writing.xml @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/interests_outer_list_item.xml b/app/src/main/res/layout/interests_outer_list_item.xml index 514d335..08fdaad 100644 --- a/app/src/main/res/layout/interests_outer_list_item.xml +++ b/app/src/main/res/layout/interests_outer_list_item.xml @@ -30,7 +30,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" - app:layout_constraintTop_toBottomOf="@id/tvCategory" /> + app:layout_constraintTop_toBottomOf="@id/rbCategory" /> + + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 997cb5b..c274d93 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,7 +16,10 @@ #ffcb22 #2bd131 #1aa8ff + #FFFDFDFD #ebebeb + #E7E7E7 + #E3E3E3 #cccccc #939393 #3d3d3d diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 598c0b5..8411c18 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,4 +44,6 @@ 최근 검색어 협업 신청하러가기 신규가입회사 + 회사소개 + yyyyMMdd_HHmmss \ No newline at end of file