自定義卡片效果的ViewGroup

不逼逼,看效果星澳!兩邊有點(diǎn)露出來(lái)的效果疚顷,比如騰訊視頻App的上方的效果,都是輕量級(jí)的控件禁偎,請(qǐng)勿見(jiàn)怪腿堤,總體時(shí)間花費(fèi)大約9個(gè)小時(shí),其中找Bug找了3個(gè)小時(shí)届垫,哈哈释液!

微信圖片_20170904213432.jpg
  • 第一個(gè)效果是正常的滑動(dòng)情況


    xiao.gif
  • 第二個(gè)效果是禁止滑動(dòng)情況全释,同時(shí)呢装处,有一個(gè)回彈的效果,四川話講這個(gè)很巴適


    xiao.gif

分享兩個(gè)東西

  • 今天發(fā)現(xiàn)的一個(gè)Android UI 開(kāi)發(fā)效率的 UI 庫(kù):https://github.com/QMUI/QMUI_Android
  • 這個(gè)我都不好意思分享,嘿嘿妄迁,周天就做這個(gè)寝蹈,做完了發(fā)現(xiàn)根本沒(méi)有什么東西可以分享,所以就寫了現(xiàn)在這個(gè)博客登淘,等我以后研究下hexo箫老,才來(lái)更新

寫在前面的話:如果我手寫慢一點(diǎn),多看看一下api黔州,我就不會(huì)把兩個(gè)api寫錯(cuò)了耍鬓,由于手滑寫錯(cuò)了,導(dǎo)致我這篇博客現(xiàn)在才來(lái)寫流妻,興奮感都快磨完了牲蜀。

72F75ABC3304DD06A39EB5A18180F6CE.gif
  • 這輩子我都不會(huì)忘記這個(gè)值了,getScaledTouchSlop()是一個(gè)距離绅这,表示滑動(dòng)的時(shí)候涣达,手的移動(dòng)要大于這個(gè)距離才開(kāi)始移動(dòng)控件。viewpager就是用這個(gè)距離來(lái)判斷用戶是否翻頁(yè)证薇,只不過(guò)呢
ViewConfiguration.get(mContext).getScaledTouchSlop()

原理如下: mTouchSlop = configuration.getScaledPagingTouchSlop();就是這個(gè)值度苔,但是你可能會(huì)說(shuō)有毛的的關(guān)系啊,別急



往ViewConfiguration類看記住這個(gè)值


image.png

看這個(gè)值mTouchSlop浑度,對(duì)吧只不過(guò)在ViewPager判斷是否需要移動(dòng)的時(shí)候寇窑,這個(gè)距離是*2。

image.png

由于我這里需要更高的精度俺泣,所以獲取了這個(gè)值getScaledTouchSlop()


  • 可千萬(wàn)不要拿到getScaledDoubleTapSlop()這個(gè)值了傲迫稀!
//第一次觸摸和第二次觸摸之間的距離,Distance in pixels between the first touch and second touch
   ViewConfiguration.get(mContext).getScaledDoubleTapSlop();

繼承ViewGroup,重寫構(gòu)造方法

public class CardViewPager extends ViewGroup{

 public CardViewPager(Context context) {
        this(context,null);
    }

    public CardViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
}

初始化init

   private void init(Context context) {
        mContext = context;
        //滑動(dòng)的對(duì)象
        mScroller = new Scroller(mContext);
        //getScaledTouchSlop是一個(gè)距離伏钠,表示滑動(dòng)的時(shí)候横漏,手的移動(dòng)要大于這個(gè)距離才開(kāi)始移動(dòng)控件。
        // 如果小于這個(gè)距離就不觸發(fā)移動(dòng)控件熟掂,如viewpager就是用這個(gè)距離來(lái)判斷用戶是否翻頁(yè)
//        mScaledDoubleTapSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
        mScaledDoubleTapSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
        //第一次觸摸和第二次觸摸之間的距離,Distance in pixels between the first touch and second touch
        ViewConfiguration.get(mContext).getScaledDoubleTapSlop();
        FIRST_width = dp2px(mContext, 10);
        TWO_GAP_WIDTH = FIRST_width * 2;
        THREE_GAP_WIDTH = FIRST_width * 3;
        FOUR_GAP_WIDTH = FIRST_width * 4;
    }

