iOS 11和iPhoneX适配遇到坑

一.iPhone X尺寸问题 

1. 高度增加了145pt,变成812pt. 

2.屏幕圆角显示,注意至少留10pt边距。

3. 状态栏高度由20pt变成44pt,留意这个距离就能避开“刘海”的尴尬,相应的导航栏以上变化64--->88。 

4.底部工具栏需要为home indicator留出34pt边距。 5.物理分辨率为1125px * 2436px

非iPhone X :

StatusBar高20px,NavigationBar高44px,底部TabBar高49px

iPhone X:

StatusBar高44px,NavigationBar高44px,底部TabBar高83px


二.适配用到的宏

// status bar height.

#define  kStatusBarHeight      (IS_iPhoneX ? 44.f : 20.f)

// Navigation bar height.

#define  kNavigationBarHeight  44.f

// Tabbar height.

#define  kTabbarHeight        (IS_iPhoneX ? (49.f+34.f) : 49.f)

// Tabbar safe bottom margin.

#define  kTabbarSafeBottomMargin        (IS_iPhoneX ? 34.f : 0.f)

// Status bar & navigation bar height.

#define  kStatusBarAndNavigationBarHeight  (IS_iPhoneX ? 88.f : 64.f)

//判断是否iPhone X

#define IS_iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)


三.APP启动样式适配,屏幕未充满

1.启动页屏幕未充满

APP在iPhone X上占满整个屏幕, 而是保持着原有的高度 在屏幕中心位置, 屏幕的顶部和底部都有黑边.


适配前


适配前首页

通过LaunchScreen.storyboard方式启动

如果使用的是Assets中的LaunchImage, 在增加了iPhone X尺寸的图片配置后.

LaunchScreen.storyboard方式不用多说, 这里说一下如何在LaunchImage中增加iPhone X尺寸的图片配置.

方法一:

准备一张尺寸:1125 * 2436的 3x启动图片, 移动到LaunchImage的Finder目录中, 并在LaunchImage中的Contents.json文件中增加 (注意Json格式):

{

"extent" : "full-screen",

"idiom" : "iphone",

"subtype" : "2436h",

"filename" : "图片名.png",

"minimum-system-version" : "11.0",

"orientation" : "portrait",

"scale" : "3x"

}


LaunchImage变化

方法二:


未勾选箭头指向Portraint



已勾选Portrait


图片拖进来效果


LaunchImage中的Contents.json文件


适配后启动图片占满整个屏幕

2.引导页iPhone X图片变形


适配前


适配后

由于iPhone X高度发生变化,图片铺满整个屏幕时候造成图片拉伸,现在需要UI切一个1125*2436的3x图片和以前做iPhone X机型判断1124*2001图片,并且对图片contentMode属性进行设置

if (IS_iPhoneX) {

coverImageNames = [NSArray arrayWithObjects:@"img_big_1_ipx.jpg", @"img_big_2_ipx.jpg",@"img_big_3_ipx.jpg", @"img_big_4_ipx.jpg",nil];

}else{

coverImageNames = [NSArray arrayWithObjects:@"img_big_1.jpg", @"img_big_2.jpg",@"img_big_3.jpg", @"img_big_4.jpg",nil];

}

imageView.clipsToBounds = YES;//超出区域裁剪

imageView.contentMode = UIViewContentModeScaleAspectFill;//图片等比例拉伸,会填充整个区域,但是会有一部分过大而超出整个区域

四:UITableview UICollectionView MJRefresh下拉刷新错乱

适配前首页

iOS11表格用MJRefresh框架下拉刷新的时候界面会闪,显示紊乱,

原因是iOS11弃用了automaticallyAdjustsScrollViewInsets属性,新增contentInsetAdjustmentBehavior来替代它

tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;

解决方法:MJRefresh作者已经针对iOS 11和iPhone X做了适配,把MJRefresh更新最新的版本

//声明tableView的位置 添加下面代码

if (@available(iOS 11.0, *)) {

_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;

_tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);

