自定義View進階篇《五》——Path之基本操作

一、Path常用方法表

為了兼容性(偷懶) 本表格中去除了部分API21(即安卓版本5.0)以上才添加的方法。


二杈曲、Path詳解

請關(guān)閉硬件加速丈钙,以免引起不必要的問題非驮!
請關(guān)閉硬件加速,以免引起不必要的問題雏赦!
請關(guān)閉硬件加速劫笙,以免引起不必要的問題芙扎!
在AndroidMenifest文件中application節(jié)點下添上 android:hardwareAccelerated=”false”以關(guān)閉整個應(yīng)用的硬件加速。

Path作用

本次特地開了一篇詳細講解Path填大,為什么要單獨摘出來呢戒洼,這是因為Path在2D繪圖中是一個很重要的東西。

在前面我們講解的所有繪制都是簡單圖形(如 矩形 圓 圓弧等)允华,而對于那些復雜一點的圖形則沒法去繪制(如繪制一個心形 正多邊形 五角星等)施逾,而使用Path不僅能夠繪制簡單圖形,也可以繪制這些比較復雜的圖形例获。另外汉额,根據(jù)路徑繪制文本和剪裁畫布都會用到Path。

Path含義

Path封裝了由直線和曲線(二次榨汤,三次貝塞爾曲線)構(gòu)成的幾何路徑蠕搜。你能用Canvas中的drawPath來把這條路徑畫出來(同樣支持Paint的不同繪制模式),也可以用于剪裁畫布和根據(jù)路徑繪制文字收壕。我們有時會用Path來描述一個圖像的輪廓妓灌,所以也會稱為輪廓線(輪廓線僅是Path的一種使用方法,兩者并不等價)
另外路徑有開放和封閉的區(qū)別蜜宪。


Path使用方法詳解

第1組: moveTo虫埂、 setLastPoint、 lineTo 和 close
由于Path的有些知識點無法單獨來講圃验,所以本次采取了一次講一組方法掉伏。

按照慣例,先創(chuàng)建畫筆:

Paint mPaint = new Paint();             // 創(chuàng)建畫筆
mPaint.setColor(Color.BLACK);           // 畫筆顏色 - 黑色
mPaint.setStyle(Paint.Style.STROKE);    // 填充模式 - 描邊
mPaint.setStrokeWidth(10);              // 邊框?qū)挾?- 10

lineTo:

方法預(yù)覽:

public void lineTo (float x, float y)

首先講解的的LineTo澳窑,為啥先講解這個呢斧散?

是因為moveTo、 setLastPoint摊聋、 close都無法直接看到效果鸡捐,借助有具現(xiàn)化效果的lineTo才能讓這些方法現(xiàn)出原形。

lineTo很簡單麻裁,只有一個方法箍镜,作用也很容易理解,line嘛煎源,顧名思義就是一條線色迂。

俗話(數(shù)學書上)說,兩點確定一條直線薪夕,但是看參數(shù)明顯只給了一個點的坐標吧(這不按常理出牌啊)脚草。

再仔細一看赫悄,這個lineTo除了line外還有一個to呢原献,to翻譯過來就是“至”馏慨,到某個地方的意思,lineTo難道是指從某個點到參數(shù)坐標點之間連一條線姑隅?

沒錯写隶,你猜對了,但是這某個點又是哪里呢讲仰?

前面我們提到過Path可以用來描述一個圖像的輪廓慕趴,圖像的輪廓通常都是用一條線構(gòu)成的,所以這里的某個點就是上次操作結(jié)束的點鄙陡,如果沒有進行過操作則默認點為坐標原點冕房。

那么我們就來試一下:

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心(寬高數(shù)據(jù)在onSizeChanged中獲取)

Path path = new Path();                     // 創(chuàng)建Path

path.lineTo(200, 200);                      // lineTo
path.lineTo(200,0);

canvas.drawPath(path, mPaint);              // 繪制Path

在示例中我們調(diào)用了兩次lineTo,第一次由于之前沒有過操作趁矾,所以默認點就是坐標原點O耙册,結(jié)果就是坐標原點O到A(200,200)之間連直線(用藍色圈1標注)。

第二次lineTo的時候毫捣,由于上次的結(jié)束位置是A(200,200),所以就是A(200,200)到B(200,0)之間的連線(用藍色圈2標注)详拙。

moveTo 和 setLastPoint:

方法預(yù)覽:

