일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 1차원 DP
- 2차원 dp
- 99클럽
- @GeneratedValue
- @GenericGenerator
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- async/await
- AVG
- AWS
- Azure
- bind
- builder
- button
- c++
- c++ builder
- c03
- Callback
- case when
- CCW
- chat GPT
- CICD
- Collections
- Combination
- combinations
- Comparator
- Today
- Total
기록
AndroidStudio/수직-수평 슬라이딩 이벤트 넣기 : 중첩 뷰페이저 활용 본문
문제
사이드 프로젝트(Android application to organize photos by swiping)중 상하좌우 슬라이딩 이벤트별 액션을 지정해야 했다. 어떤 이벤트에 어떤 액션을 지정할지는 정해지지 않았고, 샘플 앱을 만들어 테스트 한 후에 정하기로 했다.
테스트1 |
|
테스트2 |
|
해결방법
뷰페이저를 2중으로 감싸서 상하좌우 스와이핑 이벤트에 액션을 지정했다.
테스트1 -> 테스트2로 전환할 때 뷰페이저의 방향만 반대로 바뀌어주면 되어서, 코드의 변경이 적었다.
코드
https://github.com/youngyin/orgnzPhts
1. Parent
- fragment
class SliderFragment : Fragment() {
private var _binding: FragmentSliderBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
model = ViewModelProvider(this)[SliderViewModel::class.java]
_binding = FragmentSliderBinding.inflate(inflater, container, false)
val root: View = binding.root
binding.vpSlide.adapter = PagerAdapter(requireActivity(), it,
object : SliderListener {
override fun showPrev() : Boolean {}
override fun showNext() : Boolean {}
override fun favorite(photo: Photo) {}
override fun delete(photo: Photo) {}})
return root
}
}
- adapter
class PagerAdapter(
fa : FragmentActivity,
var database: ArrayList<Photo>,
private val listener : SliderListener
) : FragmentStateAdapter(fa) {
private lateinit var fragment : Fragment
override fun getItemCount(): Int = database.size
override fun createFragment(position: Int): Fragment {
fragment = PhotoFragment(database[position], listener)
return fragment
}
}
2. child
- fragment
class PhotoFragment(
var photo: Photo,
val listener : SliderListener
) : Fragment() {
private var _binding: FragmentPhotoBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentPhotoBinding.inflate(inflater, container, false)
val adapter = InnerPagerAdapter()
adapter.setPhoto(photo)
binding.vpSlide.adapter = adapter
binding.vpSlide.setCurrentItem(1, false)
binding.vpSlide.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
when(position){
0 -> listener.delete(photo)
2 -> listener.favorite(photo)
}
}
})
return binding.root
}
}
- adapter
class InnerPagerAdapter : RecyclerView.Adapter<InnerPagerAdapter.ViewHolder>() {
private val database = ArrayList<Photo>()
fun setPhoto(photo: Photo){
database.clear()
database.add(Photo("", "", 0L, ""))
database.add(photo)
database.add(Photo("", "", 0L, ""))
notifyItemChanged(1)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType1: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_viewpager_photo, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(database[position])
}
override fun getItemCount(): Int = database.size
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
@SuppressLint("ClickableViewAccessibility", "CheckResult")
fun bind(photo: Photo) {
itemView.findViewById<TextView>(R.id.tv_photo).text = photo.toString()
}
}
}
개선할점/주의할점
1. 멀티뷰타입
adapter를 두개 사용하지만, 각 adapter가 하는 역할이 크게 다르지 않다. 이전에 시도했었던 멀티뷰타입(2022.05.29 - [Moblie/Android] - AndroidStudio/java/ 멀티뷰 타입 Recyclerview)을 활용하면, adapter을 하나만 둘 수 있을 것이다.
2. 뷰페이저 setOffscreenPageLimit
3. 사진 가져오기
해당 프로젝트는 사진첩에서 사진을 가져와 삭제할 사진과 저장할 사진을 쉽게 구분할 수 있도록 하는 것이 주된 아이디어이다. 이로 인해 mediaStore을 이용해 갤러리에 접근하는 것이 필요했으며, 해당 내용은 추후 정리하여 공유할 예정이다.
4. 프로젝트 구조
스프링을 접하고 난 이후에 한 첫 프로젝트라, 각 요소를 spring처럼 써보려고 했다. 사진첩에서 사진 데이터를 직접 요청하는 로직, 퍼미션을 체크하는 로직 등을 서비스로 빼고, viewmodel은 연관 있는 서비스를 호출하는데에만 사용하려고 했다. 이후 내부 DB를 사용하게 되면, dao와 service도 나누어 볼 생각이다.
'Moblie > Android' 카테고리의 다른 글
issue/Spinner/java.lang.NullPointerException(onItemSelected) (0) | 2022.11.21 |
---|---|
Androidstudio/kotlin/멀티뷰타입 리사이클러뷰 응용 (0) | 2022.08.10 |
AndroidStudio/kotlin/Enum을 이용한 fragment 재활용 (0) | 2022.07.22 |
[issue] 공공데이터 api connectError (0) | 2022.07.18 |
AndroidStudio/XML의 글꼴 적용하기 (0) | 2022.07.12 |