_tableView.scrollIndicatorInsets = _tableView.contentInset;

}

五.纯代码适配齐刘海

iPhone X导航栏由以前的固定64变成现在88,Statebar的高度由20变成44,增加24,项目中以前用导航栏64地方都进行是否iPhoneX判断,用到宏#define  kStatusBarAndNavigationBarHeight  (IS_iPhoneX ? 88.f : 64.f)

项目中导航栏自定义导航栏会遇到很多奇葩的问题如下图

导航栏

(1)在iPhone X中导航栏高度变成88,项目中自定义导航栏高度64,需要对导航栏高度进行判断

_navigationBar = [[MCCustomNavigationBar alloc]initWithFrame:CGRectMake(0, 0, SCREENW, 64) andType:CustomBarType_Home];

_navigationBar = [[MCCustomNavigationBar alloc]initWithFrame:CGRectMake(0, 0, SCREENW, kStatusBarAndNavigationBarHeight) andType:CustomBarType_Home];

(2)搜索框和左右两边按钮高度有问题,因为iPhone X中状态栏高度由20增加24变成44,所以搜索框和左右两边按钮高度在iPhone X上距顶部高度加上24高度,

#define itemTopOffset (IS_iPhoneX ? (26+24) : 26)

[self.leftBtn mas_makeConstraints:^(MASConstraintMaker *make) {

make.left.offset(itemHorOffset);

make.height.equalTo(@(itemHeight));

make.width.equalTo(@(itemHeight));

make.top.offset(itemTopOffset);

}];

(3)iOS11上searchBar高度明显变大,

UITextField

UISearchBar改变搜索框的高度

系统的searchBar

UISearchBar的中子控件及其布局

UIView(直接子控件) frame 等于 searchBar的bounds,view的子控件及其布局

UISearchBarBackground(间接子控件) frame 等于searchBar的bounds

UISearchBarTextField(间接子控件) frame.origin等于(8.0, 6.0),即不等于searchBar的bounds

改变searchBar的frame只会影响其中搜索框的宽度,不会影响其高度,原因如下:

系统searchBar中的UISearchBarTextField的高度默认固定为28

左右边距固定为8,上下边距是父控件view的高度减去28除以2

改变UISearchBar的高度

方案

重写UISearchBar的子类(MCSearchBar),重新布局UISearchBar子控件的布局

增加成员属性contentInset,控制UISearchBarTextField距离父控件的边距

若用户没有设置contentInset,则计算出默认的contentInset

若用户设置了contentInset,则根据最新的contentInset布局UISearchBarTextField

新建UISearchBar的子类,增加成员属性contentInset,用来调整UISearchBarTextField距离父控件的边距。contentInset的setter方法

#pragma mark - setter method

- (void)setContentInset:(UIEdgeInsets)contentInset {

_contentInset.top = contentInset.top;

_contentInset.bottom = contentInset.bottom;

_contentInset.left = contentInset.left;

_contentInset.right = contentInset.right;

self.isChangeFrame = YES;

[self layoutSubviews];

}

- (void)layoutSubviews {

[super layoutSubviews];

for (UIView *subView in self.subviews[0].subviews) {

if ([subView isKindOfClass:[UIImageView class]]) {

//移除UISearchBarBackground

[subView removeFromSuperview];

}

if ([subView isKindOfClass:[UITextField class]]) {

CGFloat height = self.bounds.size.height;

CGFloat width = self.bounds.size.width;

if (_isChangeFrame) {

//说明contentInset已经被赋值

// 根据contentInset改变UISearchBarTextField的布局

subView.frame = CGRectMake(_contentInset.left, _contentInset.top, width - 2 * _contentInset.left, height - 2 * _contentInset.top);

} else {

// contentSet未被赋值

// 设置UISearchBar中UISearchBarTextField的默认边距

CGFloat top = (height - 28.0) / 2.0;

CGFloat bottom = top;

CGFloat left = 8.0;

CGFloat right = left;

_contentInset = UIEdgeInsetsMake(top, left, bottom, right);

subView.frame = CGRectMake(_contentInset.left, _contentInset.top, width - 2 * _contentInset.left, height - 2 * _contentInset.top);

}

}

}

}