// moveTo
public void moveTo (float x, float y)

// setLastPoint
public void setLastPoint (float dx, float dy)

這兩個方法雖然在作用上有相似之處,但實際上卻是完全不同的兩個東東蔓同,具體參照下表:



廢話不多說饶辙,直接上代碼:

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心

Path path = new Path();                     // 創(chuàng)建Path

path.lineTo(200, 200);                      // lineTo

path.moveTo(200,100);                       // moveTo

path.lineTo(200,0);                         // lineTo

canvas.drawPath(path, mPaint);              // 繪制Path

這個和上面演示lineTo的方法類似,只不過在兩個lineTo之間添加了一個moveTo斑粱。
moveTo只改變下次操作的起點弃揽,在執(zhí)行完第一次LineTo的時候,本來的默認點位置是A(200,200),但是moveTo將其改變成為了C(200,100),所以在第二次調(diào)用lineTo的時候就是連接C(200,100) 到 B(200,0) 之間的直線(用藍色圈2標注)则北。
下面是setLastPoint的示例:

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心

Path path = new Path();                     // 創(chuàng)建Path

path.lineTo(200, 200);                      // lineTo

path.setLastPoint(200,100);                 // setLastPoint

path.lineTo(200,0);                         // lineTo

canvas.drawPath(path, mPaint);              // 繪制Path

setLastPoint是重置上一次操作的最后一個點蹋宦,在執(zhí)行完第一次的lineTo的時候,最后一個點是A(200,200),而setLastPoint更改最后一個點為C(200,100),所以在實際執(zhí)行的時候咒锻,第一次的lineTo就不是從原點O到A(200,200)的連線了冷冗,而變成了從原點O到C(200,100)之間的連線了。

在執(zhí)行完第一次lineTo和setLastPoint后惑艇,最后一個點的位置是C(200,100),所以在第二次調(diào)用lineTo的時候就是C(200,100) 到 B(200,0) 之間的連線(用藍色圈2標注)蒿辙。

close

方法預(yù)覽:

public void close ()

close方法用于連接當前最后一個點和最初的一個點(如果兩個點不重合的話),最終形成一個封閉的圖形滨巴。

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心

Path path = new Path();                     // 創(chuàng)建Path

path.lineTo(200, 200);                      // lineTo

path.lineTo(200,0);                         // lineTo

path.close();                               // close

canvas.drawPath(path, mPaint);              // 繪制Path

很明顯思灌,兩個lineTo分別代表第1和第2條線,而close在此處的作用就算連接了B(200,0)點和原點O之間的第3條線恭取,使之形成一個封閉的圖形泰偿。
注意:close的作用是封閉路徑,與連接當前最后一個點和第一個點并不等價蜈垮。如果連接了最后一個點和第一個點仍然無法形成封閉圖形裕照,則close什么 也不做调塌。

第2組: addXxx與arcTo

這次內(nèi)容主要是在Path中添加基本圖形,重點區(qū)分addArc與arcTo羔砾。

第一類(基本形狀)

方法預(yù)覽:

// 第一類(基本形狀)

// 圓形
public void addCircle (float x, float y, float radius, Path.Direction dir)
// 橢圓
public void addOval (RectF oval, Path.Direction dir)
// 矩形
public void addRect (float left, float top, float right, float bottom, Path.Direction dir)
public void addRect (RectF rect, Path.Direction dir)
// 圓角矩形
public void addRoundRect (RectF rect, float[] radii, Path.Direction dir)
public void addRoundRect (RectF rect, float rx, float ry, Path.Direction dir)

仔細觀察一下第一類是方法负间,無一例外姜凄,在最后都有一個 Path.Direction,這是一個什么神奇的東東态秧?
Direction的意思是 方向玩祟,趨勢。 點進去看一下會發(fā)現(xiàn)Direction是一個枚舉(Enum)類型屿聋,里面只有兩個枚舉常量润讥,如下:



先偷偷劇透一下這個順時針和逆時針的作用。



這個先劇透這么多撮慨,至于對閉合順序有啥影響脆粥,圖形的渲染等問題等請慢慢看下去

咱們先研究確定閉合順序的問題,添加一個矩形試試看:

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心

Path path = new Path();

path.addRect(-200,-200,200,200, Path.Direction.CW);

canvas.drawPath(path,mPaint);

