Android drawPath實(shí)現(xiàn)QQ拖拽泡泡

這兩天學(xué)習(xí)了使用Path繪制貝塞爾曲線相關(guān)匿刮,然后自己動(dòng)手做了一個(gè)類(lèi)似QQ未讀消息可拖拽的小氣泡刃鳄,效果圖如下:

最終效果圖

接下來(lái)一步一步的實(shí)現(xiàn)整個(gè)過(guò)程叠纹。

基本原理

其實(shí)就是使用Path繪制三點(diǎn)的二次方貝塞爾曲線來(lái)完成那個(gè)妖嬈的曲線的跨新。然后根據(jù)觸摸點(diǎn)不斷繪制對(duì)應(yīng)的圓形剃盾,根據(jù)距離的改變改變?cè)脊潭▓A形的半徑大小灶挟。最后就是松手后返回或者爆裂的實(shí)現(xiàn)琉朽。

Path介紹:

顧名思義,就是一個(gè)路徑的意思稚铣,Path里面有很多的方法箱叁,本次設(shè)計(jì)主要用到的相關(guān)方法有

moveTo() 移動(dòng)Path到一個(gè)指定的點(diǎn)
quadTo() 繪制二次貝塞爾曲線,接收兩個(gè)點(diǎn)惕医,第一個(gè)是控制弧度的點(diǎn)耕漱,第二個(gè)是終點(diǎn)。
lineTo() 就是連線
close() 閉合Path路徑抬伺,
reset() 重置Path的相關(guān)設(shè)置

  • Path入門(mén)熱身:

      path.reset();
      path.moveTo(200, 200);
      //第一個(gè)坐標(biāo)是對(duì)應(yīng)的控制的坐標(biāo)螟够,第二個(gè)坐標(biāo)是終點(diǎn)坐標(biāo)
      path.quadTo(400, 250, 600, 200);
    
      canvas.drawPath(path, paint);
      canvas.translate(0, 200);
      //調(diào)用close,就會(huì)首尾閉合連接
      path.close();
      canvas.drawPath(path, paint);
    

記得不要在onDraw方法中new Path或者 Paint喲!

Path

具體實(shí)現(xiàn)拆分:

其實(shí)整個(gè)過(guò)程就是繪制了兩個(gè)貝塞爾二次曲線的的閉合Path路徑峡钓,然后在上面添加兩個(gè)圓形妓笙。

原理圖1

原理圖2
  • 閉合的Path 路徑實(shí)現(xiàn)從左上點(diǎn)畫(huà)二次貝塞爾曲線到左下點(diǎn),左下點(diǎn)連線到右下點(diǎn)能岩,右下點(diǎn)二次貝塞爾曲線到右上點(diǎn)寞宫,最后閉合一下!!

  • 相關(guān)坐標(biāo)的確定
    這是這次里面的難點(diǎn)之一,因?yàn)樯婕暗搅藬?shù)學(xué)里面的一個(gè)sin,cos,tan等等拉鹃,我其實(shí)也忘完了辈赋,然后又腦補(bǔ)了一下,廢話不多說(shuō)膏燕,直接上圖L棵怼!

    旋轉(zhuǎn)過(guò)程的角標(biāo)

為什么自己要親自去畫(huà)一下呢煌寇,因?yàn)楫?huà)了你才知道,在360旋轉(zhuǎn)的過(guò)程中逾雄,角標(biāo)體系是有兩套的阀溶,如果就使用一套來(lái)畫(huà)的話腻脏,就畫(huà)出現(xiàn)在旋轉(zhuǎn)的過(guò)程中曲線重疊在一起的情況!

問(wèn)題已經(jīng)拋出來(lái)了银锻,接下來(lái)直接看看代碼實(shí)現(xiàn)永品!

角度確定

根據(jù)貼出來(lái)的原理圖可以知道,我們可以使用起始圓心坐標(biāo)和拖拽的圓心坐標(biāo)击纬,根據(jù)反正切函數(shù)來(lái)得到具體的弧度鼎姐。

