News Digest(雅虎新闻)模仿秀第三弹

最近得空做了一个小的新闻类APP,基本上都是照着News Digest的模子刻出来的,之所以这个为参考,是因为觉得News Digest这个APP做得真的很酷炫!


猛戳这里获取整个项目源代码
项目前端主要由swift编写,本地数据用CoreData,后端由Node.js编写,后台数据库用MongoDB。

News Digest(雅虎新闻)模仿秀第一弹
News Digest(雅虎新闻)模仿秀第二弹
News Digest(雅虎新闻)模仿秀第四弹

这期我们来说一下加载动画的实现,先上效果图:

加载动画
  1. LoadingView Frame
    let radius: CGFloat = 45/2.0 - 4.5   // (总半径 - 圆圈半径) 用来计算每一个点的center
    var loadLayer = CALayer()   // Loading Layer
    // Color
    let firstColor = UIColor.RGBColor(0, green: 176, blue: 56, alpha: 1)
    let secondColor = UIColor.RGBColor(255, green: 182, blue: 63, alpha: 1)
    let thirdColor = UIColor.RGBColor(0, green: 140, blue: 212, alpha: 1)
    let fourthColor = UIColor.RGBColor(0, green: 167, blue: 141, alpha: 1)
    let fifthColor = UIColor.RGBColor(255, green: 0, blue: 123, alpha: 1)
    let sixthColor = UIColor.RGBColor(255, green: 87, blue: 36, alpha: 1)
    let endColor = UIColor.RGBColor(0, green: 140, blue: 212, alpha: 1)
    
    // Color Layer
    var firstLayer = CALayer()  // redColor
    var secondLayer = CALayer() // greenColor
    var thirdLayer = CALayer()  // yellowColor
    var fourthLayer = CALayer() // blackColor
    var fifthLayer = CALayer()  // blueColor
    var sixthLayer = CALayer()  // brownColor
    // Postion
    var firstPostion = CGPointZero
    var secondPostion = CGPointZero
    var thirdPostion = CGPointZero
    var fourthPostion = CGPointZero
    var fifthPostion = CGPointZero
    var sixthPostion = CGPointZero
    // Animation
    var rotateAnimation = CABasicAnimation()
    var firstGroupAnimation = CAAnimationGroup()
    var secondGroupAnimation = CAAnimationGroup()
    var thirdGroupAnimation = CAAnimationGroup()
    var fourthGroupAnimation = CAAnimationGroup()
    var fifthGroupAnimation = CAAnimationGroup()
    var sixthGroupAnimation = CAAnimationGroup()
    init() {
        // 位于正中心
        super.init(frame: CurrentWindow.frame)
        self.backgroundColor = UIColor.whiteColor()
        
        // Background Image
        let imageView = UIImageView(frame: self.frame)
        imageView.image = UIImage(named: "")
        self.addSubview(imageView)
        
        configurateLayer()
        configurateAnimation()
    }

