模仿UC新闻标签编辑功能

备注:博文只贴出关键代码,其中涉及到自定义控件、数据model可以忽略。博友使用过程中可以直接用button等替换掉报错的代码即可。

************************************ h 文件  ************************************

#import <UIKit/UIKit.h>

#import "DragButton.h"

/**

*  非编辑状态,点击顶部标签回调到上一页数据

*

*  @param model 点击标签model

*/

typedef void(^DragButtonTapBlock) (DragButtonModel *model);

/**

*  标签的增、减、坐标变换等,回调新数组到上一页

*

*  @param newArray 新数组

*/

typedef void(^DragButtonSortBlock) (NSMutableArray *newArray);

@interface DragButtonSortView : UIScrollView

<UIScrollViewDelegate,

UIGestureRecognizerDelegate> {

NSMutableArray *_topDataArray ,*_bottomDataArray;     // 顶部 + 底部数据源

NSMutableArray *_topButtonArray ,*_bottomButtonArray; // 顶部 + 底部存放button数组

BOOL _dragDown;                                       // 向前(上)、向后(下)拖动

CGFloat _criticalValue;                               // 临界值---顶部button区域的最后一个button底部Y坐标

CGFloat _scrollY;                                     // scrollView 滚动的位置,支持自动滚动到顶部

NSInteger _touchOldIndex;                             // 与哪个button交汇,button所在数组的索引

CGPoint startPoint, originPoint;                      // 拖动相关变量

CGPoint _dragStart,_dragCurrent;                      // 长按begin的point + 持续拖动的point

CGFloat minY, maxY;                                   // 是不是在水平方向拖动(最小Y + 最大Y)

}

@property (nonatomic, copy) DragButtonTapBlock   tapBlock;   // 点击

@property (nonatomic, copy) DragButtonSortBlock  dragBlock;  // 拖动顺序变化

@property (nonatomic, strong) UILabel  *topLabel;

@property (nonatomic, strong) UIButton *editeButton;

@property (nonatomic, strong) UILabel  *bottomLabel;

@property (nonatomic, strong) UIButton *allButton;

/**

*  初始化

*

*  @param frame          frame

*  @param dragArray      可排序的数组

*  @param normalArray    底部推荐区域的数组

*  @param tBlock         可排序的自定义view正常状态下点击回调

*  @param dBlock         可排序的数组的任何变动回调

*

*  @return 对象

*/

- (instancetype)initWithFrame:(CGRect)frame

dragArray:(NSArray *)dragArray

normalArray:(NSArray *)normalArray

tapButton:(DragButtonTapBlock)tBlock

updateDragArray:(DragButtonSortBlock)dBlock;

@end

************************************ m 文件  ************************************

#import "DragButtonSortView.h"

static NSInteger const TopButtonTag    = 10000;

static NSInteger const BottomButtonTag = 20000;

static NSInteger const ButtonNumber    = 3; // 一行 3 个控件

@implementation DragButtonSortView

- (instancetype)initWithFrame:(CGRect)frame

dragArray:(NSArray *)dragArray

normalArray:(NSArray *)normalArray

tapButton:(DragButtonTapBlock)tBlock

updateDragArray:(DragButtonSortBlock)dBlock {

self = [super initWithFrame:frame];

if (self) {

self.backgroundColor = [UIColor whiteColor];

self.delegate = self;

_tapBlock   = tBlock;

_dragBlock  = dBlock;

_enterBlock = eBlock;

_topDataArray      = [[NSMutableArray alloc] init];

_bottomDataArray   = [[NSMutableArray alloc] init];

_topButtonArray    = [[NSMutableArray alloc] init];

_bottomButtonArray = [[NSMutableArray alloc] init];

if (dragArray) {

[_topDataArray addObjectsFromArray:dragArray];

}

if (normalArray) {

[_bottomDataArray addObjectsFromArray:normalArray];

}

[self addSubview:self.topLabel];

[self addSubview:self.editeButton];

[self addSubview:self.bottomLabel];

[self addSubview:self.allButton];

[self loadTopDragButton:dragArray];

[self loadBottomNormalButton:normalArray];

self.contentOffset = CGPointMake(0, 0);

}

return self;

}