int dy = Math.abs(CIRCLEY - startY);
int dx = Math.abs(CIRCLEX - startX);
 angle = Math.atan(dy * 1.0 / dx);

ok,這里的startX,Y就是移動(dòng)過(guò)程中的坐標(biāo)。angle就是得到的對(duì)應(yīng)的弧度(角度)更振。

相關(guān)Path繪制

前面已經(jīng)提到在旋轉(zhuǎn)的過(guò)程中有兩套坐標(biāo)體系炕桨,一開(kāi)始我也很糾結(jié)這個(gè)坐標(biāo)體系要怎么確定,后面又恍然大悟肯腕,其實(shí)相當(dāng)于就是一三象限正比例增長(zhǎng)献宫,二四象限,反比例增長(zhǎng)实撒。

 flag = (startY - CIRCLEY  ) * (startX- CIRCLEX ) <= 0;
 //增加一個(gè)flag,用于判斷使用哪種坐標(biāo)體系姊途。

最最重要的來(lái)了,繪制相關(guān)的Path路徑知态!

 path.reset();
 if (flag) {
     //第一個(gè)點(diǎn)
 path.moveTo((float) (CIRCLEX - Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY - Math.cos(angle) * ORIGIN_RADIO));

 path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (startX - Math.sin(angle) * DRAG_RADIO), (float) (startY - Math.cos(angle) * DRAG_RADIO));
path.lineTo((float) (startX + Math.sin(angle) * DRAG_RADIO), (float) (startY + Math.cos(angle) * DRAG_RADIO));

path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (CIRCLEX + Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY + Math.cos(angle) * ORIGIN_RADIO));
path.close();
canvas.drawPath(path, paint);
 } else {
     //第一個(gè)點(diǎn)
     path.moveTo((float) (CIRCLEX - Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY + Math.cos(angle) * ORIGIN_RADIO));

     path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (startX - Math.sin(angle) * DRAG_RADIO), (float) (startY + Math.cos(angle) * DRAG_RADIO));
     path.lineTo((float) (startX + Math.sin(angle) * DRAG_RADIO), (float) (startY - Math.cos(angle) * DRAG_RADIO));

     path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (CIRCLEX + Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY - Math.cos(angle) * ORIGIN_RADIO));
     path.close();
     canvas.drawPath(path, paint);
 }

這里的代碼就是把圖片上相關(guān)的數(shù)學(xué)公式Java化而已捷兰!

到這里,其實(shí)主要的工作就完成的差不多了负敏!
接下來(lái)贡茅,設(shè)置paint 為填充的效果,最后再畫(huà)兩個(gè)圓

 paint.setStyle(Paint.Style.FILL)
 canvas.drawCircle(CIRCLEX, CIRCLEY, ORIGIN_RADIO, paint);//默認(rèn)的
 canvas.drawCircle(startX == 0 ? CIRCLEX : startX, startY == 0 ? CIRCLEY : startY, DRAG_RADIO, paint);//拖拽的

就可以繪制出想要的效果了!

這里不得不再說(shuō)說(shuō)onTouch的處理原在!

  case MotionEvent.ACTION_DOWN://有事件先攔截再說(shuō)S讶拧!
            getParent().requestDisallowInterceptTouchEvent(true);
            CurrentState = STATE_IDLE;
            animSetXY.cancel();
            startX = (int) ev.getX();
            startY = (int) ev.getRawY();
            break;

處理一下事件分發(fā)的坑庶柿!

測(cè)量和布局