將上面代碼的CW改為CCW再運行一次规伐。接下來就是見證奇跡的時刻匣缘,兩次運行結(jié)果一模一樣,有木有很神奇肌厨!(神奇?zhèn)€毛啊??????????)
其實啊,這個東東是自帶隱身技能的吵护,想要讓它現(xiàn)出原形,就要用到咱們剛剛學到的setLastPoint(重置當前最后一個點的位置)祥诽。

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心

Path path = new Path();

path.addRect(-200,-200,200,200, Path.Direction.CW);

path.setLastPoint(-300,300);                // <-- 重置最后一個點的位置

canvas.drawPath(path,mPaint);

可以明顯看到用爪,圖形發(fā)生了奇怪的變化胁镐。為何會如此呢偎血?

我們先分析一下,繪制一個矩形(僅繪制邊線)盯漂,實際上只需要進行四次lineTo操作就行了颇玷,也就是說就缆,只需要知道4個點的坐標竭宰,然后使用moveTo到第一個點,之后依次lineTo就行了(從上面的測試可以看出狞甚,在實際繪制中也確實是這么干的)廓旬。

可是為什么要這么做呢?確定一個矩形最少需要兩個點(對角線的兩個點)涩盾,根據(jù)這兩個點的坐標直接算出四條邊然后畫出來不就行了励背,干嘛還要先計算出四個點坐標,之后再連直線呢终畅?

這個就要涉及一些path的存儲問題了竟闪,前面在path中的定義中說過炼蛤,Path是封裝了由直線和曲線(二次,三次貝塞爾曲線)構(gòu)成的幾何路徑。其中曲線部分用的是貝塞爾曲線绿聘,稍后再講次舌。 然而除了曲線部分就只剩下直線了彼念,對于直線的存儲最簡單的就是記錄坐標點,然后直接連接各個點就行了哲思。雖然記錄矩形只需要兩個點吩案,但是如果只用兩個點來記錄一個矩形的話,就要額外增加一個標志位來記錄這是一個矩形靠益,顯然對于存儲和解析都是很不劃算的事情残揉,將矩形轉(zhuǎn)換為直線,為的就是存儲記錄方便绩卤。

扯了這么多江醇,該回歸正題了陶夜,就是我們的順時針和逆時針在這里是干啥的?

圖形在實際記錄中就是記錄各個的點黔夭,對于一個圖形來說肯定有多個點羽嫡,既然有這么多的點,肯定就需要一個先后順序婚惫,這里順時針和逆時針就是用來確定記錄這些點的順序的。

對于上面這個矩形來說艰管,我們采用的是順時針(CW)蒋川,所以記錄的點的順序就是 A -> B -> C -> D. 最后一個點就是D捺球,我們這里使用setLastPoint改變最后一個點的位置實際上是改變了D的位置。

理解了上面的原理之后餐济,設(shè)想如果我們將順時針改為逆時針(CCW)胆剧,則記錄點的順序應(yīng)該就是 A -> D -> C -> B, 再使用setLastPoint則改變的是B的位置醉冤,我們試試看結(jié)果和我們的猜想是否一致:

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心

Path path = new Path();

path.addRect(-200,-200,200,200, Path.Direction.CCW);

path.setLastPoint(-300,300);                // <-- 重置最后一個點的位置

canvas.drawPath(path,mPaint);

通過驗證發(fā)現(xiàn)蚁阳,發(fā)現(xiàn)結(jié)果和我們猜想的一樣,但是還有一個潛藏的問題不曉得大家可否注意到颠悬。我們用兩個點的坐標確定了一個矩形定血,矩形起始點(A)就是我們指定的第一個點的坐標澜沟。

需要注意的是,交換坐標點的順序可能就會影響到某些繪制內(nèi)容哦刊苍,例如上面的例子濒析,你可以嘗試交換兩個坐標點,或者指定另外兩個點來作為參數(shù)婴氮,雖然指定的是同一個矩形,但實際繪制出來是不同的哦名船。
參數(shù)中點的順序很重要旨怠!
參數(shù)中點的順序很重要鉴腻!
參數(shù)中點的順序很重要!

重要的話說三遍蜓席,本次是用矩形作為例子的课锌,其他的幾個圖形基本上都包含了曲線,詳情參見后續(xù)的貝塞爾曲線部分雏胃。

重要的話說三遍志鞍,本次是用矩形作為例子的固棚,其他的幾個圖形基本上都包含了曲線,詳情參見后續(xù)的貝塞爾曲線部分厂汗。