在项目中使用自定义的MCSearchBar,SearchBar的高度可以改变

(4)iOS11中UISearchBar没有居中居左显示,并且icon和placeholder间距太窄


图标居左显示

现在实现居中显示


图标和文字居中

@property(nonatomic,assign)CGFloatwidth;

//判断版本

if(@available(iOS11.0, *)){

UITextField *textField = [self.searchBar valueForKey:@"searchField"];

[textField sizeToFit];

//记录一下这个时候的宽度

_width= textField.frame.size.width;

[_searchBar setPositionAdjustment:UIOffsetMake((_searchBar.width-_width)/2.0,0)forSearchBarIcon:UISearchBarIconSearch];

}

然后在代理方法 searchBarTextDidBeginEditing:(UISearchBar*)searchBar 调整位置

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{

if (@available(iOS 11.0, *)) {

if(!_searchBar.text.length) {

[_searchBar setPositionAdjustment:UIOffsetMake(0,0)forSearchBarIcon:UISearchBarIconSearch];

}

}

}

结束的方法  searchBarTextDidEndEditing:(UISearchBar*)searchBar 判断是否有内容

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{

if (@available(iOS 11.0, *)) {

if(!_searchBar.text.length) {

[_searchBar setPositionAdjustment:UIOffsetMake((_searchBar.width-self.width)/2.0,0) forSearchBarIcon:UISearchBarIconSearch];

}

}

}

如果有占位文字后台返的,UITextField在搜索框默认文字大小17,可以根据文字个数和大小算出占位文字宽度,然后算出搜索图标的偏移量.


(5)搜索页面导航栏中搜索框距离返回按钮太近


适配前

self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, testView.width - (SCREENW > 320 ? 90: 100)*SCREEN_Proportion, testView.height)];

由于搜索框距离左边距离导致的,现在需要定义一个宏做判断

#define marginLeft (IS_iPhoneX ? 10 : 0)

self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(marginLeft, 0, testView.width - (SCREENW > 320 ? 90: 100)*SCREEN_Proportion, testView.height)];


适配后效果

六.纯代码适配底部工具栏

在iPhone X中底部工具栏需要为home indicator留出34pt边距,iPhone X以前机型TarBar高度49,iPhone X中Tarbar高度加上34变成83.由于项目中Tabbar是用自定义的,需要对Tabbar的高度做适配,用到宏#define kTabbarHeight (IS_iPhoneX ? (49.f+34.f) : 49.f)


TarBar适配前

适配前代码

_customBarView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREENH - 49,SCREENW, 49)];

适配后的代码_customBarView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREENH - kTabbarHeight,SCREENW, kTabbarHeight)];

图标和文字居中

图标和文字和其他机型相比偏下,现在需要对图标和文字高度进行调整,做iPhone X和非iPhone X机型适配


图标高度适配


适配后的TarBar

七.底部view出现问题

(1)购物车View适配,涉及页面商品详情页,搜索页面,购物车页面

购物车页面适配前


搜索页面


购物车view


#define kTabbarHeight (IS_iPhoneX ? (49.f+34.f) : 49.f)


适配后购物车View


其他页面点击购物车图标进入购物车页面


点击TarBar按钮进入购物车,购物车View被遮挡


适配前的代码

-(void)updateUIFrame

{

if (_fromType == ToShoppingTrolleyType_New_Other) {

[[MCNavigationLeftView shareManager] initWithTitle:nil andNavi:self andSEL:@selector(back)];

[[MCTabbarTool shareManager]hideTabbarView:NO];

self.view.frame = CGRectMake(0, 0, SCREENW, SCREENH-kStatusBarAndNavigationBarHeight-(IS_iPhoneX?34:0));

}else{

[[MCTabbarTool shareManager]showTabbarView:YES];

self.view.frame = CGRectMake(0, 0, SCREENW, SCREENH-kStatusBarAndNavigationBarHeight-kTabbarHeight);

}

self.cartBottomView.frame = CGRectMake(0, self.view.height-49, SCREENW, 49);

}