#pragma mark - 懒加载

- (UILabel *)topLabel {

if (!_topLabel) {

_topLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, SCREENWIDTH, 30)];

_topLabel.backgroundColor = [UIColor clearColor];

_topLabel.textColor = [UIColor grayColor];

_topLabel.textAlignment = NSTextAlignmentLeft;

_topLabel.font = [UIFont systemFontOfSize:15.0];

_topLabel.text = @"进入";

}

return _topLabel;

}

- (UIButton *)editeButton {

if (!_editeButton) {

_editeButton = [UIButton buttonWithType:UIButtonTypeSystem];

_editeButton.frame = CGRectMake(10, 0, SCREENWIDTH - 20, 30);

_editeButton.backgroundColor = [UIColor clearColor];

_editeButton.titleLabel.font = [UIFont systemFontOfSize:15.f];

_editeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;

[_editeButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

[_editeButton setTitle:@"编辑" forState:UIControlStateNormal];

[_editeButton setTitle:@"完成" forState:UIControlStateSelected];

[_editeButton addTarget:self action:@selector(editeButtonClick:) forControlEvents:UIControlEventTouchUpInside];

}

return _editeButton;

}

- (UILabel *)bottomLabel {

if (!_bottomLabel) {

_bottomLabel = [[UILabel alloc] initWithFrame:CGRectZero];

_bottomLabel.backgroundColor = [UIColor clearColor];

_bottomLabel.textColor = [UIColor grayColor];

_bottomLabel.textAlignment = NSTextAlignmentLeft;

_bottomLabel.font = [UIFont systemFontOfSize:15.0];

_bottomLabel.text = @" ";

}

return _bottomLabel;

}

- (UIButton *)allButton {

if (!_allButton) {

_allButton = [UIButton buttonWithType:UIButtonTypeSystem];

_allButton.frame = CGRectZero;

_allButton.backgroundColor = [UIColor clearColor];

_allButton.titleLabel.font = [UIFont systemFontOfSize:15.f];

_allButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;

[_allButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

[_allButton setTitle:@"更多>" forState:UIControlStateNormal];

[_allButton addTarget:self action:@selector(allButtonClick:) forControlEvents:UIControlEventTouchUpInside];

}

return _allButton;

}

- (void)loadTopDragButton:(NSArray *)array {

CGFloat topY = CGRectGetMaxY(self.topLabel.frame);

for (NSInteger i = 0; i < array.count; i++) {

DragButtonModel *model = array[i];

CGRect rect = [self getRectAtIndex:i topLocation:topY];

DragButton *button = [[DragButton alloc] initWithFrame:rect deleteImageViewHiden:YES dataSource:model];

button.tag = TopButtonTag + i;

button.exclusiveTouch = YES;

button.backgroundColor = RGBA(239, 239, 239, 1.0);

button.titleLabel.font = [UIFont systemFontOfSize:15.f];

[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

[button setTitle:model.name forState:UIControlStateNormal];

[button addTarget:self action:@selector(topButtonClick:) forControlEvents:UIControlEventTouchUpInside];

[self addSubview:button];

[self editeButtonGesture:button];

[_topButtonArray addObject:button];

if (i == array.count - 1) {

_criticalValue = CGRectGetMaxY(button.frame) + 20;

}

}

[self updateBottomLabelLocation];

}

- (void)loadBottomNormalButton:(NSArray *)array {

CGFloat tempHeight = 0;

CGFloat topY       = CGRectGetMaxY(self.bottomLabel.frame);

for (NSInteger i = 0; i < array.count; i++) {

DragButtonModel *model = array[i];

CGRect rect = [self getRectAtIndex:i topLocation:topY];

DragButton *button = [[DragButton alloc] initWithFrame:rect deleteImageViewHiden:YES dataSource:model];

button.tag = BottomButtonTag + i;

button.frame = rect;

button.exclusiveTouch = YES;

button.backgroundColor = RGBA(239, 239, 239, 1.0);

button.titleLabel.font = [UIFont systemFontOfSize:15.f];

[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

[button setTitle:model.name forState:UIControlStateNormal];

[button addTarget:self action:@selector(bottomButtonClick:) forControlEvents:UIControlEventTouchUpInside];

[self addSubview:button];

[_bottomButtonArray addObject:button];

tempHeight = CGRectGetMaxY(button.frame) + 10;

}

CGFloat totalHeight = (tempHeight > SCREENHEIGHT) ? tempHeight : SCREENHEIGHT + 10;

self.contentSize = CGSizeMake(self.frame.size.width, totalHeight);

}

#pragma mark - 基础功能

- (void)editeButtonClick:(UIButton *)button {

self.editeButton.selected = !self.editeButton.selected;

[self updateTopLabelTitle];

BOOL hidenDeleteButton = (self.editeButton.selected) ? NO : YES;

[self updateTopButtonDrag:hidenDeleteButton];

}

- (void)allButtonClick:(UIButton *)button {

if (self.enterBlock) {

self.enterBlock();

}

}

/**

*  顶部所有button的点击方法

*  1.如果当前为编辑(拖动)状态,并且顶部所有button个数大于4(至少保留4个,反之提示),点击后从_topDataArray + _topButtonArray移除相应数据源 + 当前点击的button,

并把当前点击的button + 对应数据源插入_bottomButtonArray + _bottomDataArray

*  2.数据处理完毕,执行移动到下面button区域动画。动画结束button移除之前绑定的事件,添加下部button的点击事件,移除绑定的长按事件,并回调新的顺序

*  3.如果当前为正常状态(不能拖动),点击回调当前button对应的数据源

*

*/

- (void)topButtonClick:(DragButton *)button {

if (_editeButton.selected) { // 编辑状态,可以拖动,此时点击要移动到底部button区域

if (_topButtonArray.count > 4) { // 至少保留 4 个

NSInteger index = [_topButtonArray indexOfObject:button];

BOOL lastOne = (index == _topButtonArray.count - 1) ? YES : NO;

DragButtonModel *model = _topDataArray[index];

[_topDataArray    removeObject:model];

[_bottomDataArray insertObject:model atIndex:0];

[_topButtonArray    removeObject:button];

[_bottomButtonArray insertObject:button atIndex:0];

[UIView animateWithDuration:0.3 animations:^{

[self removeFromTopIsLastOne:lastOne currentIndex:index];

} completion:^(BOOL finished) {

[button removeTarget:self action:@selector(topButtonClick:) forControlEvents:UIControlEventTouchUpInside];

[button addTarget:self action:@selector(bottomButtonClick:) forControlEvents:UIControlEventTouchUpInside];

[button deleteImageViewHiden:YES];

[self editeButtonGesture:button];

if (self.dragBlock) {

self.dragBlock(_topDataArray);

}

}];

} else {

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"至少保留 4 个标签"

message:nil

delegate:nil

cancelButtonTitle:@"返回"

otherButtonTitles: nil];

[alert show];

}

} else { // 数据回调

if (self.tapBlock) {

self.tapBlock(button.dataSourceModel);

}

}

}

/**

*  底部所有button的点击方法

*  1.移除当前点击button + 对应数据源,添加到顶部 _topButtonArray + _topDataArray 中

*  2.执行移动到顶部的动画,如果此时顶部 _topButtonArray 中最后一个button独自占一行,那么要相应调整底部lable的位置 + 底部_bottomButtonArray 要重新排序,

*  3.动画结束,移除底部button当前绑定的点击事件,添加顶部button的点击事件.此时如果是编辑(拖动)状态,那么当前点击的这个button就要显示删除按钮,反之不显示。

并且要绑定长按事件,回调新的顺序

*

*/

- (void)bottomButtonClick:(DragButton *)button {

NSInteger index = [_bottomButtonArray indexOfObject:button];

DragButtonModel *model = _bottomDataArray[index];

[_topDataArray  addObject:model];

[_bottomDataArray removeObject:model];

[_topButtonArray addObject:button];

[_bottomButtonArray removeObject:button];

NSInteger percent = _topButtonArray.count % ButtonNumber;

BOOL update = (percent == 1) ? YES : NO;

CGFloat topY    = CGRectGetMaxY(self.topLabel.frame);

[UIView animateWithDuration:0.3 animations:^{

button.frame = [self getRectAtIndex:_topButtonArray.count - 1 topLocation:topY];

[self moveToTopFirst:update];

} completion:^(BOOL finished) {

[button removeTarget:self action:@selector(bottomButtonClick:) forControlEvents:UIControlEventTouchUpInside];

[button addTarget:self action:@selector(topButtonClick:) forControlEvents:UIControlEventTouchUpInside];

if (self.editeButton.selected) {

[button deleteImageViewHiden:NO];

}

[self editeButtonGesture:button];

if (self.dragBlock) {

self.dragBlock(_topDataArray);

}

}];

}

- (CGRect)getRectAtIndex:(NSInteger)index topLocation:(NSInteger)top {

CGFloat topY       = top; // 起始高度

CGFloat border     = 10;  // 控件间隙

CGFloat viewWidth  = (SCREENWIDTH - border * 4) / ButtonNumber; // 控件宽度

CGFloat viewHeight = 40; // 控件高度

CGFloat x   = (viewWidth + border)  * (index % ButtonNumber) + border;

CGFloat y   = (viewHeight + border) * (index / ButtonNumber) + border + topY;

return CGRectMake(x, y, viewWidth, viewHeight);

}

// 移除 + 绑定长按事件

- (void)editeButtonGesture:(DragButton *)button {

NSArray *gestures = button.gestureRecognizers;

if (gestures.count > 0) {

UILongPressGestureRecognizer *longGesture = gestures.firstObject;

longGesture.delegate = nil;

[button removeGestureRecognizer:longGesture];

} else {

UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];

[button addGestureRecognizer:longGesture];

longGesture.minimumPressDuration = 0.2;

longGesture.delegate = self;

}

}

- (void)updateTopLabelTitle {

self.topLabel.text = self.editeButton.selected ? @"拖动排序" : @"点击进入社区";

}

// 顶部 _topButtonArray 追加button(底部点击移动到顶部)

- (void)moveToTopFirst:(BOOL)firstOne {

CGFloat topY    = CGRectGetMaxY(self.topLabel.frame);

NSInteger index = _topButtonArray.count - 1;

DragButton *btn = _topButtonArray[index];

btn.frame = [self getRectAtIndex:index topLocation:topY];

if (firstOne) { // 点击下面button(topButtonArray.count % 3 == 1,每一行的第一个)

[self updateBottomLabelLocation];

}

[self updateBottomButtonLocation];

}

// 点击顶部button执行的动画:最后一个不需要重新排序,其他都要重新排序

- (void)removeFromTopIsLastOne:(BOOL)lastOne currentIndex:(NSInteger)index {

if (lastOne) {  // 点击上面button( 如果是最后一个_topButtonArray无需重新排序)

} else { // 如果不是最后一个 _topButtonArray 后续所有需要重新排序

CGFloat topY    = CGRectGetMaxY(self.topLabel.frame);

for (NSInteger i = index; i < _topButtonArray.count; i++) {

DragButton *btn = _topButtonArray[i];

btn.frame = [self getRectAtIndex:i topLocation:topY];

}

}

// 如果topButtonArray.count % 3 == 0(每一行的第三个button),那么要相应变动  底部label.frame  及  _bottomButtonArray 中的button.frame

NSInteger percent = _topButtonArray.count % ButtonNumber;

if (percent == 0) {

[self updateBottomLabelLocation];

}

[self updateBottomButtonLocation];

}

- (void)updateTopButtonDrag:(BOOL)drag {

for (NSInteger i = 0; i < _topButtonArray.count; i++) {

DragButton *button = _topButtonArray[i];

[button deleteImageViewHiden:drag];

}

}

- (void)updateBottomLabelLocation {

if (_topButtonArray.count > 0) {

DragButton *btn = _topButtonArray[_topButtonArray.count - 1];

_criticalValue = CGRectGetMaxY(btn.frame) + 20;

self.bottomLabel.frame = CGRectMake(10, _criticalValue,SCREENWIDTH - 20, 30);

self.allButton.frame   = CGRectMake(10, _criticalValue,SCREENWIDTH - 20, 30);

}

}

- (void)updateBottomButtonLocation {

CGFloat bottomY = CGRectGetMaxY(self.bottomLabel.frame);

for (NSInteger i = 0; i < _bottomButtonArray.count; i++) {

DragButton *btn = _bottomButtonArray[i];

btn.frame = [self getRectAtIndex:i topLocation:bottomY];

}

}

#pragma mark - UILongPressGestureRecognizer

/**

*  长按拖动详解 (核心代码)

*  UIGestureRecognizerStateBegan : 当前button执行放大+改变透明度的动画,并从 _topButtonArray + _topDataArray 移除,记录其最大、小Y坐标

*  UIGestureRecognizerStateChanged : button跟随手势移动

*  1.当前拖动Y坐标 < scrollview滑动的位移,此时scrollview滚动到顶部---看效果可知

*  2.当前拖动button与其他button交汇。

A情况 --- 水平移动,与同一行的button交汇,根据 X 坐标判断滑动方向,并执行动画

B情况 --- 垂直(上下)移动,与其他button交汇,根据 Y 坐标判断滑动方向,并执行动画,及时更新当前行的最大 + 小 Y 坐标

*  UIGestureRecognizerStateEnded :当前拖动button还原frame并透明度改为1,插入到指定位置并插入对应数据源,回调最新顺序

*

*/

- (void)longPress:(UILongPressGestureRecognizer *)gesture {

DragButton *button = (DragButton *)gesture.view;

DragButtonModel   *model  = button.dataSourceModel;

BOOL contains = NO;

switch (gesture.state) {

case UIGestureRecognizerStateBegan:

{

// 长按开始拖动

if (!self.editeButton.selected) {

[self updateTopButtonDrag:NO];

self.editeButton.selected = !self.editeButton.selected;

[self updateTopLabelTitle];

}

[self bringSubviewToFront:button];

_touchOldIndex = [_topButtonArray indexOfObject:button];

startPoint  = [gesture locationInView:gesture.view];

originPoint = button.center;

_dragDown   = NO;

[UIView animateWithDuration:0.3 animations:^{

button.transform = CGAffineTransformMakeScale(1.2, 1.2);

button.alpha = 0.7;

}];

[_topButtonArray removeObject:button];

[_topDataArray   removeObject:model];

_dragStart  = [gesture locationInView:gesture.view];

minY = CGRectGetMinY(button.frame);

maxY = CGRectGetMaxY(button.frame);

}

break;

case UIGestureRecognizerStateChanged:

{

// button伴随移动

CGPoint currentPoint = [gesture locationInView:gesture.view];

CGFloat deltaX  = currentPoint.x - startPoint.x;

CGFloat deltaY  = currentPoint.y - startPoint.y;

button.center = CGPointMake(button.center.x + deltaX, button.center.y + deltaY);

// scrollview移动到顶部

if (button.center.y < _scrollY && button.center.y > 0) {

[self setContentOffset:CGPointMake(0, 0) animated:YES];

_scrollY = 0;

}

_dragCurrent = button.center;

// 执行动画逻辑

NSInteger index = [self locationChange:button.center moveButton:button];

if (index < 0) {

contains = NO;

_dragDown = NO;

} else {

contains = YES;

DragButton *insertBtn = _topButtonArray[index];

originPoint = insertBtn.center;

if (_dragCurrent.y < maxY && _dragCurrent.y > minY) {

NSLog(@"cccccc");

if (_dragCurrent.x < _dragStart.x) {

_dragDown = NO;

[UIView animateWithDuration:0.3 animations:^{

CGFloat topY = CGRectGetMaxY(self.topLabel.frame);

for (NSInteger i = index; i < _topButtonArray.count; i++) {

DragButton *btn = _topButtonArray[i];

btn.frame = [self getRectAtIndex:i + 1 topLocation:topY];

}

}];

} else {

_dragDown = YES;

[UIView animateWithDuration:0.3 animations:^{

CGFloat topY = CGRectGetMaxY(self.topLabel.frame);

for (NSInteger i = _touchOldIndex; i < index + 1; i++) {

if (_topDataArray.count > i) {

DragButton *btn = _topButtonArray[i];

btn.frame = [self getRectAtIndex:i topLocation:topY];

}

}

}];

}

} else {

if (_dragCurrent.y < _dragStart.y) { //  || _dragCurrent.x > _dragStart.x

minY = CGRectGetMinY(insertBtn.frame);

maxY = CGRectGetMaxY(insertBtn.frame);

_dragDown = NO;

NSLog(@"aaaaa");

[UIView animateWithDuration:0.3 animations:^{

CGFloat topY = CGRectGetMaxY(self.topLabel.frame);

for (NSInteger i = index; i < _topButtonArray.count; i++) {

DragButton *btn = _topButtonArray[i];

btn.frame = [self getRectAtIndex:i + 1 topLocation:topY];

}

}];

} else {

minY = CGRectGetMinY(insertBtn.frame);

maxY = CGRectGetMaxY(insertBtn.frame);

NSLog(@"bbbbbb");

_dragDown = YES;

[UIView animateWithDuration:0.3 animations:^{

CGFloat topY = CGRectGetMaxY(self.topLabel.frame);

for (NSInteger i = _touchOldIndex; i < index + 1; i++) {

if (_topDataArray.count > i) {

DragButton *btn = _topButtonArray[i];

btn.frame = [self getRectAtIndex:i topLocation:topY];

}

}

}];

}

}

_touchOldIndex = index;

}

_dragStart = button.center;

}

break;

case UIGestureRecognizerStateEnded:

{

_dragStart  = CGPointZero;

[UIView animateWithDuration:0.3 animations:^{

button.transform = CGAffineTransformIdentity;

button.alpha = 1.0;

if (!contains) {

button.center = originPoint;

}

} completion:^(BOOL finished) {

if (!contains) {

NSInteger insertIndex = _dragDown ? _touchOldIndex + 1 : _touchOldIndex;

[_topButtonArray insertObject:button atIndex:insertIndex];

[_topDataArray   insertObject:model atIndex:insertIndex];

if (self.dragBlock) {

self.dragBlock(_topDataArray);

}

}

}];

}

break;

default:

break;

}

}

// 拖动point是否在button内

- (NSInteger)locationChange:(CGPoint)point moveButton:(DragButton *)btn {

NSInteger index = -1;

for (NSInteger i = 0; i < _topButtonArray.count; i++) {

DragButton *currentButton = _topButtonArray[i];

if (currentButton != btn) {

if (CGRectContainsPoint(currentButton.frame, point)) {

index = i;

}

}

}

return index;

}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{

return YES;

}

#pragma mark - UIScrollView

// scrollview的位移

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

_scrollY = scrollView.contentOffset.y;

}

@end

时间: 2024-10-12 03:22:12

模仿UC新闻标签编辑功能的相关文章

聚合类新闻客户端产品功能点详情分析

产品功能点 功能 今日头条 百度新闻 鲜果 ZAKER 媒体订阅 × √ ★ ★ 个性化内容推荐 ★ √ × × 个性化订阅(RSS) × × ★ × 视频新闻 × × × × 评论盖楼 √ √ √ √ 搜索新闻 √ ★ × × 离线下载 √ √ √ √ 地方新闻 √ √ × √ 一键分享 √ √ √ √ 收藏 √ √ √ × 推送 √ √ × √ 天气 × × × √ 夜间模式 √ √ √ √ 线上活动 ★ × × ★ 主题设置 × × × √ 感兴趣 √ √ × × 语音读文章 × × ×

聚合类新闻client产品功能点详情分析

产品功能点 功能 今日头条 百度新闻 鲜果 ZAKER 媒体订阅 × √ ★ ★ 个性化内容推荐 ★ √ × × 个性化订阅(RSS) × × ★ × 视频新闻 × × × × 评论盖楼 √ √ √ √ 搜索新闻 √ ★ × × 离线下载 √ √ √ √ 地方新闻 √ √ × √ 一键分享 √ √ √ √ 收藏 √ √ √ × 推送 √ √ × √ 天气 × × × √ 夜间模式 √ √ √ √ 线上活动 ★ × × ★ 主题设置 × × × √ 感兴趣 √ √ × × 语音读文章 × × ×

HTML5各种头部meta标签的功能

<!DOCTYPE html>  H5标准声明,使用 HTML5 doctype,不区分大小写 <head lang="en"> 标准的 lang 属性写法 <meta charset='utf-8′>    声明文档使用的字符编码 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1″/>   优先使用 IE 最新版本和 Chrome &l

HTML5 CSS3 诱人的实例 :模仿优酷视频截图功能

一般的视频网站对于用户上传的视频,在用户上传完成后,可以对播放的视频进行截图,然后作为视频的展示图.项目中也可以引入这样的功能给用户一种不错的体验,而不是让用户额外上传一张展示图. 效果图: 看起来还是很不错,下面我给大家分析下,极其核心代码很简单: _canvas = document.createElement("canvas"); _ctx = _canvas.getContext("2d"); _ctx.fillStyle = '#ffffff'; _ctx

基于TF-IDF的新闻标签提取

基于TF-IDF的新闻标签提取 1. 新闻标签 新闻标签是一条新闻的关键字,可以由编辑上传,或者通过机器提取.新闻标签的提取主要用于推荐系统中,所以,提取的准确性影响推荐系统的有效性.同时,对于将标签展示出来的新闻网站,标签的准确性也会影响用户体验. 2. 新闻标签提取算法 新闻首先是一段文本,新闻的标签首先是这一段文本的关键字.在文本关键字提取当中,TD-IDF是首先可以想到的算法.TF-IDF算法的优点是:简单快速,结果比较符合实际情况:缺点是,单纯以"词频"衡量一个词的重要性,不

Swift - 给表格添加编辑功能(删除,插入)

1,下面的样例是给表格UITableView添加编辑功能: (1)给表格添加长按功能,长按后表格进入编辑状态 (2)在编辑状态下,第一个分组处于删除状态,第二个分组处于插入状态 (3)点击删除图标,删除对应条目 (4)点击添加图标,插入一条新数据 2,效果图           3,代码如下 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 31 32 33 34 35 36 37 3

jQuery easyUI 1.3.2 删除编辑功能 行号混乱的bug

最近使用jQuery easyUI 1.3.2 开发.在记录行设置一操作列,包含删除和编辑功能,操作后不reload重载(不发送新的数据库查询请求).网上教程是在初始化数据的时候,将行号index传入,如下代码 formatter:function(value,row,index){ if (row.editing){ var s = '<a href="javascript:void(0);" class="savebtn" onclick="sa

Dynamics 365 for CRM: Sitemap站点图的可视化编辑功能

Dynamics 365 for CRM 提供了Sitemap站点图的可视化编辑功能 在之前的所有版本中,我们只能通过从系统中导出站点图的XML进行编辑后再导入(容易出错),或使用第三方的Sitemap编辑工具进行编辑(非常方便). 在Dynamics 365 for CRM 中原生地提供了站点图的可视化编辑功能,非常强大方便: 1.在默认解决方案或自定义解决方案的"客户端扩展"中,找到"站点地图"记录:如果没有则需要点击"添加现成",添加&qu

c# 框架学习(nop )总结-------编辑功能

一.在js中配置列: <script> $(document).ready(function () { $("#enterprise-grid").kendoGrid({ dataSource: { type: "json", transport: { read: { url: "@Html.Raw(Url.Action("List", "Individual"))", type: "