onMeasure,重寫測(cè)量這里記住widthMeasureSpec缎浇、heightMeasureSpec是一個(gè)32位的int值,其中高兩位是物理模式赴肚,低的30位才是控件的寬度和高度的信息素跺。

MeasureSpec.EXACTLY:父視圖希望子視圖的大小應(yīng)該是specSize中指定的。
MeasureSpec.AT_MOST:子視圖的大小最多是specSize中指定的值誉券,也就是說(shuō)不建議子視圖的大小超過(guò)specSize中給定的值指厌。
MeasureSpec.UNSPECIFIED:我們可以隨意指定視圖的大小。

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //這才是真正的寬度和高度
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heighSize = MeasureSpec.getSize(heightMeasureSpec);
        //設(shè)置測(cè)量的大小
        setMeasuredDimension(widthSize,heighSize);
        //測(cè)量孩子的大小
        mChildCount = getChildCount();
        for (int i=0;i<mChildCount;i++){
            //這里需要把模式也傳入進(jìn)去
            getChildAt(i).measure(widthMeasureSpec,heightMeasureSpec);
        }
    }

onLayout重新布局:將孩子的view布局踊跟,這里橫向的布局踩验,一個(gè)字View接著右邊,這是設(shè)計(jì)之初的方法,自己先明白到底是怎么樣布局,就好像我明白的方式箕憾,是個(gè)偉大的ui妹子說(shuō)牡借,看這個(gè)app,就是這樣袭异,哈哈