這樣基本過(guò)得去了村怪,但是我們的布局什么的還沒(méi)有處理,math_parent是萬(wàn)萬(wàn)沒(méi)法使用到具體項(xiàng)目當(dāng)中去的浮庐!
測(cè)量的時(shí)候甚负,如果發(fā)現(xiàn)不是精準(zhǔn)模式,那么都手動(dòng)去計(jì)算出需要的寬度和高度审残。

 @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
    int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
    if (modeWidth == MeasureSpec.UNSPECIFIED || modeWidth == MeasureSpec.AT_MOST) {
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(DEFAULT_RADIO * 2, MeasureSpec.EXACTLY);
    }
    if (modeHeight == MeasureSpec.UNSPECIFIED || modeHeight == MeasureSpec.AT_MOST) {
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(DEFAULT_RADIO * 2, MeasureSpec.EXACTLY);
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

然后在布局變化時(shí)梭域,獲取相關(guān)坐標(biāo),確定初始圓心坐標(biāo):

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    CIRCLEX = (int) ((w) * 0.5 + 0.5);
    CIRCLEY = (int) ((h) * 0.5 + 0.5);
}

然后清單文件里面就可以這樣配置了:

 <com.lovejjfg.circle.DragBubbleView
    android:id="@+id/dbv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"/>

這樣之后搅轿,又會(huì)出現(xiàn)一個(gè)問(wèn)題病涨,那就是wrap_content 之后,這個(gè)View能繪制的區(qū)域只有自身那么大了璧坟,拖拽了都看不見(jiàn)了既穆!這個(gè)坑怎么辦呢赎懦,其實(shí)很簡(jiǎn)單,父布局加上android:clipChildren="false" 的屬性幻工!
這個(gè)坑也算是解決了@健!

相關(guān)狀態(tài)的確定

我們是不希望它可以無(wú)限的拖拽的囊颅,就是有一個(gè)拖拽的最遠(yuǎn)距離当悔,還有就是放手后的返回,爆裂踢代。那么對(duì)應(yīng)的盲憎,這里需要確定幾種狀態(tài):

  private final static int STATE_IDLE = 1;//靜止的狀態(tài)
    private final static int STATE_DRAG_NORMAL = 2;//正在拖拽的狀態(tài)
    private final static int STATE_DRAG_BREAK = 3;//斷裂后的拖拽狀態(tài)
    private final static int STATE_UP_BREAK = 4;//放手后的爆裂的狀態(tài)
    private final static int STATE_UP_BACK = 5;//放手后的沒(méi)有斷裂的返回的狀態(tài)
    private final static int STATE_UP_DRAG_BREAK_BACK = 6;//拖拽斷裂又返回的狀態(tài)
    private int CurrentState = STATE_IDLE;
    
private int MIN_RADIO = (int) (ORIGIN_RADIO * 0.4);//最小半徑
    private int MAXDISTANCE = (int) (MIN_RADIO * 13);//最遠(yuǎn)的拖拽距離

確定好這些之后,在move的時(shí)候奸鬓,就要去做相關(guān)判斷了:

  case MotionEvent.ACTION_MOVE://移動(dòng)的時(shí)候
            startX = (int) ev.getX();
            startY = (int) ev.getY();

            updatePath();
            invalidate();
            break;

private void updatePath() {
    int dy = Math.abs(CIRCLEY - startY);
    int dx = Math.abs(CIRCLEX - startX);

    double dis = Math.sqrt(dy * dy + dx * dx);
    if (dis <= MAXDISTANCE) {//增加的情況焙畔,原始半徑減小
        if (CurrentState == STATE_DRAG_BREAK || CurrentState == STATE_UP_DRAG_BREAK_BACK) {
            CurrentState = STATE_UP_DRAG_BREAK_BACK;
        } else {
            CurrentState = STATE_DRAG_NORMAL;
        }
        ORIGIN_RADIO = (int) (DEFAULT_RADIO - (dis / MAXDISTANCE) * (DEFAULT_RADIO - MIN_RADIO));
        Log.e(TAG, "distance: " + (int) ((1 - dis / MAXDISTANCE) * MIN_RADIO));
        Log.i(TAG, "distance: " + ORIGIN_RADIO);
    } else {
        CurrentState = STATE_DRAG_BREAK;
    }
//        distance = dis;
    flag = (startY - CIRCLEY) * (startX - CIRCLEX) <= 0;
    Log.i("TAG", "updatePath: " + flag);
    angle = Math.atan(dy * 1.0 / dx);
}

