스크롤 시에 contentOffset 의 y값에 따라 이동하고 싶습니다.

3 답변 글타래를 보이고 있습니다
  • 글쓴이
    • 뚭니
      참가자
      • 글작성 : 9
      • 답글작성 : 17

      안녕하세요,

      먼저 제가 남긴 질문을 클릭하고 들어와주셔서 감사합니다.

      저는 iOS 를 1년이 조금 안되는 기간 동안 혼자 공부하고 있어 작은 키워드라도 답변을 남겨주신다면 큰 도움이 될 것 같습니다.

       

      제가 구현한 방식은 UIScrollViewDelegate 딜리게이트 안에 scrollViewWillEndDragging 메소드를 사용했고, withVelocity 파라미터를 추가하여 스크롤의 위/아래 방향을 감지할 수 있도록 하였습니다.

      현재는 아래 코드와 같이 transform 을 애니메이션 함수 안에 넣어 duration 만 주었기 때문에 contentOffset 의 y값이 얼마만큼 증가 했는지와 상관 없이 스크롤이 발생하면 해당 좌표로 고정 이동합니다. 스크롤이 아래로 발생한다면 transform 값을 .identity 로 설정하여 모든 변환이 제거되는 방법입니다.


      // 스크롤이 위로 발생했을 때 효과 func topViewUp() { UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: { // 상단바 위치 올리기 self.topView.transform = CGAffineTransform(translationX: 0, y: -115) self.view.layoutIfNeeded() }) }

      구현하고자 하는 바는 contentOffset 의 y값이 점차 증가함에 따라 topView 의 위치도 함께 점차 점차 이동시키고 싶습니다.

      제가 시도했던 방법은 CGAffineTransform 의 y 값에다가 scrollView 의 contentOffset y 좌표를 넣는 것이었습니다.

      CGAffineTransform(translationX: 0, y: -self.scrollView.contentOffset.y)

      그러나 위와 같이 사용하니 스크롤이 위로 발생하면서 contentOffset 의 y좌표 값이 증가할 수록 topView 가 무한정 위로 올라가 화면에서 사라져버리는 문제가 있었습니다.

      topView 가 점차 점차 위로 올라가되, 최대 -115 이상으로 올라가지 않도록 제한하고 싶습니다.

      어떻게 검색하면 좋을지 키워드를 알려주신다면 무척 감사합니다.

    • 멍단비
      참가자
      • 글작성 : 10
      • 답글작성 : 98

      애니메이션 함수내에 첫번째줄에 self.scrollView.contentOffset.y 가 115보다 크면 리턴해버리는 가드문 넣으면 안되던가요 ?

    • 뚭니
      참가자
      • 글작성 : 9
      • 답글작성 : 17

      안녕하세요!

      귀한 시간 내어 아이디어 공유해주셔서 무척 감사드립니다.

       

      말씀해주신 방법이 효과가 있을 것 같아

      guard self.scrollView.contentOffset.y <= CGFloat(115) else { return }

      위 구문을 추가하여 구동해보았습니다.

       

      제가 가드문을 생각해주신 바와 같게 사용했는지 모르겠습니다만

      contentOffset.y 값이 바뀌는 속도에 따라서 return 되는 지점이 다른 것 같습니다.

      스크롤 강도를 어떻게 했느냐에 따라 topView의 y 위치가 조금 변경되기도 하고 많이 변경되기도 하여 return 되는 시점의 y값을 출력해보니 아래와 같이 때마다 달랐습니다.

      이 이슈는 제가 velocity 로 스크롤 방향을 체크해서 발생한 문제같기도 합니다.

      UISwipeGestureRecognizer 를 사용하여 다시 구현해보려고 합니다.

       

      혹시 제가 잘못 알고 있는 부분이 있다면 지적해주시면 감사하겠습니다.

      도움 주셔서 감사합니다.

    • i참
      참가자
      • 글작성 : 1
      • 답글작성 : 10

      질문을 제대로 이해했는지 모르겠지만 아마도 테이블 뷰 섹션 헤더를 구현하려는 것으로 생각됩니다.
      저장해 둔 스니펫이 있어서 남깁니다(잘 되는지는 모르겠네요).
      func scrollViewDidScroll(_ scrollView: UIScrollView) {
      let sectionHeaderHeight: CGFloat = 40
      if scrollView.contentOffset.y &lt;= sectionHeaderHeight &amp;&amp; scrollView.contentOffset.y &gt;= 0 {
      scrollView.contentInset = UIEdgeInsets(top: -scrollView.contentOffset.y, left: 0, bottom: 0, right: 0)
      } else if scrollView.contentOffset.y &gt;= sectionHeaderHeight {
      scrollView.contentInset = UIEdgeInsets(top: -sectionHeaderHeight, left: 0, bottom: 0, right: 0)
      }
      }

      추가로 뷰의 위치를 변경하고자 하는것이 최종 목적이라면 transform 대신 다른 방법을 사용하는 것이 좋아 보입니다. 아핀 트랜스폼이 무엇인지 어디에 주로 활용되는지 이 기회에 알아두셔도 좋겠네요.
      https://developer.apple.com/documentation/uikit/uiview/1622459-transform

      • 이 답변은 i참에 의해 4 years, 1 month 전에 수정됐습니다.
      • 뚭니
        참가자
        • 글작성 : 9
        • 답글작성 : 17

        안녕하세요, 아이참님!

        조언과 공유해주신 snippet 까지 모두 감사드립니다.

         

        말씀해주신 바와 같이 tableView 의 섹션 헤더 인터랙션을 tableView 가 아닌 scrollView 에서 구현해보고 싶어 시도해보았습니다.

        공유해주신 공식 문서를 읽어보니 뷰의 위치를 변경하는 저와 같은 경우에는 transform 속성보다 frame 값을 변경하는 것이 더 적절한 방법이겠군요..

        덕분에 frame 과 bounds 의 차이도 다시 공부하였습니다.

         

        부족한 부분을 짚어주신 덕분에 발전하네요.

        친절히 링크까지 남겨주셔서 감사합니다.

3 답변 글타래를 보이고 있습니다
  • 답변은 로그인 후 가능합니다.

logo landscape small

사업자번호 : 743-81-02195
통신판매업 신고번호 : 제 2022-충북청주-1278 호
고객센터 : 카카오톡채널 @yagom