首先设置加载视图的frame,是当前UIWindow的frame,也就是说覆盖整个屏幕(代码当中的imageView本来想加一张背景的,但是现在直接用backgroundColor = whiteColor 做背景)

  1. LoadingView loadLayer
    //MARK: - Configurate Layer
    func configurateLayer() {
        loadLayer.frame = CGRectMake(self.center.x - 45, self.center.y - 45, 90, 90)
        loadLayer.backgroundColor = UIColor.clearColor().CGColor
        loadLayer.position = self.center
        
        let centerX: CGFloat = 45
        let centerY: CGFloat = 45
        // 这里计算center,每一个相隔60°,所以计算sin和cos然后算出位置即可
        firstPostion = CGPointMake(centerX, centerY - radius)
        secondPostion = CGPointMake(centerX + radius*sin(CGFloat(M_PI)/3.0), centerY - radius*cos(CGFloat(M_PI/3.0)))
        thirdPostion = CGPointMake(centerX + radius*cos(CGFloat(M_PI)/6.0), centerY + radius*sin(CGFloat(M_PI/6.0)))
        fourthPostion = CGPointMake(centerX, centerY + radius)
        fifthPostion = CGPointMake(centerX - radius*sin(CGFloat(M_PI)/3.0), centerY + radius*cos(CGFloat(M_PI/3.0)))
        sixthPostion = CGPointMake(centerX - radius*sin(CGFloat(M_PI)/3.0), centerY - radius*cos(CGFloat(M_PI/3.0)))
        
        // Add Six Circles
        firstLayer.frame = CGRectMake(0, 0, 9, 9)
        firstLayer.position = firstPostion
        firstLayer.cornerRadius = 4.5
        firstLayer.masksToBounds = true
        firstLayer.backgroundColor = firstColor.CGColor
        loadLayer.addSublayer(firstLayer)
        
        secondLayer.frame = CGRectMake(0, 0, 9, 9)
        secondLayer.position = secondPostion
        secondLayer.cornerRadius = 4.5
        secondLayer.masksToBounds = true
        secondLayer.backgroundColor = secondColor.CGColor

        loadLayer.addSublayer(secondLayer)
        
        thirdLayer.frame = CGRectMake(0, 0, 9, 9)
        thirdLayer.position = thirdPostion
        thirdLayer.cornerRadius = 4.5
        thirdLayer.masksToBounds = true
        thirdLayer.backgroundColor = thirdColor.CGColor

        loadLayer.addSublayer(thirdLayer)
        
        fourthLayer.frame = CGRectMake(0, 0, 9, 9)
        fourthLayer.position = fourthPostion
        fourthLayer.cornerRadius = 4.5
        fourthLayer.masksToBounds = true
        fourthLayer.backgroundColor = fourthColor.CGColor
        loadLayer.addSublayer(fourthLayer)
        
        fifthLayer.frame = CGRectMake(0, 0, 9, 9)
        fifthLayer.position = fifthPostion
        fifthLayer.cornerRadius = 4.5
        fifthLayer.masksToBounds = true
        fifthLayer.backgroundColor = fifthColor.CGColor
        loadLayer.addSublayer(fifthLayer)
        
        sixthLayer.frame = CGRectMake(0, 0, 9, 9)
        sixthLayer.position = sixthPostion
        sixthLayer.cornerRadius = 4.5
        sixthLayer.masksToBounds = true
        sixthLayer.backgroundColor = sixthColor.CGColor
        loadLayer.addSublayer(sixthLayer)
        
        self.layer.addSublayer(loadLayer)
    }