第二類(Path)

方法預(yù)覽:

// 第二類(Path)
// path
public void addPath (Path src)
public void addPath (Path src, float dx, float dy)
public void addPath (Path src, Matrix matrix)

這個相對比較簡單黍翎,也很容易理解匣掸,就是將兩個Path合并成為一個。

第三個方法是將src添加到當前path之前先使用Matrix進行變換霎匈。

第二個方法比第一個方法多出來的兩個參數(shù)是將src進行了位移之后再添加進當前path中送爸。
示例:

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心
canvas.scale(1,-1);                         // <-- 注意 翻轉(zhuǎn)y坐標軸

Path path = new Path();
Path src = new Path();

path.addRect(-200,-200,200,200, Path.Direction.CW);
src.addCircle(0,0,100, Path.Direction.CW);

path.addPath(src,0,200);

mPaint.setColor(Color.BLACK);           // 繪制合并后的路徑
canvas.drawPath(path,mPaint);

首先我們新建地方兩個Path(矩形和圓形)中心都是坐標原點,我們在將包含圓形的path添加到包含矩形的path之前將其進行移動了一段距離墨吓,最終繪制出來的效果就如上面所示帖烘。

第三類(addArc與arcTo)

方法預(yù)覽:

// 第三類(addArc與arcTo)

// addArc
public void addArc (RectF oval, float startAngle, float sweepAngle)
// arcTo
public void arcTo (RectF oval, float startAngle, float sweepAngle)
public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

參數(shù)表:


PS: sweepAngle取值范圍是 [-360, 360)秘症,不包括360,當 >= 360 或者 < -360 時將不會繪制任何內(nèi)容役耕, 對于360聪廉,你可以用一個接近的值替代,例如: 359.99图云。

從名字就可以看出邻邮,這兩個方法都是與圓弧相關(guān)的筒严,作用都是添加一個圓弧到path中情萤,但既然存在兩個方法,兩者之間肯定是有區(qū)別的:



可以看到addArc有1個方法(實際上是兩個的,但另一個重載方法是API21添加的), 而arcTo有2個方法睁宰,其中一個最后多了一個布爾類型的變量forceMoveTo柒傻。

forceMoveTo是什么作用呢?

這個變量意思為“是否強制使用moveTo”伐债,也就是說峰锁,是否使用moveTo將變量移動到圓弧的起點位移双戳,也就意味著:



示例(addArc):

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心
canvas.scale(1,-1);                         // <-- 注意 翻轉(zhuǎn)y坐標軸

Path path = new Path();
path.lineTo(100,100);

RectF oval = new RectF(0,0,300,300);

path.addArc(oval,0,270);
// path.arcTo(oval,0,270,true);             // <-- 和上面一句作用等價

canvas.drawPath(path,mPaint);

示例(arcTo):

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心
canvas.scale(1,-1);                         // <-- 注意 翻轉(zhuǎn)y坐標軸

Path path = new Path();
path.lineTo(100,100);

RectF oval = new RectF(0,0,300,300);

path.arcTo(oval,0,270);
// path.arcTo(oval,0,270,false);             // <-- 和上面一句作用等價

canvas.drawPath(path,mPaint);

第3組:isEmpty千诬、 isRect膏斤、isConvex、 set 和 offset

這一組比較簡單傲茄,稍微說一下就可以了沮榜。

isEmpty

方法預(yù)覽:

public boolean isEmpty ()

判斷path中是否包含內(nèi)容蟆融。

Path path = new Path();
Log.e("1",path.isEmpty()+"");

path.lineTo(100,100);
Log.e("2",path.isEmpty()+"");

log輸出結(jié)果:

com.sloop.canvas E/1: true
com.sloop.canvas E/2: false

isRect

方法預(yù)覽:

public boolean isRect (RectF rect)

判斷path是否是一個矩形,如果是一個矩形的話山憨,會將矩形的信息存放進參數(shù)rect中弥喉。

path.lineTo(0,400);
path.lineTo(400,400);
path.lineTo(400,0);
path.lineTo(0,0);

RectF rect = new RectF();
boolean b = path.isRect(rect);
Log.e("Rect","isRect:"+b+"| left:"+rect.left+"| top:"+rect.top+"| right:"+rect.right+"| bottom:"+rect.bottom);

log 輸出結(jié)果:

