內(nèi)化篇--RecyclerView的item點擊長按拖拽移動,水平滑動刪除

首先聲明烈拒,內(nèi)化篇都是本人重寫網(wǎng)絡上的精品文章圆裕,是為了向?qū)W習他人進而內(nèi)化為自己的知識。如果需要引用或者學習請參考原作者原著文章荆几,地址為:http://www.reibang.com/p/70788a7a5547吓妆。再次感謝作者OCNYang提供的精品文章。

image.png

主界面是兩個按鈕吨铸,點擊會跳轉(zhuǎn)到相應的不同的界面行拢。

startActivity(new Intent(this,ListViewActivity.class));

很喜歡這種簡潔的寫法,看起來很清爽诞吱。

GIF.gif

LIST VIEW跳轉(zhuǎn)

點擊LIST VIEW跳轉(zhuǎn)過來時一個簡單的RecyclerView舟奠,長按會有背景加深顯示,還可以拖拽移動位置房维。省略一些常規(guī)的知識沼瘫,這里用的較少的知識點歸納為一下幾點:
1.在代碼中添加分割線,而不是在xml文件中去操作(添加邊距握巢,或者單獨布局一個view去顯示分割線);
2.item長按可以拖拽移動位置松却;
3.item的長按的背景加深暴浦;
4.item水平滑動可實現(xiàn)刪除溅话。

重點知識點詳解

1.代碼添加分割線

mLinearRecyclerView.addItemDecoration(new DividerListItemDecoration(this,LinearLayoutManager.VERTICAL));

而這個DividerListItemDecoration類是系統(tǒng)沒有的,我們需要自己去創(chuàng)建歌焦,代碼如下:

class DividerListItemDecoration extends RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerListItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public DividerListItemDecoration(Context context, int orientation, int drawableId) {
        mDivider = ContextCompat.getDrawable(context, drawableId);
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }

    }


    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

這個類需要繼承RecyclerView.ItemDecoration飞几。這樣就實現(xiàn)了分割線的添加。
需要在添加分割線后加入下列代碼:

mLinearRecyclerView.setHasFixedSize(true);

因為當我們確定Item的改變不會影響RecyclerView的寬高的時候可以設(shè)置setHasFixedSize(true)独撇,并通過Adapter的增刪改插方法去刷新RecyclerView屑墨,而不是通過notifyDataSetChanged()。(其實可以直接設(shè)置為true纷铣,當需要改變寬高的時候就用notifyDataSetChanged()去整體刷新一下)卵史,這是網(wǎng)上找到的答案,大概意思就是這樣時固定item的寬高搜立,可以避免重復的計算以躯,提高性能,有空深入研究一下啄踊。

2.item長按可以拖拽移動位置

核心代碼

//        方便來控制item的拖拽和滑動刪除
        RecycItemTouchHelperCallback itemTouchHelperCallback = new RecycItemTouchHelperCallback(mRecyAdapter);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
//        具備了響應相關(guān)touchEvent的能力
        itemTouchHelper.attachToRecyclerView(mLinearRecyclerView);

先完整的貼出重要的自定義的類

public class RecycItemTouchHelperCallback extends ItemTouchHelper.Callback {
    RecyclerView.Adapter mAdapter;
    boolean isSwipeEnable;
    boolean isFirstDragUnable;

    public RecycItemTouchHelperCallback(RecyAdapter recyAdapter) {
        mAdapter = recyAdapter;
        isSwipeEnable = true;
        isFirstDragUnable = false;
    }

    public RecycItemTouchHelperCallback(RecyAdapter recyAdapter, boolean isSwipeEnable, boolean isFirstDragUnable) {
        mAdapter = recyAdapter;
        this.isSwipeEnable = isSwipeEnable;
        this.isFirstDragUnable = isFirstDragUnable;
    }
//    確定可以移動的方向
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
//            如果是網(wǎng)格就可以上下左右移動
//            dragFlags是拖拽標志
            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
//            swipeFlags是滑動標志忧设,當swipeFlags設(shè)置為0時不考慮滑動相關(guān)的操作
            int swipeFlags = 0;
            return makeMovementFlags(dragFlags, swipeFlags);
        } else {
//            如果是線性只能上下滑動
            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
            return makeMovementFlags(dragFlags,swipeFlags);
        }
    }
