首页 技术 正文
技术 2022年11月14日
0 收藏 843 点赞 4,313 浏览 4436 个字

基本数据采集

经过体验,手机QQ采用的应该是线性动画,即视图缩放比例等随手指在屏幕上滑动的距离以一次方程的形式变化。

提取基本数据,向右侧滑达到最大幅度时:

<img src="https://www.shuzhiduo.com/A/1O5EN0V4d7/

1、   右侧主视图左边界距离屏幕左边界的距离占屏幕宽度的比例为:78%

2、   右侧主视图的高度占屏幕高度的比例为:77%

分步实现:

1、实现主视图的缩放侧滑;

2、实现主视图与左视图的联动;

第一步,实现主视图的缩放侧滑

此前动手做时参考了一些类似的demo,发现许多是用手势UIPanGestureRecognizer来实现的,而本文将采用UITouch。并使用以下两个触摸触发事件:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

原理:

主视图mainVC的移动和缩放:

①. 主视图frmae的x坐标 = 主视图frmae的x坐标 + 手指滑动的x轴总偏移量偏移量;

#pragma mark - 手指在屏幕上移动
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{ if ([event touchesForView:_mainVC.view]) { // 获取UITouch对象
UITouch *touch = [touches anyObject]; // 获取当前点
CGPoint currentPoint = [touch locationInView:self.view]; // 获取上一个点
CGPoint prePoint = [touch previousLocationInView:self.view]; // x轴偏移量:当手指移动一点的时候,x偏移多少
CGFloat offsetX = currentPoint.x - prePoint.x; // 设置当前主视图的frame
_mainVC.view.frame = [self getCurrentFrameWithOffsetX:offsetX]; // 移动渐变效果 (明 - 暗)
_blackCover.alpha = (1 - _mainVC.view.frame.origin.x / RTarget); } // 判断是拖拽 还是 点击tap
_isDraging = YES;
}

②. 主视图的缩放比例 :

// 当手指偏移一点,根据X轴的偏移量算出当前主视图的frame
- (CGRect)getCurrentFrameWithOffsetX:(CGFloat)offsetX
{ // 获取y轴偏移量,手指每移动一点,y轴偏移多少
CGFloat offsetY = offsetX * _maxOffestHight / screenWidth; // 每次移动缩小比例
CGFloat scale = (screenHeight - 2 * offsetY) / screenHeight;#if 0
if (offsetX < 0 && _mainVC.view.frame.origin.x <= 0)
{ // 往左边滑动
scale = (screenH + 2 * offsetY) / screenH; }
#endif // 获取之前的frame *************** 限制成只能显示左视图!
CGRect frame = _mainVC.view.frame; if ((frame.origin.x+offsetX) >=0 )
frame.origin.x += offsetX;
else
frame.origin.x = 0; frame.size.height = frame.size.height *scale;
frame.size.width = frame.size.width *scale;
frame.origin.y = (screenHeight - frame.size.height) / 2.0; return frame;
}

/**  当手指偏移一点,根据X轴的偏移量算出当前主视图的frame **/

// 获取y轴偏移量,手指每移动一点,y轴偏移多少

CGFloat offsetY = offsetX * _maxOffestHight / screenWidth;

// 每次移动缩小比例

CGFloat scale = (screenHeight – 2 * offsetY) / screenHeight;

CGRect frame = _mainVC.view.frame;

… …

/** 主视图的位置变化 和 大小缩放 **/

frame.origin.x += offsetX;

frame.size.height = frame.size.height *scale;

frame.size.width = frame.size.width *scale;

frame.origin.y = (screenHeight – frame.size.height) / 2.0;

… …

第二步,实现主视图与左视图的联动

原理:

重点是找出线性关系,然后联动可以这样做 :

1、这是leftVC.view的缩放比例:

找出这两点 (0.77 ,0) (1 ,screenwidth
* 0.78),即(left.view的缩放比例, main.view.x坐标),可得线性关系:

CGFloat leftScale = ((1 - _minSclae)/(screenWidth * _boundScale))*_mainVC.view.frame.origin.x + _minSclae;
leftCX = _mainVC.view.frame.origin.x >= screenWidth * _boundScale ? self.view.center.x : leftCX;

2、这是leftVC.view的移动:

找出这两点(self.view.center.x ,
screenwidth * 0.78) (center – 80 , 0),即(屏幕中心点x的坐标 ,main.view.or.x坐标),可得线性关系:

    CGFloat leftCX = ( _leftCenterFactor / (screenWidth * _boundScale) )*_mainVC.view.frame.origin.x + screenWidth/2 - _leftCenterFactor;    leftScale = leftScale >= 1 ? 1 :leftScale;

3、最后移动和缩放:

_leftVC.view.center = CGPointMake(leftCX, self.view.center.y);    _leftVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, leftScale, leftScale);

完整代码:

/**
* 开启左视图联动事件
*/
- (void)startedLeftViewLinkage
{
// 执行左视图联动动画 // (self.view.center.x , screenwidth * 0.78) (center - 80 , 0) ==> (中心点x的坐标 ,main.view.or.x坐标),线性关系
CGFloat leftCX = ( _leftCenterFactor / (screenWidth * _boundScale) )*_mainVC.view.frame.origin.x + screenWidth/2 - _leftCenterFactor;
leftCX = _mainVC.view.frame.origin.x >= screenWidth * _boundScale ? self.view.center.x : leftCX; // (0.77 , 0) (1 , screenwidth*0.78) ==》 (left.view的缩放比例, main.view.or.x坐标),线性关系
CGFloat leftScale = ((1 - _minSclae)/(screenWidth * _boundScale))*_mainVC.view.frame.origin.x + _minSclae;
leftScale = leftScale >= 1 ? 1 :leftScale; _leftVC.view.center = CGPointMake(leftCX, self.view.center.y);
_leftVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, leftScale, leftScale);
}

最后,松开手指事件:

#pragma mark - 停止移动- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([event touchesForView:_mainVC.view]) { // 点击tap事件 复位满屏
if (_isDraging == NO && _mainVC.view.frame.origin.x != 0) { [UIView animateWithDuration:0.25 animations:^{ _mainVC.view.frame = self.view.bounds;
}];
} CGFloat target = 0; if (_mainVC.view.frame.origin.x > screenWidth / 3) { // 定位到右边
target = RTarget; }else if (CGRectGetMaxX(_mainVC.view.frame) < screenWidth / 3) { // 定位到左边
target = LTarget; } // 停止拖拽时判断是显示左视图还是主视图
[UIView animateWithDuration:0.25 animations:^{ if (target) { // 在需要定位左边或者右边 // 获取x轴偏移量
CGFloat offsetX = target - _mainVC.view.frame.origin.x; // 设置当前主视图的frame
_mainVC.view.frame = [self getCurrentFrameWithOffsetX:offsetX];
_blackCover.alpha = (1 - _mainVC.view.frame.origin.x / RTarget); }else{ // 还原
_mainVC.view.frame = self.view.bounds;
_blackCover.alpha = (1 - _mainVC.view.frame.origin.x / RTarget);
} // 开启左视图联动
[self startedLeftViewLinkage];
}];
} _isDraging = NO;
}

以上是对左视图和主视图的移动及缩放关系的解析,侧滑的关键就是找准视图之间的内在动态联系。按本文方法可达到高仿,实现的效果基本与手机QQ一样。

 

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,088
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,564
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,412
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,185
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,822
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,905