(2)自定义数字键盘适配


适配前TabBar图标进去购物车页面


适配后

适配底部用的一个宏#define  kTabbarSafeBottomMargin        (IS_iPhoneX ? 34.f : 0.f)用于计算距离屏幕顶部高度,如果iPhone X,留出距离屏幕底部34安全距离,控件不能显示34安全距离上

适配前代码


适配后代码

(3)筛选views适配


适配前


适配前collectionview


适配后collectionview

运行程序发现底部按钮高度偏高,如图所示,现在需要调整底部按钮距离屏幕顶部高度



底部按钮


适配后代码
适配后


(4)适配查看优惠券


适配前优惠券的详细信息


适配前


适配前代码


适配后代码


适配后优惠券详情

(5)适配填写订单


适配前


适配前底部view代码


适配后底部view代码


适配后

(6)Tabbar没有完全遮住


适配前遮罩部位没有遮住

为了遮住TabBar,在iPhone X上tabbar高度增加34,需要调整遮罩tabbar窗口的高度


适配前代码


适配后代码


适配后效果

八.继承自UIScrollView的视图偏移问题

我们可以发现collectionview在iOS11向下偏移64,什原因导致偏移?在iOS11之前,如果想要scrollView不偏移64p,则需设置automaticallyAdjustsScrollViewInsets=NO,但是这个属性在iOS11直接被遗弃了😳:使用scrollView的属性contentInsetAdjustmentBehavior来防止偏移。

UIScrollViewContentInsetAdjustmentAutomatic

UIScrollViewContentInsetAdjustmentScrollableAxes

UIScrollViewContentInsetAdjustmentNever

UIScrollViewContentInsetAdjustmentAlways

这里我们直接选Never就可以了

if (@available(iOS 11.0, *)) {

  _collectionView.contentInsetAdjustmentBehavior = UIApplicationBackgroundFetchIntervalNever;

     }

但是在iOS11以前系统编译崩溃,原来@available(iOS 11.0, *)是iOS 11新增加的,在iOS11以下系统找不到崩溃,为了解决这个问题需要用到条件编译指令解决这个问题

#ifdef __IPHONE_11_0

if (@available(iOS 11.0, *)) {

_collectionView.contentInsetAdjustmentBehavior = UIApplicationBackgroundFetchIntervalNever;

}

#endif


适配前我的页面


适配后我的页面

九.自定义分割线处理

1.iOS 11分割线颜色加深

iOS 11中有的自定义分割线颜色莫名奇妙变深,很难看,如下图所示,不符合设计规范,尝试其他方法没有解决这个问题,最后通过改变分割线的透明度来解决

适配前


适配前代码


适配后代码


适配后

2.没有文字显示分割线


适配前

// 这些界面以下使用代理方法来设置,发现并没有生效

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

// 这样的原理是因为之前只是实现了高度的代理方法,却没有实现View的代理方法,iOS10及以前这么写是没问题的,iOS11开启了行高估算机制引起的bug,因此有以下几种解决方法:

// 解决方法一:添加实现View的代理方法,只有实现下面两个方法,方法 (CGFloat)tableView: heightForFooterInSection: 才会生效

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {

return nil;

}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

return nil;

}

// 解决方法二:直接使用tableView属性进行设置,修复该UI错乱

self.tableView.sectionHeaderHeight = 0;

self.tableView.sectionFooterHeight = 5;

[_optionTableView setContentInset:UIEdgeInsetsMake(-35, 0, 0, 0)];

// 解决方法三:添加以下代码关闭估算行高

self.tableView.estimatedRowHeight = 0;

self.tableView.estimatedSectionHeaderHeight = 0;

self.tableView.estimatedSectionFooterHeight = 0;


适配后

十.顶部菜单上移,挡住文字适配


适配前顶部菜单被挡住


适配前代码


适配后代码