loadLayer是添加到self.layer的子layer,也就是说最主要实现加载动画的父layer就是这个loadLayer

  • 这里我设定loadLayer的frame是位于正中心,width和height都是90
  • 圈圈的圆心到loadLayer的中心距离是45(设高度和宽度都是90就是为了方便圈圈做结束动画向外伸展一定距离再收缩)
  • firstPostion-sixthPostion是计算每一个圈圈的圆心位置(其实就是一个圆平分成六个60°,通过sin/cos算出具体位置),这几个参数后面还需要用于计算圈圈向外的伸展收缩动画
  • 剩下的就是设置layer的属性,width和height都是9,然后设置cornerRadius = 4.5,再裁剪,使之变成圆形
  1. LoadingView Animation
    //MARK: - Configurate Animation
    func configurateAnimation() {
        rotateAnimation = CABasicAnimation()
        rotateAnimation.keyPath = "transform.rotation"
        rotateAnimation.fromValue = NSNumber.init(float: 0)
        rotateAnimation.toValue = NSNumber.init(float: 2*Float(M_PI))
        rotateAnimation.duration = 1.2
        rotateAnimation.repeatCount = Float.infinity    // 无限循环
        rotateAnimation.removedOnCompletion = false     // 动画后不移除
        rotateAnimation.fillMode = kCAFillModeForwards  // 保留动画后的样子,如果removedOnCompletion不是false,没效果
        
        // Scale
        let sizeAnimation = CAKeyframeAnimation()
        sizeAnimation.keyPath = "transform.scale"
        sizeAnimation.keyTimes = [NSNumber(float: 0), NSNumber(float: 0.2), NSNumber(float: 0.4), NSNumber(float: 0.6), NSNumber(float: 1.0)]
        sizeAnimation.values = [NSNumber(float: 1.0), NSNumber(float: 0.8), NSNumber(float: 0.8), NSNumber(float: 1.4), NSNumber(float: 1.6)]
        sizeAnimation.duration = 1.6
        sizeAnimation.repeatCount = 1.0
        
        // Color
        let colorAnimation = CAKeyframeAnimation()
        colorAnimation.keyPath = "backgroundColor"
        colorAnimation.keyTimes = [NSNumber(float: 0.6), NSNumber(float: 1.0)]
        colorAnimation.values = [endColor.CGColor, endColor.CGColor]
        colorAnimation.duration = 1.6
        colorAnimation.repeatCount = 1.0
        
        // First Animation Group
        firstGroupAnimation = CAAnimationGroup()
        firstGroupAnimation.duration = 1.6
        firstGroupAnimation.repeatCount = 1.0
        
        let firstTransformAnimation = CAKeyframeAnimation()
        firstTransformAnimation.keyPath = "position"
        firstTransformAnimation.keyTimes = [NSNumber(float: 0.2), NSNumber(float: 0.4), NSNumber(float: 0.6), NSNumber(float: 1.0)]
        let firstPoint1 = CGPointMake(45, 17)
        let firstPoint2 = CGPointMake(45, 45)
        firstTransformAnimation.values = [NSValue(CGPoint: firstPoint1), NSValue(CGPoint: firstPoint1), NSValue(CGPoint: firstPoint2), NSValue(CGPoint: firstPoint2)]
        firstTransformAnimation.duration = 1.6
        firstTransformAnimation.repeatCount = 1.0
        firstGroupAnimation.animations = [colorAnimation, sizeAnimation, firstTransformAnimation]
        
        // Second Animation Group
        secondGroupAnimation = CAAnimationGroup()
        secondGroupAnimation.duration = 1.6
        secondGroupAnimation.repeatCount = 1.0
        
        let secondTransformAnimation = CAKeyframeAnimation()
        secondTransformAnimation.keyPath = "position"
        secondTransformAnimation.keyTimes = [NSNumber(float: 0.2), NSNumber(float: 0.4), NSNumber(float: 0.6), NSNumber(float: 1.0)]
        let secondX = secondPostion.x + 10*cos(CGFloat(M_PI/6.0))
        let secondY = secondPostion.y - 10*sin(CGFloat(M_PI/6.0))
        
        let secondPoint1 = CGPointMake(secondX, secondY)
        let secondPoint2 = CGPointMake(45, 45)
        secondTransformAnimation.values = [NSValue(CGPoint: secondPoint1), NSValue(CGPoint: secondPoint1), NSValue(CGPoint: secondPoint2), NSValue(CGPoint: secondPoint2)]
        secondTransformAnimation.duration = 1.6
        secondTransformAnimation.repeatCount = 1.0
        secondGroupAnimation.animations = [colorAnimation, sizeAnimation, secondTransformAnimation]
        
        // Third Animation Group
        thirdGroupAnimation = CAAnimationGroup()
        thirdGroupAnimation.duration = 1.6
        thirdGroupAnimation.repeatCount = 1.0
        
        let thirdTransformAnimation = CAKeyframeAnimation()
        thirdTransformAnimation.keyPath = "position"
        thirdTransformAnimation.keyTimes = [NSNumber(float: 0.2), NSNumber(float: 0.4), NSNumber(float: 0.6), NSNumber(float: 1.0)]
        let thirdX = thirdPostion.x + 10*cos(CGFloat(M_PI/6.0))
        let thirdY = thirdPostion.y + 10*sin(CGFloat(M_PI/6.0))
        
        let thirdPoint1 = CGPointMake(thirdX, thirdY)
        let thirdPoint2 = CGPointMake(45, 45)
        thirdTransformAnimation.values = [NSValue(CGPoint: thirdPoint1), NSValue(CGPoint: thirdPoint1), NSValue(CGPoint: thirdPoint2), NSValue(CGPoint: thirdPoint2)]
        thirdTransformAnimation.duration = 1.6
        thirdTransformAnimation.repeatCount = 1.0
        thirdGroupAnimation.animations = [colorAnimation, sizeAnimation, thirdTransformAnimation]
        
        // Fourth Animation Group
        fourthGroupAnimation = CAAnimationGroup()
        fourthGroupAnimation.duration = 1.6
        fourthGroupAnimation.repeatCount = 1.0
        
        let fourthTransformAnimation = CAKeyframeAnimation()
        fourthTransformAnimation.keyPath = "position"
        fourthTransformAnimation.keyTimes = [NSNumber(float: 0.2), NSNumber(float: 0.4), NSNumber(float: 0.6), NSNumber(float: 1.0)]
        let fourthPoint1 = CGPointMake(45, 73)
        let fourthPoint2 = CGPointMake(45, 45)
        fourthTransformAnimation.values = [NSValue(CGPoint: fourthPoint1), NSValue(CGPoint: fourthPoint1), NSValue(CGPoint: fourthPoint2), NSValue(CGPoint: fourthPoint2)]
        fourthTransformAnimation.duration = 1.6
        fourthTransformAnimation.repeatCount = 1.0
        fourthGroupAnimation.animations = [colorAnimation, sizeAnimation, fourthTransformAnimation]
        
        // Fifth Animation Group
        fifthGroupAnimation = CAAnimationGroup()
        fifthGroupAnimation.duration = 1.6
        fifthGroupAnimation.repeatCount = 1.0
        
        let fifthTransformAnimation = CAKeyframeAnimation()
        fifthTransformAnimation.keyPath = "position"
        fifthTransformAnimation.keyTimes = [NSNumber(float: 0.2), NSNumber(float: 0.4), NSNumber(float: 0.6), NSNumber(float: 1.0)]
        let fifthX = fifthPostion.x - 10*cos(CGFloat(M_PI/6.0))
        let fifthY = fifthPostion.y + 10*sin(CGFloat(M_PI/6.0))
        
        let fifthPoint1 = CGPointMake(fifthX, fifthY)
        let fifthPoint2 = CGPointMake(45, 45)
        fifthTransformAnimation.values = [NSValue(CGPoint: fifthPoint1), NSValue(CGPoint: fifthPoint1), NSValue(CGPoint: fifthPoint2), NSValue(CGPoint: fifthPoint2)]
        fifthTransformAnimation.duration = 1.6
        fifthTransformAnimation.repeatCount = 1.0
        fifthGroupAnimation.animations = [colorAnimation, sizeAnimation, fifthTransformAnimation]
        
        // Sixth Animation Group
        sixthGroupAnimation = CAAnimationGroup()
        sixthGroupAnimation.duration = 1.6
        sixthGroupAnimation.repeatCount = 1.0
        
        let sixthTransformAnimation = CAKeyframeAnimation()
        sixthTransformAnimation.keyPath = "position"
        sixthTransformAnimation.keyTimes = [NSNumber(float: 0.2), NSNumber(float: 0.4), NSNumber(float: 0.6), NSNumber(float: 1.0)]
        let sixthX = sixthPostion.x - 10*cos(CGFloat(M_PI/6.0))
        let sixthY = sixthPostion.y - 10*sin(CGFloat(M_PI/6.0))
        
        let sixthPoint1 = CGPointMake(sixthX, sixthY)
        let sixthPoint2 = CGPointMake(45, 45)
        sixthTransformAnimation.values = [NSValue(CGPoint: sixthPoint1), NSValue(CGPoint: sixthPoint1), NSValue(CGPoint: sixthPoint2), NSValue(CGPoint: sixthPoint2)]
        sixthTransformAnimation.duration = 1.6
        sixthTransformAnimation.repeatCount = 1.0
        sixthGroupAnimation.animations = [colorAnimation, sizeAnimation, sixthTransformAnimation]
    }
  • rotateAnimation:这个是使loadLayer旋转的动画,keyPath是transform.rotation,然后设置fromValue是0,toValue是2π,执行次数repeatCount是无限循环,这样旋转动画就一直旋转了,需要执行结束动画的停止它即可
  • sizeAnimation(这里应该写成scaleAinmation,但是那时候敲代码的时候没注意):这里用是使圈圈大小变化的CAKeyframeAnimation(关键帧动画),keyPath依旧是执行变化的参数,keyTimes和values是执行变化的时间和变化的数值,也就是说,在某一个时间,我能使圈圈放大/缩小多少倍
  • colorAnimation:跟sizeAnimation一样,是执行圈圈颜色变化的动画
  • firstGroupAnimation-sixthGroupAnimation:第一个圈圈到第六个圈圈的组合动画,每个组合都添加三个动画,分别是上面的两个sizeAnimation、colorAnimation还有最后一个向外移动然后收缩回来的动画TransformAnimation
  • TransformAnimation(这里只以一个举例):依然是CAKeyframeAnimation,这里keyTimes的值为[0.2, 0.4, 0.6, 1.0]
    values的值是[Point1, Point1, Point2, Point2]. 也就是说在前20%的执行时间里,系统执行从原位置到Point1位置的过渡动画,20%到40%的时间里,执行位置不变的动画,40%到60%的时间里,执行Point1到Point2的过渡动画以此类推. 只需要把向外移动的位置和最后停止的位置算出来,就可以了.(本例子以圆心为起点,半径指向圆心向外移动10px再收缩回圆心位置)
  1. LoadingView Show/Dismiss
    //MARK: - Show OR Dismiss
    func show() {
        CurrentWindow.addSubview(self)
        // 执行动画
        self.loadLayer.addAnimation(self.rotateAnimation, forKey: "Rotation")
    }
    
    func dismiss() {
        // 先停止转圈动画
        self.loadLayer.removeAnimationForKey("Rotation") //此方法停止后,图层外观会更新到当前模型的值
        // 执行结束动画
        self.firstLayer.addAnimation(self.firstGroupAnimation, forKey: "FirstCircle")
        self.secondLayer.addAnimation(self.secondGroupAnimation, forKey: "SecondCircle")
        self.thirdLayer.addAnimation(self.thirdGroupAnimation, forKey: "ThirdCircle")
        self.fourthLayer.addAnimation(self.fourthGroupAnimation, forKey: "FourthCircle")
        self.fifthLayer.addAnimation(self.fifthGroupAnimation, forKey: "FifthCircle")
        self.sixthLayer.addAnimation(self.sixthGroupAnimation, forKey: "SixthCircle")
        Delay(1.4) {
            self.exchangeViews()
        }
    }