//    拖拽的過程中不斷調(diào)用的方法
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
       int fromPosition = viewHolder.getAdapterPosition();
        int toPosition = target.getAdapterPosition();
        if (isFirstDragUnable && toPosition == 0) {
            return false;
        }
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
//                數(shù)據(jù)一般都在adapter中,所以要傳入adapter
                Collections.swap(((RecyAdapter) mAdapter).getDataList(),i, i+1); //TODO
            }
        }else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(((RecyAdapter) mAdapter).getDataList(),i, i-1);
            }
        }
//        數(shù)據(jù)的更新也需要用到adapter
        mAdapter.notifyItemMoved(fromPosition,toPosition);
        return true;
    }
//    滑動移除的方法
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        int adapterPosition = viewHolder.getAdapterPosition();
        mAdapter.notifyItemRemoved(adapterPosition);
        ((RecyAdapter) mAdapter).getDataList().remove(adapterPosition);
    }
//    給選中的item添加背景顏色
    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
//        IDLE閑置的
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
        }
        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        viewHolder.itemView.setBackgroundColor(Color.WHITE);
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return !isFirstDragUnable;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return isSwipeEnable;
    }
}

實現(xiàn)長按拖拽移動需要重寫getMovementFlags()和onMove()颠通,這兩個方法址晕,其中g(shù)etMovementFlags是為了確認可以移動的方向,需要做判斷顿锰,如果是網(wǎng)格就可以上下左右移動谨垃,如果是線性只能上下滑動。onMove是在移動的過程中不斷被調(diào)用的方法撵儿,其中主要是判斷初始位置中終止位置乘客,讓后做相應的處理。

3.item的長按的背景加深

//    給選中的item添加背景顏色
    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
//        IDLE閑置的
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
        }
        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        viewHolder.itemView.setBackgroundColor(Color.WHITE);
    }

4.item水平滑動可實現(xiàn)刪除

//    滑動移除的方法
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        int adapterPosition = viewHolder.getAdapterPosition();
        mAdapter.notifyItemRemoved(adapterPosition);
        ((RecyAdapter) mAdapter).getDataList().remove(adapterPosition);
    }

刪除一個item最重要的就是要先得到這個item的position淀歇,通過getAdapterPosition()得到item的position易核,然后在相應的adapter和集合中都刪除對應position的item即可。

點擊事件

既然是item當然少不了有點擊事件浪默,RecyclerView的api雖然沒有提供onItemClickListener但是提供了addOnItemTouchListener()方法牡直,既然可以添加觸摸監(jiān)聽,那么我們完全可以獲取觸摸手勢來識別點擊事件纳决,然后通過觸摸坐標來判斷點擊的事哪個item碰逸。
直接傳入OnItemTouchListener() 是行不通的,因為我們無法得到item的position阔加,從而也就無法確認是哪一個item被點擊饵史,這里我們就自定義一個類去實現(xiàn)OnItemTouchListener() 這個接口,然后通過GestureDetectorCompat根據(jù)坐標來得到具體的item,從而對相應的UI做出處理胳喷。

//行不通湃番,因為無法得到item的position,無法確定是哪個item
mLinearRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                return false;
            }

            @Override
            public void onTouchEvent(RecyclerView rv, MotionEvent e) {

            }

            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

            }
        });

下面是自定義的OnRecyclerItemClickListener 類:

public abstract class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
//    手勢探測器來探測屏幕事件
    private GestureDetectorCompat mGestureDetectorCompat;
    private RecyclerView mRecyclerView;

    public OnRecyclerItemClickListener(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        mGestureDetectorCompat = new GestureDetectorCompat(mRecyclerView.getContext(),new ItemTouchHelperGestureListener());
    }



    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        mGestureDetectorCompat.onTouchEvent(e);
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        mGestureDetectorCompat.onTouchEvent(e);
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
//    抽象方法吭露,實現(xiàn)類必須要實現(xiàn)
    public abstract void onItemClick(RecyclerView.ViewHolder viewHolder);
    public abstract void onLongClick(RecyclerView.ViewHolder viewHolder);