updatePath() 的方法之前已經(jīng)看過(guò)部分了,這次的就是完整的串远。
這里做的事就是根據(jù)拖拽的距離更改相關(guān)的狀態(tài)宏多,并根據(jù)百分比來(lái)修改原始圓形的半徑大小。還有就是之前介紹的確定相關(guān)的弧度澡罚!

最后放手的時(shí)候:

   case MotionEvent.ACTION_UP:
            if (CurrentState == STATE_DRAG_NORMAL) {
                CurrentState = STATE_UP_BACK;
                valueX.setIntValues(startX, CIRCLEX);
                valueY.setIntValues(startY, CIRCLEY);
                animSetXY.start();
            } else if (CurrentState == STATE_DRAG_BREAK) {
                CurrentState = STATE_UP_BREAK;
                invalidate();
            } else {
                CurrentState = STATE_UP_DRAG_BREAK_BACK;
                valueX.setIntValues(startX, CIRCLEX);
                valueY.setIntValues(startY, CIRCLEY);
                animSetXY.start();
            }
            break;

自動(dòng)返回這里使用到的 ValueAnimator伸但,

 animSetXY = new AnimatorSet();

    valueX = ValueAnimator.ofInt(startX, CIRCLEX);
    valueY = ValueAnimator.ofInt(startY, CIRCLEY);
    animSetXY.playTogether(valueX, valueY);
    valueX.setDuration(500);
    valueY.setDuration(500);
    valueX.setInterpolator(new OvershootInterpolator());
    valueY.setInterpolator(new OvershootInterpolator());
    valueX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            startX = (int) animation.getAnimatedValue();
            Log.e(TAG, "onAnimationUpdate-startX: " + startX);
            invalidate();
        }

    });
    valueY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            startY = (int) animation.getAnimatedValue();
            Log.e(TAG, "onAnimationUpdate-startY: " + startY);
            invalidate();

        }
    });

最后在看看完整的onDraw方法吧!

 @Override
protected void onDraw(Canvas canvas) {
    switch (CurrentState) {
        case STATE_IDLE://空閑狀態(tài)留搔,就畫(huà)默認(rèn)的圓
            if (showCircle) {
                canvas.drawCircle(CIRCLEX, CIRCLEY, ORIGIN_RADIO, paint);//默認(rèn)的
            }
            break;
        case STATE_UP_BACK://執(zhí)行返回的動(dòng)畫(huà)
        case STATE_DRAG_NORMAL://拖拽狀態(tài) 畫(huà)貝塞爾曲線和兩個(gè)圓
            path.reset();
            if (flag) {
                //第一個(gè)點(diǎn)
                path.moveTo((float) (CIRCLEX - Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY - Math.cos(angle) * ORIGIN_RADIO));

                path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (startX - Math.sin(angle) * DRAG_RADIO), (float) (startY - Math.cos(angle) * DRAG_RADIO));
                path.lineTo((float) (startX + Math.sin(angle) * DRAG_RADIO), (float) (startY + Math.cos(angle) * DRAG_RADIO));

                path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (CIRCLEX + Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY + Math.cos(angle) * ORIGIN_RADIO));
                path.close();
                canvas.drawPath(path, paint);
            } else {
                //第一個(gè)點(diǎn)
                path.moveTo((float) (CIRCLEX - Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY + Math.cos(angle) * ORIGIN_RADIO));

                path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (startX - Math.sin(angle) * DRAG_RADIO), (float) (startY + Math.cos(angle) * DRAG_RADIO));
                path.lineTo((float) (startX + Math.sin(angle) * DRAG_RADIO), (float) (startY - Math.cos(angle) * DRAG_RADIO));

                path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (CIRCLEX + Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY - Math.cos(angle) * ORIGIN_RADIO));
                path.close();
                canvas.drawPath(path, paint);
            }
            if (showCircle) {
                canvas.drawCircle(CIRCLEX, CIRCLEY, ORIGIN_RADIO, paint);//默認(rèn)的
                canvas.drawCircle(startX == 0 ? CIRCLEX : startX, startY == 0 ? CIRCLEY : startY, DRAG_RADIO, paint);//拖拽的
            }
            break;

        case STATE_DRAG_BREAK://拖拽到了上限更胖,畫(huà)拖拽的圓:
        case STATE_UP_DRAG_BREAK_BACK:
            if (showCircle) {
                canvas.drawCircle(startX == 0 ? CIRCLEX : startX, startY == 0 ? CIRCLEY : startY, DRAG_RADIO, paint);//拖拽的
            }
            break;

        case STATE_UP_BREAK://畫(huà)出爆裂的效果
            canvas.drawCircle(startX - 25, startY - 25, 10, circlePaint);
            canvas.drawCircle(startX + 25, startY + 25, 10, circlePaint);
            canvas.drawCircle(startX, startY - 25, 10, circlePaint);
            canvas.drawCircle(startX, startY, 18, circlePaint);
            canvas.drawCircle(startX - 25, startY, 10, circlePaint);
            break;

    }


}