show的时候将self添加到window,然后loadLayer执行选择动画self.rotateAnimation即可
dismiss的时候,首先停止转圈动画removeAnimationForKey("Rotation"),然后执行组合动画,就是圈圈向外移动再收缩的动画
因为组合动画执行时间是1.6s,所以我设定在1.4s之后执行切换视图的动画,以此达到从圆心放大展示另一个view的效果

  1. LoadingView ExchangeViews
    /*
     CAShapeLayer 是一个通过矢量图形而不是bitmap来绘制的图层子类
     不需要创建寄宿图形,高效使用内存,硬件加速渲染,可以根据CGPath绘制各种形状的图形(不需要闭合)
     */
    func exchangeViews() {
        let rootView = CurrentWindow.subviews[0]
        let fromPath = UIBezierPath(arcCenter: self.center, radius: 7.2, startAngle: 0, endAngle: CGFloat(2.0 * M_PI), clockwise: true);
        let toPath = UIBezierPath.init(arcCenter: self.center, radius: HEIGHT, startAngle: 0, endAngle: CGFloat(2.0 * M_PI), clockwise: true)
        
        let maskLayer = CAShapeLayer();
        maskLayer.path = fromPath.CGPath;
        rootView.layer.mask = maskLayer
        
        let maskLayerAnimation = CABasicAnimation(keyPath: "path")
        maskLayerAnimation.fromValue = fromPath.CGPath
        maskLayerAnimation.toValue = toPath.CGPath
        maskLayerAnimation.duration = 0.8
        maskLayerAnimation.delegate = self
        maskLayerAnimation.removedOnCompletion = false
        maskLayerAnimation.fillMode = kCAFillModeForwards
        maskLayer.addAnimation(maskLayerAnimation, forKey: "MaskPath")
        
        CurrentWindow.exchangeSubviewAtIndex(0, withSubviewAtIndex: 1)
    }
    
    //MARK: - Animation Stop
    override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        self.loadLayer.removeFromSuperlayer()
        self.removeFromSuperview()
    }

这里会用到CAShapeLayer,其他layer好像不能直接设置path(这个我不太确定),这里我们设置CAShapeLayer的其实path是以self.center为圆心,半径是7.2的圆圈(大小差不多等于收缩之后的圈圈),然后toValue设置成半径是window高度的圆圈(这里只要toValue绘制的圆大于整个屏幕就行,就能显现出来了)

  • 这里需要用到layer.mask模板属性,也就是设置视图只显示maskLayer的path(也就是只显示7.2px半径的圆圈)
  • 然后动画执行把半径7.2px的圆圈过渡到半径是Height的圆圈,也就是说全部显示设置视图
  • 这里用到一个UIWindow的exchangeSubviewAtIndex方法,因为我这里只有两个视图,所以切换0和1就行了,如果你栈里面有更多视图的话,你就需要自己辨别判断一下了

今天就写到这里了.

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

推荐阅读更多精彩内容