适配后常用清单页面

十一.适配xib页面

适配前注册页面

注册页面用xib写的,页面tableview距离顶部高度64,写死的,由于导航栏高度在iPhone X和非iPhone X高度不一致,如果都写成64出现下图问题,为了解决这个问题,用到系统自动布局NSLayoutConstraint视图上面,在storyboard 中,通过拖拽方式,将一个IBOutlet 拖拽到 .m 文件中如图所示


tableview距离顶部高度


适配后代码


适配后注册页面

十二:信号栏的字体颜色无法改变


适配前信号栏颜色


改变信号栏颜色方法

改变信号栏方法使用,如果某个页面状态栏颜色改变自己定义颜色用这个方法,针对iOS11以前使用

- (void)viewWillAppear:(BOOL)animated {

[super viewWillAppear:animated];

[MCHelpTool changeSignalFormatWithColor:[UIColor whiteColor]];

}

但是在iOS11上状态栏的颜色通过这个方法无法改变,状态栏机制发生变化导致,需要对该方法进行iOS11适配.


iOS 11(非iPhone X机型)


iPhone X
iOS11以前


/**

*  改变信号栏字体颜色

*

*  @param color 颜色参数

*/

+ (void)changeSignalFormatWithColor:(UIColor *)color{

UIApplication * app = [UIApplication sharedApplication];

id obj = [app valueForKeyPath:@"statusBar"];

if (@available(iOS 11.0, *)) {

if (IS_iPhoneX) {

id obc = [obj valueForKeyPath:@"statusBar"];

unsigned int propertyCount;

objc_property_t * properties = class_copyPropertyList([obc class], &propertyCount);

NSMutableArray * arr = [NSMutableArray arrayWithCapacity:1];

for (int i = 0; i < propertyCount; i++){

objc_property_t property = properties[i];

NSString * propertyStr = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];

if ([propertyStr isEqualToString:@"foregroundColor"]){

[obj setValue:color forKey:propertyStr];

}

[arr sui_addObj:propertyStr];

}

free(properties);

}else{

id ob = [obj valueForKeyPath:@"superclass"];

unsigned int propertyCount;

objc_property_t * properties = class_copyPropertyList([ob class], &propertyCount);

NSMutableArray * arr = [NSMutableArray arrayWithCapacity:1];

for (int i = 0; i < propertyCount; i++){

objc_property_t property = properties[i];

NSString * propertyStr = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];

if ([propertyStr isEqualToString:@"foregroundColor"]){

[obj setValue:color forKey:propertyStr];

}

[arr sui_addObj:propertyStr];

}

free(properties);

}

}else{

unsigned int propertyCount;

objc_property_t * properties = class_copyPropertyList([obj class], &propertyCount);

NSMutableArray * arr = [NSMutableArray arrayWithCapacity:1];

for (int i = 0; i < propertyCount; i++){

objc_property_t property = properties[i];

NSString * propertyStr = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];

if ([propertyStr isEqualToString:@"foregroundColor"]){

[obj setValue:color forKey:propertyStr];

}

[arr sui_addObj:propertyStr];

}

free(properties);

}

}

未完待续....

参考文章:

iOS11-UISearchBar居中placeholder和icon

ios 改变searchBar的高度

UIsearchBar iOS11 像之前的版本那样没有内容居中 有内容居左

iPhone X HIG

Adaptivity & Layout

Image size & Resolution

WWDC17: What's New in Location Technologies ?

Designing for iPhone X

Building Apps for iPhone X

关于iPhone X 的适配

iOS11 & iPhone X 适配指南

你可能需要为你的 APP 适配 iOS 11

适配iOS11,适配iPhoneX,适配安全区的几个文章和宏

为 iOS 11 适配工具栏(UIToolBar)

简书 App 适配 iOS 11

iOS 安全区域适配总结

Update Apps for iPhone X

手管 iPhone X 的适配总结

iOS11 以及iPhone X 适配记录

如何快速定位、分析、解决非Crash的BUG(iOS 11篇)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容