-
private fun loginEvent() { binding.btnLogin.setOnClickListener { if (!binding.etId.text.isNullOrBlank() && !binding.etPw.text.isNullOrBlank()) { showToast("๋ก๊ทธ์ธ ์ฑ๊ณต") goHome() } else showToast("์์ด๋/๋น๋ฐ๋ฒํธ๋ฅผ ํ์ธํด์ฃผ์ธ์") } }
-
private fun signupEvent() { with(binding) { btnComplete.setOnClickListener { if (!binding.etId.text.isNullOrBlank() && !binding.etName.text.isNullOrBlank() && !binding.etPw.text.isNullOrBlank()) { val intent = Intent(this@SignUpActivity, SignInActivity::class.java) intent.putExtra("id", etId.text.toString()) intent.putExtra("password", etPw.text.toString()) setResult(RESULT_OK, intent) finish() } else { showToast("์ ๋ ฅํ์ง ์์ ์ ๋ณด๊ฐ ์์ต๋๋ค.") } } } }
-
private fun setSignUp() { resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { val id = result.data?.getStringExtra("id") ?: "" val password = result.data?.getStringExtra("password") ?: "" binding.etId.setText(id) binding.etPw.setText(password) } } } private fun signupEvent() { binding.btnSignup.setOnClickListener { val intent = Intent(this, SignUpActivity::class.java) resultLauncher.launch(intent) } }
-
<data> <variable name="user" type="org.sopt.seminar.User" /> </data> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".HomeActivity"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/img_profile" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginHorizontal="120dp" android:layout_marginTop="50dp" android:src="@drawable/profile" app:layout_constraintDimensionRatio="1:1" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView . . android:text="@{user.age}" . ./>
-
[DataBinding] -๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ฃผ๋ชฉ์ ์ UI ๋ ์ด์์์ ๋ทฐ๋ฅผ ์ฑ ์ฝ๋์ ์ ์ฅ๋ ๋ฐ์ดํฐ์ ์ฐ๊ฒฐํ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ ๊ณต -๋ฐ์ดํฐ์ ๋ทฐ๋ฅผ ์ฐ๊ฒฐํ๋ ์์ ์ ๋ ์ด์์์์ -๋ฒํผ๊ณผ ๊ฐ์ UI ์ปจํธ๋กค์ UI์ปจํธ๋กค๋ฌ ๋๋ ViewModel ์ธ์คํด์ค์ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ด๋ฒคํธ๋ ๋ฆฌ์ค๋ ํจ์์ ์ฐ๊ฒฐ ์ํค๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ๋ ์กด์ฌ -ํนํ LiveData ์ปดํฌ๋ํธ์ ๊ฐ์ด ์ฌ์ฉ ๋ ๋ ์ด์ ์ด ๋ฐฐ๊ฐ ๋จ -xml๋จ์์ <layout> ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ง๋ ๊ฒ๋ง ์ฒ๋ฆฌ [ViewBinding] -findViewById()์ฌ์ฉ๋ณด๋ค Null ์์ ์ ์์ด ์๋์ ๊ฐ์ ์ฅ์ ์ด ์กด์ฌ -๋ทฐ ๊ฒฐํฉ์ ๋ทฐ์ ์ง์ ์ฐธ์กฐ๋ฅผ ์์ฑํ๋ฏ๋ก ์ ํจํ์ง ์์ ๋ทฐ ID๋ก ์ธํด null ํฌ์ธํฐ ์์ธ๊ฐ ๋ฐ์ํ ์ํ์ด ์์ -๋ ์ด์์์ ์ผ๋ถ ๊ตฌ์ฑ์๋ง ๋ทฐ๊ฐ ์๋ ๊ฒฝ์ฐ ๊ฒฐํฉ ํด๋์ค์์ ์ฐธ์กฐ๋ฅผ ํฌํจํ๋ ํ๋๊ฐ @Nullable๋ก ํ์ -๋ทฐ๋ฐ์ธ๋ฉ์ ๋ฐ์ดํฐ๋ฐ์ธ๋ฉ์ ๋นํด ์ฃผ์์ฒ๋ฆฌ๊ฐ ํ์ํ์ง ์์ผ๋ฏ๋ก ๋ ๋น ๋ฅธ ์ปดํ์ผ ์๋๋ฅผ ๊ฐ์ง -ํ์ง๋ง ๋ทฐ๋ฐ์ธ๋ฉ์ ๋ ์ด์์ ๋ณ์ ๋๋ ๋ ์ด์์ ํํ์์ ์ง์ํ์ง ์์ผ๋ฏ๋ก XML ๋ ์ด์์ ํ์ผ์์ ์ง์ ๋์ UI ์ฝํ ์ธ ๋ฅผ ์ ์ธํ๋ ๋ฐ ์ฌ์ฉ ๋ถ๊ฐ๋ฅ -์๋ฐฉํฅ ๋ฐ์ดํฐ ๊ฒฐํฉ ์ง์ ๋ถ๊ฐ
๋ก๊ทธ์ธ | ํ์๊ฐ์ |
---|---|
-
supportFragmentManager.beginTransaction().add(R.id.fragment_home, followerFragment).commit() binding.btnFollower.setOnClickListener { val transaction = supportFragmentManager.beginTransaction() if (position == REPO_POSITION) { transaction.replace(R.id.fragment_home, followerFragment).commit() position = FOLLOWER_POSITION } } binding.btnRepo.setOnClickListener { val transaction = supportFragmentManager.beginTransaction() if (position == FOLLOWER_POSITION) { transaction.replace(R.id.fragment_home, repoFragment).commit() position = REPO_POSITION } }
-
<TextView ... android:ellipsize="end" android:ems="8" android:maxLines="1" android:text="@{repo.repo}" android:textColor="@color/black" android:textSize="17sp" android:textStyle="bold" ... /> <TextView ... android:ellipsize="end" android:ems="7" android:maxLines="1" android:text="@{repo.introduction}" android:textColor="@color/black" android:textSize="15sp" ... />
-
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
-
private fun itemClickEvent() { followerAdapter.setItemClickListener(object : FollowerAdapter.OnItemClickListener { override fun onClick(view: View, position: Int) { val name = followerAdapter.currentList[position].name val introduce = followerAdapter.currentList[position].introduction val intent = Intent(context, DetailActivity::class.java) .putExtra("name", name) .putExtra("introduction", introduce) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } }) }
-
private fun recyclerViewDecoration() { with(binding) { rvFollower.addItemDecoration(VerticalItemDecorator(10)) rvFollower.addItemDecoration(HorizontalItemDecorator(10)) } }
-
val callback = MyTouchHelperCallback(followerAdapter) val touchHelper = ItemTouchHelper(callback) touchHelper.attachToRecyclerView(binding.rvFollower) binding.rvFollower.adapter = followerAdapter followerAdapter.startDrag(object : FollowerAdapter.OnStartDragListener { override fun onStartDrag(viewHolder: FollowerAdapter.FollowerViewHolder) { touchHelper.startDrag(viewHolder) } })
-
abstract class BaseFragment<B : ViewDataBinding>(@LayoutRes private val layoutRes: Int) : Fragment() { private var _binding: B? = null val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = DataBindingUtil.inflate(inflater, layoutRes, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.lifecycleOwner = this initAdapter() } abstract fun initAdapter() override fun onDestroyView() { _binding = null super.onDestroyView() } }
-
class RepoViewHolder( private val binding: ItemRepoListBinding ) : RecyclerView.ViewHolder(binding.root) { fun onBind(repoData: RepoData) { binding.repo = repoData } } companion object { val DIFFUTIL = object : DiffUtil.ItemCallback<RepoData>() { override fun areItemsTheSame( oldItem: RepoData, newItem: RepoData ): Boolean { return oldItem.repo == newItem.repo } override fun areContentsTheSame( oldItem: RepoData, newItem: RepoData ): Boolean { return oldItem == newItem } } }
-
์์ฒ๊ฐ์ ๋ฐ์ดํฐ ์ค ๋จ ํ ๊ฐ์ ๋ฐ์ดํฐ๋ง ๋ฐ๋๋ค๋ฉด notifyDataSetChanged()์ ์ฌ์ฉ์ ๋นํจ์จ์ ์ด๋ค.
๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ์ position์ ์ธ์๋ก ๋๊ฒจ์ฃผ์ด ํด๋น ๋ฐ์ดํฐ๋ง ๋ณ๊ฒฝํ๋ notifyItemChanged๊ฐ ์์ง๋ง ์ญ์๋ position์ ์ฐพ์ ๋๊ฒจ์ฃผ๋ฉฐ ํ๋ํ๋ ๊ฐ์ ๋ณ๊ฒฝํ๋ ๋ฒ๊ฑฐ๋ก์ด ์ผ์ด ๋ฐ์ํ๋ค.
-
-
ListAdapter๋ DiffUtil์ ํ์ฉํ์ฌ ๋ฆฌ์คํธ๋ฅผ ์ ๋ฐ์ดํธํ ์ ์๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ Adapter, ๊ธฐ์กด ์ด๋ํฐ์ ๋น๊ตํด์ ์ถ๊ฐ๋ก DiffUtil ๊ธฐ๋ฅ์ ๋ํ ์ฝ๋ฐฑ ๊ธฐ๋ฅ ํด๋์ค๋ง ๊ตฌํํ๋ฉด ๋๋ฏ๋ก ์์ฐ์ฑ, ํจ์จ์ฑ์ ๋์ผ ์ ์๋ค.
-
https://velog.io/@l2hyunwoo/Android-RecyclerView-DiffUtil-ListAdapter
-
https://velog.io/@deepblue/RecyclerView%EC%9D%98-notifyDataSetChanged
-
DetailActivity | ์์ดํ ์ด๋ |
---|---|
-
private fun initTransactionEvent() { val followerFragment = FollowerFragment() val repositoryFragment = RepoFragment() childFragmentManager.beginTransaction().add(R.id.fragment_profile, followerFragment) .commit() binding.btnFollower.isSelected = true //์ฒ์ ํ๋ฉด ๋ณด์ฌ์ง ์์ binding.btnFollower.setTextColor(Color.BLACK) binding.btnFollower.setOnClickListener { childFragmentManager.beginTransaction() .replace(R.id.fragment_profile, followerFragment) .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) .commit() binding.btnFollower.isSelected = true; binding.btnRepo.isSelected = false; binding.btnRepo.setTextColor(Color.GRAY) binding.btnFollower.setTextColor(Color.BLACK) } binding.btnRepo.setOnClickListener { childFragmentManager.beginTransaction() .replace(R.id.fragment_profile, repositoryFragment) .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) .commit() binding.btnRepo.isSelected = true binding.btnFollower.isSelected = false binding.btnFollower.setTextColor(Color.GRAY) binding.btnRepo.setTextColor(Color.BLACK) } }
-
private fun initTabLayout() { val tabLable = listOf("ํ๋ก์", "ํ๋ก์") TabLayoutMediator(binding.homeTablayout, binding.vpHome) { tab, position -> tab.text = tabLable[position] }.attach() }
<com.google.android.material.tabs.TabLayout android:id="@+id/home_tablayout" ... app:tabIndicatorColor="@color/sopt_main_purple" app:tabMode="fixed" app:tabSelectedTextColor="@color/sopt_main_purple" />
-
class ViewPagerAdapter(fragment: FragmentActivity) : FragmentStateAdapter(fragment) { override fun getItemCount() = 3 override fun createFragment(position: Int): Fragment { return when (position) { 0 -> ProfileFragment() 1 -> HomeFragment() else -> CameraFragment() } } }
-
<org.sopt.seminar.NestedScrollableHost android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/home_tablayout"> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/vp_home" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FAFAFA" /> </org.sopt.seminar.NestedScrollableHost>
-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
private val activityLauncher: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { if (it.resultCode == RESULT_OK && it.data != null) { var currentImageUri = it.data?.data Glide.with(requireActivity()).load(currentImageUri).into(binding.ivGalleryImage) } else if (it.resultCode == RESULT_CANCELED) { requireActivity().showToast("์ฌ์ง ์ ํ ์ทจ์") } else { requireActivity().showToast("์ฌ์ง ์ฒจ๋ถ ์คํจ") } }
Profile,Home | Camera |
---|---|