/**
     * @param changed
     * @param l 左上角的left
     * @param t top
     * @param r  右下角right
     * @param b bottom值
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        View child;
        int widthLeft=0;
        for (int i=0;i<mChildCount;i++){
            child = getChildAt(i);
            //得到第一個(gè)孩子的寬度钠龙,兩邊都減去了兩個(gè)參數(shù),記住是這個(gè)4倍值
            int measuredWidth = child.getMeasuredWidth() - FOUR_GAP_WIDTH;
            int measuredHeight = child.getMeasuredHeight();
            //是第一個(gè)孩子
            if (i==0){
                child.layout(widthLeft+TWO_GAP_WIDTH,0,widthLeft+TWO_GAP_WIDTH+measuredWidth,measuredHeight);
                //改變向左的值
                widthLeft+=measuredWidth+THREE_GAP_WIDTH;
            }else {
                child.layout(widthLeft, 0, widthLeft + measuredWidth, measuredHeight);
                widthLeft += measuredWidth + FIRST_width;
            }
        }
    }

效果雖然看了御铃,但是真正理解的layout的話碴里,還需明白其中的原理,這里我不講了的太細(xì)上真,獻(xiàn)上美圖一張并闲,嗦嘎,原理就是谷羞,不是每一個(gè)屏幕都在裝著一個(gè)我們的卡片帝火,我們每次移動(dòng)的時(shí)候,也不是移動(dòng)一個(gè)屏幕湃缎,而是通過(guò)運(yùn)算的方式犀填,移動(dòng)到恰好能夠看到兩邊10dp的值,這里的要轉(zhuǎn)成像素

 dp2px(mContext, 10);

image.png

關(guān)于像素px我還想說(shuō)說(shuō): context.getResources().getDisplayMetrics().density;density顯示器的邏輯密度嗓违,這是【獨(dú)立的像素密度單位(首先明白dp是個(gè)單位)】的一個(gè)縮放因子九巡,在屏幕密度大約為160dpi的屏幕上,一個(gè)dp等于一個(gè)px,這個(gè)提供了系統(tǒng)顯示器的一個(gè)基線. 例如:屏幕為240320的手機(jī)屏幕蹂季,其尺寸為 1.5"2" 也就是1.5英寸乘2英寸的屏幕 它的dpi(屏幕像素密度冕广,也就是每英寸的像素?cái)?shù),dpi是dot per inch的縮寫)大約就為160dpi偿洁, 所以在這個(gè)手機(jī)上dp和px的長(zhǎng)度(可以說(shuō)是長(zhǎng)度撒汉,最起碼從你的視覺(jué)感官上來(lái)說(shuō)是這樣的)是相等的。 因此在一個(gè)屏幕密度為160dpi的手機(jī)屏幕上density的值為1涕滋,而在120dpi的手機(jī)上為0.75等等.例如:一個(gè)240320的屏幕盡管他的屏幕尺寸為1.8"1.3",(我算了下這個(gè)的dpi大約為180dpi多點(diǎn))但是它的density還是1(也就是說(shuō)取了近似值) 然而睬辐,如果屏幕分辨率增加到320480 但是屏幕尺寸仍然保持1.5"2" 的時(shí)候(和最開(kāi)始的例子比較)
這個(gè)手機(jī)的density將會(huì)增加(可能會(huì)增加到1.5)

 public static int dp2px(Context context, float dpValue) {
        ///這個(gè)得到的不應(yīng)該叫做密度,應(yīng)該是密度的一個(gè)比例宾肺。不是真實(shí)的屏幕密度溯饵,
        /// 而是相對(duì)于某個(gè)值的屏幕密度。也可以說(shuō)是相對(duì)密度
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

攔截事件:當(dāng)大于了需要移動(dòng)控件的距離的話锨用,就需要把這個(gè)事件攔截自己處理丰刊。

 @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                int x = (int) ev.getX();
                mLastMotionX = x ;
                break;
            case MotionEvent.ACTION_MOVE:
                x= (int) ev.getX();
                //滑動(dòng)的距離
                int delX = mLastMotionX - x;
                //如果說(shuō)距離大于這個(gè)距離的話,就需要滾動(dòng)了增拥,攔截事件
                if (Math.abs(delX)>mScaledDoubleTapSlop){
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

處理事件:在down的事件一定需要攔截啄巧,才能記錄坐標(biāo)

返回值為True洪橘,代表攔截這次事件,直接進(jìn)入到ViewGroup的onTouchEvent中棵帽,就不會(huì)進(jìn)入到View的onTouchEvent了
返回值為False,代表不攔截這次事件渣玲,不進(jìn)入到ViewGroup的onTouchEvent中逗概,直接進(jìn)入到View的onTouchEvent中

 public boolean onTouchEvent(MotionEvent event) {
        //如果沒(méi)有孩子的話,不需要攔截
        if (getChildCount()==0){
            return false;
        }
        //監(jiān)聽(tīng)滑動(dòng)的速度
        obtainTracker(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()){
                    //停止動(dòng)畫
                    mScroller.abortAnimation();
                }
                int x = (int) event.getX();
                mLastMotionX=x;
                //不管怎么怎么樣這個(gè)事件都必須攔截
                return true;

            case MotionEvent.ACTION_MOVE:
                 x = (int) event.getX();
                int desX = mLastMotionX - x;
                //這個(gè)距離大于了屏幕的10/1的話忘衍,就給他賦值10/1
                if (!isAllowScroll&&desX>getWidth()/10){
                    desX=getWidth()/10;
                    //如果設(shè)置了不可以滑動(dòng)的逾苫,這個(gè)flag需要到up事件單獨(dú)處理
                    mCanScrolled = true;
                }
                //只需計(jì)算x的距離
                mVelocityTracker.computeCurrentVelocity(1000,ViewConfiguration.getMaximumFlingVelocity());
                mXVelocity = (int) mVelocityTracker.getXVelocity();
                //如果說(shuō)距離滑動(dòng)太小,或者是只有一個(gè)屏幕的話枚钓,就不往下去做操作了
                if (Math.abs(desX)<mScaledDoubleTapSlop||(desX>=0&&
                        mCurScreen==mChildCount-1)||(desX<=0&&mCurScreen==0)){
                    break;
                }

                //能到這里來(lái)的話铅搓,就必須往手指方向慢慢滾動(dòng)了
                scrollTo(getChildAt(mCurScreen).getLeft()+desX,0);
                break;
            case MotionEvent.ACTION_UP:
                //mXVelocity為正數(shù)的話,這個(gè)是往left滾
                if (isAllowScroll&&mXVelocity>MAX_VELOCITY_VALUE&&mCurScreen>0){
                    scrollScreen(mCurScreen-1);
                }else if (isAllowScroll&&mXVelocity<-MAX_VELOCITY_VALUE&&mCurScreen<mChildCount-1){
                    scrollScreen(mCurScreen+1);
               //當(dāng)設(shè)置了不能滑動(dòng)時(shí)候搀捷,并且手指滑動(dòng)的Move的距離已經(jīng)超過(guò)了屏幕的10/1星掰,有一個(gè)回彈的效果,左右搖擺
                }else if (mCanScrolled){
                    springToDestination();
                }else{
                    snapToDestination();
                }
                //最后不要忘記了釋放
                releaseVelocityTracker();
                break;
        }
        return super.onTouchEvent(event);
    }

滑動(dòng)到指定的屏幕,在記住兩個(gè)地方嫩舟,就不需要滑動(dòng)了氢烘,一個(gè)是在最右和最左端。

 private void scrollScreen(int whichScreen) {
        //防止超出了最大的孩子的數(shù)量
        int min = Math.min(whichScreen, mChildCount - 1);
        whichScreen = Math.max(0, min);
        //getScrollX() 就是當(dāng)前view的左上角相對(duì)于母視圖的左上角的X軸偏移量家厌。
        //在這里當(dāng)getScrollX==0的時(shí)候播玖,等于后面的whichScreen*getWidth()那么就滑動(dòng)到第一頁(yè)了
        //后續(xù)就不需要滑動(dòng)了,也不需要重新繪制了
        // TODO: 2017/9/3 這里只在最左不能進(jìn)去滑動(dòng)了饭于,其實(shí)在最右端也是不能夠去滑動(dòng)了蜀踏,帶解決
        if (getScrollX()!=whichScreen*getWidth()){
            int deltaX = whichScreen * (getWidth() - THREE_GAP_WIDTH) - getScrollX();
            mCurScreen = whichScreen;
            mScroller.startScroll(getScrollX(), 0, deltaX, 0, Math.abs(deltaX));
            invalidate();
        }
    }

但是在這里我留下一個(gè)問(wèn)題,但是在這里我留下一個(gè)問(wèn)題在我的手機(jī)上我測(cè)試了1到5個(gè)孩子的情況分別數(shù)據(jù)如下:
getScrollX()和whichScreen*getWidth()
1個(gè)屏幕是0 0--------0
2個(gè)屏幕是90 990 -------1080
3個(gè)屏是 120
4個(gè)屏 =270 2970 -------3240
5個(gè)屏 =380 3960 -------4320
當(dāng)我們滑動(dòng)到最有端的時(shí)候掰吕,其實(shí)也是不能夠去滑動(dòng)了果覆,但是我這個(gè)方法呢是能夠 走到if當(dāng)中的,而且對(duì)應(yīng)關(guān)系也不太明確殖熟,這個(gè)問(wèn)題我還得想想随静。

還需要理解一個(gè)東西getScrollX()到底是什么值?再次獻(xiàn)上我的美作吗讶,哈哈燎猛,反正我是明白了,我怕講不明白照皆,所以先看圖重绷,然后抓日記,一下就明白!

image.png

監(jiān)聽(tīng)滑動(dòng)的速度膜毁,在上篇筆鋒效果里面有講到過(guò)昭卓,還是Viewpager里面的東西,記住要釋放這個(gè)算是監(jiān)聽(tīng)吧愤钾!

     //監(jiān)聽(tīng)滑動(dòng)的速度
        obtainTracker(event);

    private void obtainTracker(MotionEvent event) {
        if (mVelocityTracker==null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        //綁定事件
        mVelocityTracker.addMovement(event);
    }
  /**
     * 釋放監(jiān)聽(tīng)滑動(dòng)速度方法
     */
    private void releaseVelocityTracker() {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

其實(shí)你就把上面的工作全部都做好了,你會(huì)發(fā)現(xiàn)還是不能夠翻頁(yè)候醒,來(lái)吧去Viewpager看看能颁,再去度娘看看

  /**
     * 計(jì)算滾動(dòng)的位置
     */
    @Override
    public void computeScroll() {
        super.computeScroll();
        //返回值為boolean,mScroller.computeScrollOffset()==true說(shuō)明滾動(dòng)尚未完成倒淫,false說(shuō)明滾動(dòng)已經(jīng)完成伙菊。
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }

    }