//    SimpleOnGestureListener來識別手勢事件的種類吠撮,調(diào)用我們相應的回調(diào)方法
    private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
//        簡單的點擊
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            View childViewUnder = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
            if (childViewUnder != null) {
                RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(childViewUnder);
                onItemClick(childViewHolder);
            }
            return true;
        }
//        長按
        @Override
        public void onLongPress(MotionEvent e) {
            View childViewUnder = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
            if (childViewUnder != null ) {
                RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(childViewUnder);
                onLongClick(childViewHolder);
            }
        }
    }
}

其中主要是要自定義一個類去繼承GestureDetector.SimpleOnGestureListener(很奇怪,明明起名字是一個Listener這要需要繼承讲竿,很容易引起誤解)泥兰,這里主要是通過MotionEvent來獲取到點擊的坐標,通過坐標得到相應的view题禀,讓后通過這個view找到相應的ViewHolder鞋诗,讓后調(diào)用抽象方法(抽象方法是為了規(guī)定實現(xiàn)類必須實現(xiàn)這個抽象方法)。
在addOnItemTouchListener()中添加自定義的OnRecyclerItemClickListener(通過GestureDetectorCompat 來獲取到item對應的viewHolder從而來操作UI)投剥。

mLinearRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mLinearRecyclerView) {
//            定義抽象方法是為了讓實現(xiàn)類必須實現(xiàn)這個方法
            @Override
            public void onItemClick(RecyclerView.ViewHolder viewHolder) {
//                要給相應的view設(shè)置屬性就要先得到擁有該view的ViewHolder
                RecyAdapter.ViewHolder viewHolder1 = (RecyAdapter.ViewHolder) viewHolder;
                String tvString = viewHolder1.mTextView.getText().toString();
                Toast.makeText(ListViewActivity.this,"內(nèi)化后 *- -* 逗逗" + tvString, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onLongClick(RecyclerView.ViewHolder viewHolder) {
                Toast.makeText(ListViewActivity.this,"內(nèi)化后 *- -* 討厭师脂,不要老是摸人家啦。江锨。吃警。", Toast.LENGTH_SHORT).show();
            }
        });

這時候不僅能夠?qū)崿F(xiàn)拖拽又可以實現(xiàn)點擊彈出吐司(當然也可以根據(jù)具體情況操作UI),如下圖:

GIF.gif

但是item的拖拽啄育,水平滑動刪除酌心,和響應點擊事件是有區(qū)別的,如下圖:

無標題.png

Grid View 跳轉(zhuǎn)

GridViewActivity的操作和ListViewActivity大體一致挑豌,并可以復用ListViewActivity其中的方法安券,但是要主要添加分割線的那個類需要自己重新定義,因為網(wǎng)格的分割線是線性的分割線是不同的氓英。我原以為只要有了下面的代碼就可以實現(xiàn)長按拖拽了

RecycItemTouchHelperCallback itemTouchHelperCallback = new RecycItemTouchHelperCallback(mRecyAdapter1,false,true);
        final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
        itemTouchHelper.attachToRecyclerView(mRecyclerView);

因為在ListViewActivity中是這樣的侯勉,拖拽移動和點擊是分開的,但是這里不是的铝阐,如果只是執(zhí)行了上面的代碼址貌,是不能實現(xiàn)長按拖拽的。
必須還要執(zhí)行下面的代碼:

mRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mRecyclerView) {
            @Override
            public void onItemClick(RecyclerView.ViewHolder viewHolder) {
                RecyAdapter.ViewHolder viewHolder1 = ((RecyAdapter.ViewHolder) viewHolder);
                String tvString = viewHolder1.mTextView.getText().toString();
                Toast.makeText(GridViewActivity.this,"內(nèi)化后*--*"+tvString,Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onLongClick(RecyclerView.ViewHolder viewHolder) {
                Toast.makeText(GridViewActivity.this,"內(nèi)化后*--*,不要老是摸人家了徘键。练对。。",Toast.LENGTH_SHORT).show();
                if (viewHolder.getLayoutPosition() != 0) {
                    //實現(xiàn)長按拖拽
                    itemTouchHelper.startDrag(viewHolder);
                }
            }
        });

這里必須要在長按的方法中 itemTouchHelper.startDrag(viewHolder)才能實現(xiàn)拖拽的效果吹害。


GIF.gif

如效果圖可以實現(xiàn)長按的拖拽移動螟凭,還有相應的UI處理,但是第一個item是固定的不能改變位置的它呀。

@Override
            public void onLongClick(RecyclerView.ViewHolder viewHolder) {
                Toast.makeText(GridViewActivity.this,"內(nèi)化后*--*,不要老是摸人家了螺男。棒厘。。",Toast.LENGTH_SHORT).show();
                if (viewHolder.getLayoutPosition() != 0) {
                    itemTouchHelper.startDrag(viewHolder);
                }
            }

一般認為這樣就可以了下隧,其實是不行的绊谭。這是原作者的回答:雖然我們通過上面兩步控制了首個 item 不能被長按拖曳,但是我們并沒有處理汪拥,別的 item 被拖曳到首個 item 的情況。那么如何才能讓首個 item 不被擠掉呢篙耗,這個也很簡單迫筑,只需要在 Callback 的 onMove() 方法中處理首個 item 被當著目標 item 的情況就行了。

//    拖拽的過程中不斷調(diào)用的方法
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
       int fromPosition = viewHolder.getAdapterPosition();
        int toPosition = target.getAdapterPosition();
//        第一個item不能拖動和改變位置
        if (isFirstDragUnable && toPosition == 0) {
            return false;
        }
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
//                數(shù)據(jù)一般都在adapter中宗弯,所以要傳入adapter
                Collections.swap(((RecyAdapter) mAdapter).getDataList(),i, i+1); //TODO
            }
        }else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(((RecyAdapter) mAdapter).getDataList(),i, i-1);
            }
        }
//        數(shù)據(jù)的更新也需要用到adapter
        mAdapter.notifyItemMoved(fromPosition,toPosition);
        return true;
    }

大功告成脯燃。
這里我還有疑問,為什么GridViewActivity不能像ListViewActivity那樣不用添加點擊事件就能拖動蒙保,必須要執(zhí)行itemTouchHelper.startDrag(viewHolder);時間原因下次再自習研究辕棚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市邓厕,隨后出現(xiàn)的幾起案子逝嚎,更是在濱河造成了極大的恐慌,老刑警劉巖详恼,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件补君,死亡現(xiàn)場離奇詭異,居然都是意外死亡昧互,警方通過查閱死者的電腦和手機挽铁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敞掘,“玉大人叽掘,你說我怎么就攤上這事【裂悖” “怎么了更扁?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茄菊。 經(jīng)常有香客問我疯潭,道長,這世上最難降的妖魔是什么面殖? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任竖哩,我火速辦了婚禮,結(jié)果婚禮上脊僚,老公的妹妹穿的比我還像新娘相叁。我一直安慰自己遵绰,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布增淹。 她就那樣靜靜地躺著椿访,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虑润。 梳的紋絲不亂的頭發(fā)上成玫,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音拳喻,去河邊找鬼哭当。 笑死,一個胖子當著我的面吹牛冗澈,可吹牛的內(nèi)容都是我干的钦勘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼亚亲,長吁一口氣:“原來是場噩夢啊……” “哼彻采!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捌归,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤肛响,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惜索,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體终惑,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年门扇,在試婚紗的時候發(fā)現(xiàn)自己被綠了雹有。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡臼寄,死狀恐怖霸奕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吉拳,我是刑警寧澤质帅,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站留攒,受9級特大地震影響煤惩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炼邀,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一魄揉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拭宁,春花似錦洛退、人聲如沸瓣俯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彩匕。三九已至,卻和暖如春媒区,著一層夾襖步出監(jiān)牢的瞬間驼仪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工袜漩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谅畅,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓噪服,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胜茧。 傳聞我的和親對象是個殘疾皇子粘优,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

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