com.sloop.canvas E/Rect: isRect:true| left:0.0| top:0.0| right:400.0| bottom:400.0

set

方法預(yù)覽:

public void set (Path src)

將新的path賦值到現(xiàn)有path由境。

canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心
canvas.scale(1,-1);                         // <-- 注意 翻轉(zhuǎn)y坐標軸

Path path = new Path();                     // path添加一個矩形
path.addRect(-200,-200,200,200, Path.Direction.CW);

Path src = new Path();                      // src添加一個圓
src.addCircle(0,0,100, Path.Direction.CW);

path.set(src);                              // 大致相當于 path = src;

canvas.drawPath(path,mPaint);

offset

方法預(yù)覽:

public void offset (float dx, float dy)
public void offset (float dx, float dy, Path dst)

這個的作用也很簡單虏杰,就是對path進行一段平移,它和Canvas中的translate作用很像攻询,但Canvas作用于整個畫布州弟,而path的offset只作用于當前path低零。
但是第二個方法最后怎么會有一個path作為參數(shù)掏婶?

其實第二個方法中最后的參數(shù)das是存儲平移后的path的猎物。


canvas.translate(mWidth / 2, mHeight / 2);  // 移動坐標系到屏幕中心
canvas.scale(1,-1);                         // <-- 注意 翻轉(zhuǎn)y坐標軸

Path path = new Path();                     // path中添加一個圓形(圓心在坐標原點)
path.addCircle(0,0,100, Path.Direction.CW);

Path dst = new Path();                      // dst中添加一個矩形
dst.addRect(-200,-200,200,200, Path.Direction.CW);

path.offset(300,0,dst);                     // 平移

canvas.drawPath(path,mPaint);               // 繪制path

mPaint.setColor(Color.BLUE);                // 更改畫筆顏色

canvas.drawPath(dst,mPaint);                // 繪制dst

從運行效果圖可以看出炕横,雖然我們在dst中添加了一個矩形老厌,但是并沒有表現(xiàn)出來枝秤,所以慷嗜,當dst中存在內(nèi)容時,dst中原有的內(nèi)容會被清空薇溃,而存放平移后的path缭乘。

三、總結(jié)

本想一篇把path寫完薄啥,但是萬萬沒想到居然扯了這么多逛尚。本篇中講解的是直線部分和一些常用方法绰寞,下一篇將著重講解貝塞爾曲線和自相交圖形渲染等相關(guān)問題铣口,敬請期待哦。

學完本篇之后又解鎖了新的境界件缸,可以看看這位大神的文章 Android雷達圖(蜘蛛網(wǎng)圖)繪制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末他炊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蚕苇,更是在濱河造成了極大的恐慌凿叠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異炒刁,居然都是意外死亡,警方通過查閱死者的電腦和手機飒筑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門协屡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來全谤,“玉大人认然,你說我怎么就攤上這事∮遥” “怎么了毕骡?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵未巫,是天一觀的道長。 經(jīng)常有香客問我叙凡,道長握爷,這世上最難降的妖魔是什么严里? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任田炭,我火速辦了婚禮漓柑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞬矩。我一直安慰自己锋玲,他們只是感情好惭蹂,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著媚污,像睡著了一般廷雅。 火紅的嫁衣襯著肌膚如雪航缀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天蛇摸,我揣著相機與錄音飞傀,去河邊找鬼砸烦。 笑死绞吁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的颜说。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼喊积,長吁一口氣:“原來是場噩夢啊……” “哼乾吻!你這毒婦竟也來了拟蜻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤诡必,失蹤者是張志新(化名)和其女友劉穎爸舒,沒想到半個月后稿蹲,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡剖效,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年璧尸,在試婚紗的時候發(fā)現(xiàn)自己被綠了爷光。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澎粟。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡活烙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出重贺,到底是詐尸還是另有隱情,我是刑警寧澤次企,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布潜圃,位于F島的核電站,受9級特大地震影響堵第,放射性物質(zhì)發(fā)生泄漏崇堵。R本人自食惡果不足惜鸳劳,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涵紊。 院中可真熱鬧幔摸,春花似錦既忆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酪术。三九已至,卻和暖如春翠储,著一層夾襖步出監(jiān)牢的瞬間绘雁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工援所, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留庐舟,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓住拭,卻偏偏與公主長得像继阻,于是被迫代替她去往敵國和親废酷。 傳聞我的和親對象是個殘疾皇子瘟檩,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容