image.png

個(gè)人翻譯就是在viewpager中需要重新計(jì)算滑動(dòng)的位置


image.png

回彈滑動(dòng)目的屏,這里就是需要有點(diǎn)動(dòng)畫的效果,先回到原來(lái)的位置敌土,然后左右搖擺搖擺镜硕!

/**
     * 回彈滑動(dòng)目的屏
     */
    private void springToDestination() {
        System.out.println("shiming  ==springToDestination");
        int screenWidth = getWidth();
        int whichScreen = (getScrollX() + screenWidth / 2) / screenWidth;
        whichScreen = Math.max(0, Math.min(whichScreen, mChildCount - 1));
        final int deltaX = whichScreen * (getWidth() - THREE_GAP_WIDTH) - getScrollX();
        mCurScreen = whichScreen;
        //先給我滾動(dòng)到原來(lái)的位置
        springToScroll(deltaX * 1.0f, Math.abs(deltaX));
        //向右的給我擺動(dòng)兩下
        postDelayed(new Runnable() {
            @Override
            public void run() {
                springToScroll(-deltaX * 0.3f, Math.abs(deltaX));
            }
        }, Math.abs(deltaX));
        //讓后給我向左擺動(dòng)兩下
        postDelayed(new Runnable() {
            @Override
            public void run() {
                springToScroll(deltaX * 0.3f, Math.abs(deltaX));
            }
        }, Math.abs(deltaX * 2));
        mCanScrolled = false;
    }

 /**
     *  getScrollX() 水平方向滾動(dòng)的偏移值,以像素為單位返干。正值表明滾動(dòng)將向左滾動(dòng)
       startY 垂直方向滾動(dòng)的偏移值兴枯,以像素為單位。正值表明滾動(dòng)將向上滾動(dòng)
       (int) deltaX 水平方向滑動(dòng)的距離矩欠,正值會(huì)使?jié)L動(dòng)向左滾動(dòng)
       0  垂直方向滑動(dòng)的距離财剖,正值會(huì)使?jié)L動(dòng)向上滾動(dòng)
     * @param deltaX
     * @param duration
     */
    private void springToScroll(float deltaX, int duration) {
        mScroller.startScroll(getScrollX(), 0, (int) deltaX, 0, duration);
        invalidate();
    }

