Commit 59cdac5b authored by MissYasiky's avatar MissYasiky
Browse files

添加云课堂 demo iOS 代码到项目中

parent d9eec957
//
// FTPageController.h
// FTPageController
//
// Created by ftao on 04/01/2018.
// Copyright © 2018 easefun. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol FTPageControllerDelegate;
/**
自定义分页控制器
*/
@interface FTPageController : UIViewController
@property (nonatomic, weak) id<FTPageControllerDelegate> delegate;
@property (nonatomic, assign, readonly) CGFloat barHeight;
@property (nonatomic, strong, readonly) NSMutableArray *titles;
@property (nonatomic, strong, readonly) NSMutableArray *controllers;
@property (nonatomic, strong, readonly) UIView *touchLineView;
@property (nonatomic, assign) BOOL circulation;
/**
通过标题及其控制器初始化分页控制器
@param titles 子控制器标题
@param controllers 子控制器
@return 分页控制
*/
- (instancetype)initWithTitles:(NSArray<NSString *> *)titles controllers:(NSArray<UIViewController *> *)controllers barHeight:(CGFloat)barHeight touchHeight:(CGFloat)touchHeight;
/**
新增页
@param title 页标题
@param controller 页控制器
*/
- (void)addPageWithTitle:(NSString *)title controller:(UIViewController *)controller;
/**
插入页在指定位置
@param title 页标题
@param controller 页控制器
@param index 位置(大于最大数量时,则插入至最后)
*/
- (void)insertPageWithTitle:(NSString *)title controller:(UIViewController *)controller atIndex:(NSUInteger)index;
/**
移除页控制器
@param index 位置
*/
- (void)removePageAtIndex:(NSUInteger)index;
/// 改变大小
- (void)changeFrame;
/// 是否圆角
- (void)cornerRadius:(BOOL)flag;
@end
@protocol FTPageControllerDelegate <NSObject>
- (BOOL)canMoveChatroom:(FTPageController *)pageController;
- (void)moveChatroom:(FTPageController *)pageController toPointY:(CGFloat)pointY;
- (void)moveChatroom:(FTPageController *)pageController;
@end
//
// FTPageController.m
// FTPageController
//
// Created by ftao on 04/01/2018.
// Copyright © 2018 easefun. All rights reserved.
//
#import "FTPageController.h"
#import "FTTitleViewCell.h"
#define kWidth [UIScreen mainScreen].bounds.size.width
static NSString *TitleCellIdentifier = @"PageTitleCell";
@interface FTPageController () <UICollectionViewDataSource,UICollectionViewDelegateFlowLayout,UIPageViewControllerDataSource,UIPageViewControllerDelegate>
@property (nonatomic, assign) CGFloat barHeight;
@property (nonatomic, assign) CGFloat touchHeight;
@property (nonatomic, strong) UICollectionView *titleCollectionView;
@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSMutableArray *titles;
@property (nonatomic, strong) NSMutableArray *controllers;
@property (nonatomic, strong) UIBezierPath *basePath;
@property (nonatomic, strong) UIBezierPath *maskPath;
@property (nonatomic, strong) UIView *touchView;
@property (nonatomic, strong) UIView *touchLineView;
@property (nonatomic, strong) UIView *topLineView;
@property (nonatomic) NSUInteger nextIndex;
@property (nonatomic, assign) BOOL canMove;
@property (nonatomic, assign) CGPoint lastPoint;
@end
@implementation FTPageController {
CGFloat _titleItemWidth;
NSIndexPath *_selectedIndexPath;
}
#pragma mark - Initialize
- (instancetype)initWithTitles:(NSArray<NSString *> *)titles controllers:(NSArray<UIViewController *> *)controllers barHeight:(CGFloat)barHeight touchHeight:(CGFloat)touchHeight {
self = [super init];
if (self) {
self.barHeight = barHeight;
self.touchHeight = touchHeight;
_selectedIndexPath = [NSIndexPath indexPathForItem:0 inSection:0];
self.titles = [[NSMutableArray alloc] initWithArray:titles];
self.controllers = [[NSMutableArray alloc] initWithArray:controllers];
[self setupTitles];
[self setupPageController];
[self.view bringSubviewToFront:self.topLineView];
}
return self;
}
- (void)changeFrame {
self.pageViewController.view.frame = CGRectMake(0, self.barHeight, kWidth, CGRectGetHeight(self.view.bounds) - self.barHeight);
}
-(void)setupPageController {
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.view.frame = CGRectMake(0, self.barHeight, kWidth, CGRectGetHeight(self.view.bounds) - self.barHeight);
self.pageViewController.dataSource = self;
self.pageViewController.delegate =self;
NSArray *initControllers = @[self.controllers[0]];
[self.pageViewController setViewControllers:initControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self.view addSubview:self.pageViewController.view];
[self addChildViewController:self.pageViewController];
self.pageViewController.view.clipsToBounds = NO;
for (UIView *subview in self.pageViewController.view.subviews) {
subview.clipsToBounds = NO;
}
}
-(void)setupTitles {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.titleCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, self.touchHeight - 1.0, kWidth, self.barHeight - self.touchHeight) collectionViewLayout:layout];
self.titleCollectionView.backgroundColor = [UIColor whiteColor];
self.titleCollectionView.dataSource = self;
self.titleCollectionView.delegate = self;
self.titleCollectionView.allowsSelection = YES;
[self.view addSubview:self.titleCollectionView];
self.titleCollectionView.showsVerticalScrollIndicator = NO;
self.titleCollectionView.showsHorizontalScrollIndicator = NO;
[self.titleCollectionView registerClass:[FTTitleViewCell class] forCellWithReuseIdentifier:TitleCellIdentifier];
if (self.touchHeight > 0.0) {
[self addTouchView];
}
}
- (void)addTouchView {
self.touchView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, self.touchHeight)];
self.touchView.backgroundColor = [UIColor whiteColor];
self.touchView.layer.mask = [[CAShapeLayer alloc] init];
self.touchView.layer.mask.frame = self.touchView.bounds;
[self.view addSubview:self.touchView];
self.basePath = [UIBezierPath bezierPathWithRect:self.touchView.bounds];
self.maskPath = [UIBezierPath bezierPathWithRoundedRect:self.touchView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(8.0, 8.0)];
self.touchLineView = [[UIView alloc] initWithFrame:CGRectMake((self.touchView.bounds.size.width - 50.0) * 0.5, 5.0, 50.0, 5.0)];
self.touchLineView.backgroundColor = [UIColor colorWithWhite:234.0 / 255.0 alpha:1.0];
self.touchLineView.layer.cornerRadius = 2.5;
[self.touchView addSubview:self.touchLineView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];
[self.touchView addGestureRecognizer:tap];
self.lastPoint = self.view.bounds.origin;
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestureRecognizer:)];
[self.touchView addGestureRecognizer:panGestureRecognizer];
}
- (void)cornerRadius:(BOOL)flag {
if (flag) {
((CAShapeLayer *)self.touchView.layer.mask).path = self.maskPath.CGPath;
} else {
((CAShapeLayer *)self.touchView.layer.mask).path = self.basePath.CGPath;
}
}
- (void)tapAction {
if (self.delegate && [self.delegate respondsToSelector:@selector(moveChatroom:)]) {
[self.delegate moveChatroom:self];
}
}
#pragma mark - gesture
- (void)handlePanGestureRecognizer:(UIPanGestureRecognizer*)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.view.superview];
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
if (self.delegate && [self.delegate respondsToSelector:@selector(canMoveChatroom:)]) {
self.canMove = [self.delegate canMoveChatroom:self];
}
} else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) {
if (self.canMove && self.delegate && [self.delegate respondsToSelector:@selector(moveChatroom:toPointY:)]) {
[self.delegate moveChatroom:self toPointY:p.y - self.lastPoint.y];
}
} else {
if (self.canMove) {
self.canMove = NO;
[self tapAction];
}
}
self.lastPoint = p;
}
#pragma mark - Public methods
- (void)addPageWithTitle:(NSString *)title controller:(UIViewController *)controller {
if (title && controller) {
[self.titles addObject:title];
[self.controllers addObject:controller];
[self.titleCollectionView reloadData];
}
}
- (void)insertPageWithTitle:(NSString *)title controller:(UIViewController *)controller atIndex:(NSUInteger)index {
if (title && controller) {
if (index > self.titles.count) {
index = self.titles.count;
}
[self.titles insertObject:title atIndex:index];
[self.controllers insertObject:controller atIndex:index];
[self.titleCollectionView reloadData];
}
}
- (void)removePageAtIndex:(NSUInteger)index {
if (index < self.titles.count) {
[self.titles removeObjectAtIndex:index];
[self.controllers removeObjectAtIndex:index];
[self.titleCollectionView reloadData];
}
}
#pragma mark - Life Cycle
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor colorWithWhite:31.0 / 255.0 alpha:1.0];
self.topLineView = [[UIView alloc] initWithFrame:CGRectMake(0, self.barHeight - 1, kWidth, 1)];
self.topLineView.backgroundColor = [UIColor colorWithRed:243.0/255.0 green:243.0/255.0 blue:244.0/255.0 alpha:1.0];
[self.view addSubview:self.topLineView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - <UICollectionViewDataSource>
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.titles.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FTTitleViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:TitleCellIdentifier forIndexPath:indexPath];
cell.titleLabel.text = self.titles[indexPath.item];
[cell setClicked:[indexPath compare:_selectedIndexPath]==NSOrderedSame];
return cell;
}
#pragma mark - <UICollectionViewLayout>
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
NSString *text = self.titles[indexPath.item];
CGFloat width = [text sizeWithAttributes:@{NSFontAttributeName : [UIFont systemFontOfSize:16.0]}].width;
return CGSizeMake(width + 32.0, CGRectGetHeight(collectionView.bounds));
}
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
}
#pragma mark - <UICollectionViewDeleaget>
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath compare:_selectedIndexPath] == NSOrderedSame) {
return;
}
_selectedIndexPath = indexPath;
[collectionView reloadData];
FTTitleViewCell *cell = (FTTitleViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
[cell setClicked:YES];
// 跳转到指定页面
NSArray *showController = @[self.controllers[indexPath.item]];
[self.pageViewController setViewControllers:showController direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:^(BOOL finished) {
//NSLog(@"setViewControllers finished."); // first low
}];
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
FTTitleViewCell *cell = (FTTitleViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
[cell setClicked:NO];
}
#pragma mark - <UIPageViewControllerDataSource>
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:viewController];
if (index == NSNotFound ) {
return nil;
}
if (index == 0 && self.circulation) {
return [self viewControllerAtIndex:(self.controllers.count-1)];
}
index --;
return [self viewControllerAtIndex:index];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:viewController];
if (index == NSNotFound ) {
return nil;
}
index ++;
if (index == self.controllers.count && self.circulation) {
return [self viewControllerAtIndex:0];
}
if (index > self.controllers.count) {
return nil;
}
return [self viewControllerAtIndex:index];
}
#pragma mark - <UIPageViewControllerDelegate>
-(void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
NSUInteger index = [self indexOfViewController:pendingViewControllers.firstObject];
self.nextIndex = index;
}
-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if (completed) {
NSUInteger index = [self indexOfViewController:previousViewControllers.firstObject];
[self deselectTitle:index];
[self selectedTitle:self.nextIndex];
}
}
#pragma mark - Private methods
// 选择标题(视图加载之后设置)
-(void)selectedTitle:(NSUInteger)index {
_selectedIndexPath = [NSIndexPath indexPathForItem:index inSection:0];
[self.titleCollectionView selectItemAtIndexPath:_selectedIndexPath animated:NO scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
FTTitleViewCell *cell = (FTTitleViewCell *)[self.titleCollectionView cellForItemAtIndexPath:_selectedIndexPath];
[cell setClicked:YES];
}
// 取消选择的标题
-(void)deselectTitle:(NSUInteger)index {
NSIndexPath *deselectedPath = [NSIndexPath indexPathForItem:index inSection:0];
[self.titleCollectionView deselectItemAtIndexPath:deselectedPath animated:NO];
FTTitleViewCell *cell = (FTTitleViewCell *)[self.titleCollectionView cellForItemAtIndexPath:deselectedPath];
[cell setClicked:NO];
}
-(UIViewController *)viewControllerAtIndex:(NSUInteger)index {
if (index == NSNotFound || index >=self.controllers.count ) {
return nil;
}
return self.controllers[index];
}
-(NSUInteger)indexOfViewController:(UIViewController *)viewController {
return [self.controllers indexOfObject:viewController];
}
@end
//
// FTTitleViewCell.h
// FTPageController
//
// Created by ftao on 04/01/2018.
// Copyright © 2018 easefun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FTTitleViewCell : UICollectionViewCell
@property (nonatomic, assign) BOOL clicked;
@property (strong, nonatomic) UILabel *titleLabel;
@property (strong, nonatomic) UIView *indicatorView;
@end
//
// FTTitleViewCell.m
// FTPageController
//
// Created by ftao on 04/01/2018.
// Copyright © 2018 easefun. All rights reserved.
//
#import "FTTitleViewCell.h"
@implementation FTTitleViewCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
CGFloat width = 100.0;
CGFloat height = 44.0;
self.frame = CGRectMake(frame.origin.x, frame.origin.y, width, height);
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, height)];
_titleLabel.textColor = [UIColor darkGrayColor];
_titleLabel.font = [UIFont systemFontOfSize:16];
_titleLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_titleLabel];
_indicatorView = [[UIView alloc] initWithFrame:CGRectMake(34, 41, 32, 3)];
_indicatorView.backgroundColor = [UIColor colorWithRed:0x21/255.0 green:0x96/255.0 blue:0xf3/255.0 alpha:1.0];
[self addSubview:_indicatorView];
_indicatorView.hidden = YES;
}
return self;
}
- (void)setClicked:(BOOL)clicked {
_clicked = clicked;
_indicatorView.hidden = !clicked;
_titleLabel.textColor = clicked ? [UIColor colorWithRed:33/255.0 green:150/255.0 blue:243/255.0 alpha:1.0] : [UIColor darkGrayColor];
}
@end
Copyright (c) 2011-2017 Charles Powell
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
\ No newline at end of file
Overview
============
MarqueeLabel is a UILabel subclass adds a scrolling marquee effect when the text of the label outgrows the available width. The label scrolling direction and speed/rate can be specified as well. All standard UILabel properties (where it makes sense) are available in MarqueeLabel, with the intent of MarqueeLabel behaving just like a UILabel.
MarqueeLabel is compatible with both iOS and tvOS, and currently works with Swift 3.0 and the iOS 10.0 SDK! (But if you're looking for Swift 2.x compatibility, [you can use release 2.8](https://github.com/cbpowell/MarqueeLabel/releases/tag/2.8.0))
## Check it out!
![GIF of MarqueeLabelDemo in action](https://raw.githubusercontent.com/cbpowell/MarqueeLabel/master/Metadata/MarqueeLabelDemo.gif)
## How To Get Started
1. Clone MarqueeLabel from GitHub, and check out the demo project.
2. Read the [MarqueeLabel CocoaDocs documentation](http://cocoadocs.org/docsets/MarqueeLabel/).
3. Take a look at the [special notes](https://github.com/cbpowell/MarqueeLabel/blob/master/README.mdown#special-notes) section to be aware of any gotchas.
4. Drop in MarqueeLabel as a replacement to your lengthy UILabels!
5. Help out with bug fixes and new features.
### Installation
#### [CocoaPods](http://cocoapods.org)
MarqueeLabel has [subspecs](https://guides.cocoapods.org/syntax/podspec.html#subspec) for both Objective-C and Swift! Currently, Objective-C is the default subspec.
That means to use MarqueeLabel in an Objective-C project, add the following to your project's Podfile:
```ruby
pod 'MarqueeLabel'
```
But if you're using Swift, add the following instead to specify the Swift subspec:
```ruby
pod 'MarqueeLabel/Swift'
```
#### Carthage
Add the following to your project's Cartfile:
```ruby
github "cbpowell/MarqueeLabel"
```
#### Manual Installation
1. Add MarqueeLabel.h and MarqueeLabel.m, or MarqueeLabel.swift, to your project.
2. Add **QuartzCore.framework** to your project frameworks.
3. Import MarqueeLabel and replace your UILabels with MarqueeLabels as needed.
#### Using MarqueeLabel in your own Swift Framework?
See the [Special Note below](https://github.com/cbpowell/MarqueeLabel/blob/master/README.mdown#swiftframeworkusage) on supporting Cocoapods and Carthage simultaneously in a Swift framework!
## Usage
MarqueeLabel automatically scrolls its text, at either a defined rate (points per second) or over a duration (seconds), whenever the length of the label's text exceeds the space available given the label's frame.
There are several options for the Marquee type, and the default is `Continuous` (which looks just like what Apple typically uses). The animation curve of this scroll can be defined, and defaults to `UIViewAnimationOptionCurveLinear`.
There are also several optional features to help with your integration of the scrolling nature of MarqueeLabel:
- An optional edge fade at the left and right edges of the view, in order to fade the label text into the background rather than simply being clipped off
- Leading and trailing buffers to offset the label text inside its frame, giving you better control over alignment