到這里,成品就出來(lái)了8粝浴却妨!

總結(jié):

1、確定默認(rèn)圓形的坐標(biāo)括眠;
2彪标、根據(jù)move的情況,實(shí)時(shí)獲取最新的坐標(biāo)掷豺,根據(jù)移動(dòng)的距離(確定出角度)捞烟,更新相關(guān)的狀態(tài),畫(huà)出相關(guān)的Path路徑当船。超出上限题画,不再畫(huà)Path路徑。
3德频、松手時(shí)苍息,根據(jù)相關(guān)的狀態(tài),要么帶Path路徑執(zhí)行動(dòng)畫(huà)返回,要么不帶Path路徑直接返回档叔,要么直接爆裂桌粉!

下一篇 Android drawTextOnPath 水果忍者跳動(dòng)的文字

相關(guān)源碼請(qǐng)移步Github,喜歡就請(qǐng)Start或者 fork一下吧衙四,有問(wèn)題歡迎留言或者issue。患亿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末传蹈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子步藕,更是在濱河造成了極大的恐慌惦界,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咙冗,死亡現(xiàn)場(chǎng)離奇詭異沾歪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)雾消,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)灾搏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人立润,你說(shuō)我怎么就攤上這事狂窑。” “怎么了桑腮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵泉哈,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我破讨,道長(zhǎng)丛晦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任提陶,我火速辦了婚禮烫沙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘搁骑。我一直安慰自己斧吐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布仲器。 她就那樣靜靜地躺著煤率,像睡著了一般。 火紅的嫁衣襯著肌膚如雪乏冀。 梳的紋絲不亂的頭發(fā)上蝶糯,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音辆沦,去河邊找鬼昼捍。 笑死识虚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的妒茬。 我是一名探鬼主播担锤,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼乍钻!你這毒婦竟也來(lái)了肛循?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤银择,失蹤者是張志新(化名)和其女友劉穎多糠,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體浩考,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夹孔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了析孽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搭伤。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绿淋,靈堂內(nèi)的尸體忽然破棺而出闷畸,到底是詐尸還是另有隱情,我是刑警寧澤吞滞,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布佑菩,位于F島的核電站,受9級(jí)特大地震影響裁赠,放射性物質(zhì)發(fā)生泄漏殿漠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一佩捞、第九天 我趴在偏房一處隱蔽的房頂上張望绞幌。 院中可真熱鬧,春花似錦一忱、人聲如沸莲蜘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)票渠。三九已至,卻和暖如春芬迄,著一層夾襖步出監(jiān)牢的瞬間问顷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杜窄,地道東北人肠骆。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像塞耕,于是被迫代替她去往敵國(guó)和親蚀腿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

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