好了,以上癌淮,我寫的寫的都要睡早了峰伙,代碼有些注釋還比較詳細(xì)一點(diǎn),如有需要看代碼吧该默,由于工程邏輯上瞳氓,還有很多復(fù)雜的代碼,我這里就提取了一部分栓袖,以供學(xué)習(xí)之用匣摘,謝謝!

地址Git:https://github.com/Shimingli/CardViewPager

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末裹刮,一起剝皮案震驚了整個(gè)濱河市音榜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捧弃,老刑警劉巖赠叼,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異违霞,居然都是意外死亡嘴办,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門买鸽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)涧郊,“玉大人,你說(shuō)我怎么就攤上這事眼五∽彼遥” “怎么了彤灶?”我有些...
    開(kāi)封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)批旺。 經(jīng)常有香客問(wèn)我幌陕,道長(zhǎng),這世上最難降的妖魔是什么汽煮? 我笑而不...
    開(kāi)封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任搏熄,我火速辦了婚禮,結(jié)果婚禮上逗物,老公的妹妹穿的比我還像新娘。我一直安慰自己瑟俭,他們只是感情好翎卓,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著摆寄,像睡著了一般失暴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上微饥,一...
    開(kāi)封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天逗扒,我揣著相機(jī)與錄音,去河邊找鬼欠橘。 笑死矩肩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肃续。 我是一名探鬼主播黍檩,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼始锚!你這毒婦竟也來(lái)了刽酱?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瞧捌,失蹤者是張志新(化名)和其女友劉穎棵里,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體姐呐,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡殿怜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了曙砂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稳捆。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖麦轰,靈堂內(nèi)的尸體忽然破棺而出乔夯,到底是詐尸還是另有隱情砖织,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布末荐,位于F島的核電站侧纯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏甲脏。R本人自食惡果不足惜眶熬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望块请。 院中可真熱鬧娜氏,春花似錦、人聲如沸墩新。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)海渊。三九已至绵疲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間臣疑,已是汗流浹背盔憨。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留讯沈,地道東北人郁岩。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像缺狠,于是被迫代替她去往敵國(guó)和親驯用。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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