UIScrollView에서 스크롤 방향을 찾으십니까?
나는 있습니다UIScrollView
가로 스크롤만 가능하며, 사용자가 스크롤하는 방향(왼쪽, 오른쪽)을 알고 싶습니다.제가 한 것은 하위 분류입니다.UIScrollView
그리고 그것을 무시합니다.touchesMoved
방법:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
float now = [touch locationInView:self].x;
float before = [touch previousLocationInView:self].x;
NSLog(@"%f %f", before, now);
if (now > before){
right = NO;
NSLog(@"LEFT");
}
else{
right = YES;
NSLog(@"RIGHT");
}
}
그런데 이사를 할 때 이 방법이 아예 불리지 않는 경우가 있습니다.당신은 어떻게 생각하나요?
방향을 결정하는 것은 매우 간단하지만, 제스처를 취하는 동안 방향이 여러 번 바뀔 수 있다는 것을 명심하십시오.예를 들어, 페이징이 설정된 상태에서 스크롤 보기를 사용할 경우 사용자가 다음 페이지로 이동하기 위해 스와이프하면 초기 방향이 오른쪽으로 이동할 수 있지만, 바운스가 설정된 경우에는 잠시 방향이 없거나 왼쪽으로 이동합니다.
방향을 결정하려면 다음을 사용해야 합니다.UIScrollView scrollViewDidScroll
위임하다이 샘플에서 다음과 같은 이름의 변수를 만들었습니다.lastContentOffset
현재 콘텐츠 오프셋을 이전 콘텐츠 오프셋과 비교하는 데 사용합니다.더 크면 스크롤 보기가 오른쪽으로 스크롤됩니다.왼쪽으로 .
// somewhere in the private class extension
@property (nonatomic, assign) CGFloat lastContentOffset;
// somewhere in the class implementation
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
ScrollDirection scrollDirection;
if (self.lastContentOffset > scrollView.contentOffset.x) {
scrollDirection = ScrollDirectionRight;
} else if (self.lastContentOffset < scrollView.contentOffset.x) {
scrollDirection = ScrollDirectionLeft;
}
self.lastContentOffset = scrollView.contentOffset.x;
// do whatever you need to with scrollDirection here.
}
다음 열거형을 사용하여 방향을 정의합니다.첫 번째 값을 ScrollDirectionNone으로 설정하면 변수를 초기화할 때 해당 방향을 기본값으로 설정할 수 있습니다.
typedef NS_ENUM(NSInteger, ScrollDirection) {
ScrollDirectionNone,
ScrollDirectionRight,
ScrollDirectionLeft,
ScrollDirectionUp,
ScrollDirectionDown,
ScrollDirectionCrazy,
};
...사용자가 스크롤하는 방향(왼쪽, 오른쪽)을 알고 싶습니다.
5에서는 iOS 5를 합니다.UIScrollViewDelegate
사용자의 이동 제스처 방향을 결정합니다.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if ([scrollView.panGestureRecognizer translationInView:scrollView.superview].x > 0) {
// handle dragging to the right
} else {
// handle dragging to the left
}
}
용사를 합니다.scrollViewDidScroll:
현재 방향을 찾을 수 있는 좋은 방법입니다.
사용자가 스크롤을 마친 후 방향을 알려면 다음을 사용합니다.
@property (nonatomic) CGFloat lastContentOffset;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
self.lastContentOffset = scrollView.contentOffset.x;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (self.lastContentOffset > scrollView.contentOffset.x) {
// moved right if last content offset is greater then current offset
} else if (self.lastContentOffset < scrollView.contentOffset.x) {
// moved left if last content offset is less that current offset
} else {
// didn't move
}
}
이를 추적하기 위해 변수를 추가할 필요가 없습니다.사용하기만 하면 됩니다.UIScrollView
의panGestureRecognizer
0이 아닌 합니다.
CGFloat yVelocity = [scrollView.panGestureRecognizer velocityInView:scrollView].y;
if (yVelocity < 0) {
NSLog(@"Up");
} else if (yVelocity > 0) {
NSLog(@"Down");
} else {
NSLog(@"Can't determine direction as velocity is 0");
}
x 성분과 y 성분의 조합을 사용하여 위, 아래, 왼쪽 및 오른쪽을 탐지할 수 있습니다.
해결책
func scrollViewDidScroll(scrollView: UIScrollView) {
if(scrollView.panGestureRecognizer.translationInView(scrollView.superview).y > 0)
{
print("up")
}
else
{
print("down")
}
}
스위프트 4:
수평 스크롤의 경우 다음 작업을 간단히 수행할 수 있습니다.
if scrollView.panGestureRecognizer.translation(in: scrollView.superview).x > 0 {
print("left")
} else {
print("right")
}
수직 스크롤 변경의 경우.x
와 함께.y
iOS8 Swift에서 저는 다음 방법을 사용했습니다.
override func scrollViewDidScroll(scrollView: UIScrollView){
var frame: CGRect = self.photoButton.frame
var currentLocation = scrollView.contentOffset.y
if frame.origin.y > currentLocation{
println("Going up!")
}else if frame.origin.y < currentLocation{
println("Going down!")
}
frame.origin.y = scrollView.contentOffset.y + scrollHeight
photoButton.frame = frame
view.bringSubviewToFront(photoButton)
}
사용자가 스크롤할 때 위치가 변경되는 동적 보기를 사용하여 보기가 화면의 동일한 위치에 유지된 것처럼 보일 수 있습니다.나는 또한 사용자가 언제 오르거나 내리는지 추적하고 있습니다.
다음은 다른 방법입니다.
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if targetContentOffset.memory.y < scrollView.contentOffset.y {
println("Going up!")
} else {
println("Going down!")
}
}
이것이 제게 도움이 되었습니다(목표-C).
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSString *direction = ([scrollView.panGestureRecognizer translationInView:scrollView.superview].y >0)?@"up":@"down";
NSLog(@"%@",direction);
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
CGPoint targetPoint = *targetContentOffset;
CGPoint currentPoint = scrollView.contentOffset;
if (targetPoint.y > currentPoint.y) {
NSLog(@"up");
}
else {
NSLog(@"down");
}
}
신속하게:
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
if scrollView.panGestureRecognizer.translation(in: scrollView).y < 0 {
print("down")
} else {
print("up")
}
}
스크롤 보기DidScroll에서도 이 작업을 수행할 수 있습니다.
또는 키 경로 "contentOffset"을 관찰할 수 있습니다.이 기능은 스크롤 보기의 대리자를 설정/변경할 수 없는 경우에 유용합니다.
[yourScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
관찰자를 추가한 후 다음 작업을 수행할 수 있습니다.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
CGFloat newOffset = [[change objectForKey:@"new"] CGPointValue].y;
CGFloat oldOffset = [[change objectForKey:@"old"] CGPointValue].y;
CGFloat diff = newOffset - oldOffset;
if (diff < 0 ) { //scrolling down
// do something
}
}
필요할 때 관찰자를 제거해야 합니다. 예를 들어 관찰자를 보기에 추가할 수 있습니다. 보기에 표시 및 제거할 수 있습니다. 사라질 것입니다.
여기 @followben 답변과 같은 동작에 대한 나의 해결책이 있지만, 느린 시작과 함께 손실이 없습니다(dy가 0일 때).
@property (assign, nonatomic) BOOL isFinding;
@property (assign, nonatomic) CGFloat previousOffset;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
self.isFinding = YES;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.isFinding) {
if (self.previousOffset == 0) {
self.previousOffset = self.tableView.contentOffset.y;
} else {
CGFloat diff = self.tableView.contentOffset.y - self.previousOffset;
if (diff != 0) {
self.previousOffset = 0;
self.isFinding = NO;
if (diff > 0) {
// moved up
} else {
// moved down
}
}
}
}
}
//Vertical detection
var lastVelocityYSign = 0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let currentVelocityY = scrollView.panGestureRecognizer.velocity(in: scrollView.superview).y
let currentVelocityYSign = Int(currentVelocityY).signum()
if currentVelocityYSign != lastVelocityYSign &&
currentVelocityYSign != 0 {
lastVelocityYSign = currentVelocityYSign
}
if lastVelocityYSign < 0 {
print("SCROLLING DOWN")
} else if lastVelocityYSign > 0 {
print("SCOLLING UP")
}
}
Mos6y의 답변 https://medium.com/ @Mos6yCanSwift/swift-ios-결정-스크롤-방향-d48a2327a004
스위프트 5
▁▁clean▁more보enum
세로 스크롤용입니다.
enum ScrollDirection {
case up, down
}
var scrollDirection: ScrollDirection? {
let yTranslation = scrollView.panGestureRecognizer.translation(in: scrollView.superview).y
if yTranslation > 0 {
return .up
} else if yTranslation < 0 {
return .down
} else {
return nil
}
}
사용.
switch scrollDirection {
case .up: print("up")
case .down: print("down")
default: print("no scroll")
}
답변 중 일부를 확인하고 UIScrollView 카테고리에서 모든 것을 한 방울씩 포장하여 AnswerBot 답변에 대해 자세히 설명했습니다."last Content Offset"은 대신 uiscrollview에 저장되며 호출만 하면 됩니다.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[scrollView setLastContentOffset:scrollView.contentOffset];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (scrollView.scrollDirectionX == ScrollDirectionRight) {
//Do something with your views etc
}
if (scrollView.scrollDirectionY == ScrollDirectionUp) {
//Do something with your views etc
}
}
https://github.com/tehjord/UIScrollViewScrollingDirection 의 소스 코드
Swift 2.2 단방향 및 다중방향을 손실 없이 추적하는 간단한 솔루션.
// Keep last location with parameter
var lastLocation:CGPoint = CGPointZero
// We are using only this function so, we can
// track each scroll without lose anyone
override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
let currentLocation = scrollView.contentOffset
// Add each direction string
var directionList:[String] = []
if lastLocation.x < currentLocation.x {
//print("right")
directionList.append("Right")
} else if lastLocation.x > currentLocation.x {
//print("left")
directionList.append("Left")
}
// there is no "else if" to track both vertical
// and horizontal direction
if lastLocation.y < currentLocation.y {
//print("up")
directionList.append("Up")
} else if lastLocation.y > currentLocation.y {
//print("down")
directionList.append("Down")
}
// scrolled to single direction
if directionList.count == 1 {
print("scrolled to \(directionList[0]) direction.")
} else if directionList.count > 0 { // scrolled to multiple direction
print("scrolled to \(directionList[0])-\(directionList[1]) direction.")
}
// Update last location after check current otherwise,
// values will be same
lastLocation = scrollView.contentOffset
}
저는 @memmons의 대답을 바탕으로 필터링을 하는 것을 선호합니다.
목표 C:
// in the private class extension
@property (nonatomic, assign) CGFloat lastContentOffset;
// in the class implementation
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (fabs(self.lastContentOffset - scrollView.contentOffset.x) > 20 ) {
self.lastContentOffset = scrollView.contentOffset.x;
}
if (self.lastContentOffset > scrollView.contentOffset.x) {
// Scroll Direction Left
// do what you need to with scrollDirection here.
} else {
// omitted
// if (self.lastContentOffset < scrollView.contentOffset.x)
// do what you need to with scrollDirection here.
// Scroll Direction Right
}
}
에 테트한 경우스에서 했을 때- (void)scrollViewDidScroll:(UIScrollView *)scrollView
:
NSLog(@"lastContentOffset: --- %f, scrollView.contentOffset.x : --- %f", self.lastContentOffset, scrollView.contentOffset.x);
self.lastContentOffset
값의 차이는 거의 0.5f입니다.
그건 필요 없다.
그리고 때로는 정확한 상태에서 처리할 때 방향을 잃을 수도 있습니다.(가끔 설명문을 건너뜁니다.)
예:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat viewWidth = scrollView.frame.size.width;
self.lastContentOffset = scrollView.contentOffset.x;
// Bad example , needs value filtering
NSInteger page = scrollView.contentOffset.x / viewWidth;
if (page == self.images.count + 1 && self.lastContentOffset < scrollView.contentOffset.x ){
// Scroll Direction Right
// do what you need to with scrollDirection here.
}
....
Swift 4에서:
var lastContentOffset: CGFloat = 0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (abs(lastContentOffset - scrollView.contentOffset.x) > 20 ) {
lastContentOffset = scrollView.contentOffset.x;
}
if (lastContentOffset > scrollView.contentOffset.x) {
// Scroll Direction Left
// do what you need to with scrollDirection here.
} else {
// omitted
// if (self.lastContentOffset < scrollView.contentOffset.x)
// do what you need to with scrollDirection here.
// Scroll Direction Right
}
}
페이징이 켜져 있으면 이 코드를 사용할 수 있습니다.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
self.lastPage = self.currentPage;
CGFloat pageWidth = _mainScrollView.frame.size.width;
self.currentPage = floor((_mainScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
if (self.lastPage < self.currentPage) {
//go right
NSLog(@"right");
}else if(self.lastPage > self.currentPage){
//go left
NSLog(@"left");
}else if (self.lastPage == self.currentPage){
//same page
NSLog(@"same page");
}
}
코드 자체가 설명이 되는 것 같아요.CGFloat difference1 및 difference2가 동일한 클래스 전용 인터페이스에 선언되었습니다.contentSize가 동일하게 유지되면 좋습니다.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat contentOffSet = scrollView.contentOffset.y;
CGFloat contentHeight = scrollView.contentSize.height;
difference1 = contentHeight - contentOffSet;
if (difference1 > difference2) {
NSLog(@"Up");
}else{
NSLog(@"Down");
}
difference2 = contentHeight - contentOffSet;
}
이 구현은 매우 효과적입니다.
@property (nonatomic, assign) CGPoint lastContentOffset;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
_lastContentOffset.x = scrollView.contentOffset.x;
_lastContentOffset.y = scrollView.contentOffset.y;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (_lastContentOffset.x < (int)scrollView.contentOffset.x) {
// moved right
NSLog(@"right");
}
else if (_lastContentOffset.x > (int)scrollView.contentOffset.x) {
// moved left
NSLog(@"left");
}else if (_lastContentOffset.y<(int)scrollView.contentOffset.y){
NSLog(@"up");
}else if (_lastContentOffset.y>(int)scrollView.contentOffset.y){
NSLog(@"down");
[self.txtText resignFirstResponder];
}
}
그러면 text가 실행됩니다. 드래그가 끝난 후 해제하려면 View(View to dismiss)
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
NSLog(@"px %f py %f",velocity.x,velocity.y);}
스크롤 뷰의 위임 방법을 사용합니다.
속도 좌표가 +ve이면 보기가 아래로 스크롤되고 -ve이면 보기가 위로 스크롤됩니다.마찬가지로 x 좌표를 사용하여 왼쪽 및 오른쪽 스크롤을 감지할 수 있습니다.
속도 값이 0보다 크면 왼쪽으로 스크롤하고 오른쪽으로 스크롤하는 것이 Short & Easy입니다.
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
var targetOffset = Float(targetContentOffset.memory.x)
println("TargetOffset: \(targetOffset)")
println(velocity)
if velocity.x < 0 {
scrollDirection = -1 //scrolling left
} else {
scrollDirection = 1 //scrolling right
}
}
UIScrollView 및 UIPageControl로 작업하는 경우, 이 방법은 PageControl의 페이지 보기도 변경합니다.
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let targetOffset = targetContentOffset.memory.x
let widthPerPage = scrollView.contentSize.width / CGFloat(pageControl.numberOfPages)
let currentPage = targetOffset / widthPerPage
pageControl.currentPage = Int(currentPage)
}
@Esq의 Swift 코드 감사합니다.
모든 상위 답변에서 문제를 해결하는 두 가지 주요 방법은 다음과 같습니다.panGestureRecognizer
또는contentOffset
두 방법 모두 장단점이 있습니다.
방법 1: 팬 제스처 인식기
사용할 때panGestureRecognizer
@followben이 제안한 것처럼 스크롤 보기를 프로그래밍 방식으로 스크롤하지 않으려면 제대로 작동합니다.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if ([scrollView.panGestureRecognizer translationInView:scrollView.superview].x > 0) {
// handle dragging to the right
} else {
// handle dragging to the left
}
}
단점
그러나 다음 코드로 스크롤 보기를 이동하면 상위 코드가 인식할 수 없습니다.
setContentOffset(CGPoint(x: 100, y: 0), animation: false)
방법 2: 내용 오프셋
var lastContentOffset: CGPoint = CGPoint.zero
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (self.lastContentOffset.x > scrollView.contentOffset.x) {
// scroll to right
} else if self.lastContentOffset.x < scrollView.contentOffset.x {
// scroll to left
}
self.lastContentOffset = self.scrollView.contentOffset
}
단점
무한 스크롤을 만들 때와 같이 스크롤하는 동안 프로그래밍 방식으로 contentOffset을 변경하려는 경우 변경할 수 있으므로 이 방법이 문제가 됩니다.contentOffset
내용 보기 위치를 변경하는 동안 오른쪽 또는 왼쪽으로 스크롤하는 상위 코드가 점프합니다.
언급URL : https://stackoverflow.com/questions/2543670/finding-the-direction-of-scrolling-in-a-uiscrollview
'programing' 카테고리의 다른 글
Django REST Framework에서 CORS를 활성화하려면 어떻게 해야 합니까? (0) | 2023.07.06 |
---|---|
Oracle에서 삭제 및 삭제 간의 차이 (0) | 2023.07.06 |
요소가 특정 값 VBA인 경우 배열에서 요소 삭제 (0) | 2023.07.06 |
특정 요소 또는 선택기에 대해서만 CSS 스타일을 재설정/제거하는 방법 (0) | 2023.07.06 |
SQL Server 2012에서 SQL Server 2014의 백업을 복원할 수 있습니까? (0) | 2023.07.06 |