(转)RecyclerView常用功能

RecyclerView是support:recyclerview-v7中提供的控件,最低兼容到android 3.0版本。

官方介绍RecyclerView为在有限的窗口展现大量数据的控件。拥有类似功能的控件有ListView、GridView以及被Google遗弃的Gallery等,为毛已经有了它们,Google还推出RecyclerView呢,那就要说说RecyclerView所具有的一些优势了。

那RecyclerView到底有啥优势呢?总结起来六颗字:低耦合高类聚。RecyclerView已经标准化ViewHolder,我们自定义的ViewHoler需要继承 RecyclerView.ViewHolder,然后在构造方法中初始化控件,后面会有具体介绍。通过设置不同的LayoutManager,以及结合ItemDecoration , ItemAnimator,ItemTouchHelper,可以实现非常炫酷的效果,这些是ListView等控件难以企及的。

基本使用:

1.使用前需要在在gradle中添加依赖

`implementation 'com.android.support:recyclerview-v7:27.0.2'  `

2.编写代码,首先我们需要在Xml中写RecyclerView的布局,

```

android:id="@+id/recyclerView"  

android:layout_width="match_parent"  

android:layout_height="match_parent"/>    

```

然后在activity中获取RecyclerView,并设置LayoutManager以及adapter

//通过findViewById拿到RecyclerView实例  

`mRecyclerView =   findViewById(R.id.recyclerView);  `

//设置RecyclerView管理器  

mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));  

//初始化适配器  

mAdapter =new MyRecyclerViewAdapter(list);   

//设置添加或删除item时的动画,这里使用默认动画  

mRecyclerView.setItemAnimator(new DefaultItemAnimator());  

//设置适配器  

mRecyclerView.setAdapter(mAdapter);  

下面是MyRecyclerViewAdapter的代码:

[java] view plain copy

package com.sharejoys.recyclerviewdemo.actvity;  


import android.support.v7.widget.RecyclerView;  

import android.view.LayoutInflater;  

import android.view.View;  

import android.view.ViewGroup;  

import android.widget.TextView;  


import com.sharejoys.recyclerviewdemo.R;  


import java.util.List;  


/**

 * Created by 青青-子衿 on 2018/1/15.

 */  



public class MyRecyclerViewAdapterextends RecyclerView.Adapter {  

private List list;  


public MyAdapter(List list) {  

this.list = list;  

    }  


@Override  

public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_base_use, parent,false);  

MyAdapter.ViewHolder viewHolder =new MyAdapter.ViewHolder(view);  

return viewHolder;  

    }  


@Override  

public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {  

        holder.mText.setText(list.get(position));  

    }  


@Override  

public int getItemCount() {  

return list.size();  

    }  


class ViewHolder extends RecyclerView.ViewHolder {  

        TextView mText;  

        ViewHolder(View itemView) {  

super(itemView);  

            mText = itemView.findViewById(R.id.item_tx);  

        }  

    }  

}  

这里item_normal的布局也非常简单

[html] view plain copy


xmlns:android="http://schemas.android.com/apk/res/android"  

android:layout_width="match_content"  

android:layout_height="wrap_content"  

android:orientation="vertical">  


android:id="@+id/item_tx"  

android:layout_width="match_content"  

android:layout_height="wrap_content"  

android:gravity="center"  

android:padding="10dp"  

android:layout_gravity="center_horizontal"  

android:text="Item"/>  



然后我们运行效果如下

从例子也可以看出来,RecyclerView的用法并不比ListView复杂,反而更灵活好用,它将数据、排列方式、数据的展示方式都分割开来,因此可定制型,自定义的形式也非常多,非常灵活。

设置横向布局:

[java] view plain copy

mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));  

设置网格布局:

[java] view plain copy

mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));  

设置瀑布流:

[java] view plain copy

mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));  

如果第二个参数可以设置为横向的,则效果如下:

从以上可知,我们可以通过设置不同的管理器,实现不同的效果

LinearLayoutManager:以线性布局展示,可以设置横向和纵向

GridLayoutManager:以网格形式展示,类似GridView效果

StaggeredGridLayoutManager:以瀑布流形式的效果

RecyclerView条目之间默认没有分割线,那是否可以像ListView一样设置divider以及dividerHight搞一条分割线出来呢,答案是不可以的,google并没有提供这样的属性。但是谷歌为我们提供了可以定制的解决办法,那就是以下要说ItemDecoration

利用ItemDecoration实现条目分割线

ItemDecoration是谷歌定义的可用于画分割线的类, 是抽象的,需要我们自己去实现

[java] view plain copy

/**

   * An ItemDecoration allows the application to add a special drawing and layout offset

   * to specific item views from the adapter's data set. This can be useful for drawing dividers

   * between items, highlights, visual grouping boundaries and more.

   *

   * 

All ItemDecorations are drawn in the order they were added, before the item

   * views (in {@link ItemDecoration#onDraw(Canvas, RecyclerView, RecyclerView.State) onDraw()}

   * and after the items (in {@link ItemDecoration#onDrawOver(Canvas, RecyclerView,

   * RecyclerView.State)}.

   */  

public abstract static class ItemDecoration {  

public void onDraw(Canvas c, RecyclerView parent, State state) {  

          onDraw(c, parent);  

      }  

@Deprecated  

public void onDraw(Canvas c, RecyclerView parent) {  

      }  


public void onDrawOver(Canvas c, RecyclerView parent, State state) {  

          onDrawOver(c, parent);  

      }  


@Deprecated  

public void onDrawOver(Canvas c, RecyclerView parent) {  

      }  



@Deprecated  

public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {  

outRect.set(0, 0, 0, 0);  

      }  


public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {  

          getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),  

                  parent);  

      }  

  }  

当我们通过

[java] view plain copy

mRecyclerView.addItemDecoration();  

    onDraw: 该方法可以在RecyclerView的画布上画任何装饰,且是在 the item views 被绘制之前回调

    onDrawOver:该方法可以在RecyclerView的画布上画任何装饰,且是在 the item views 被绘制之后回调

    getItemOffsets :可以在该方法中为the item views添加偏移量

下面我们可以就通过继承ItemDecoration为RecyclerView添加分割线。

DividerItemDecoration的代码如下: 

[java] view plain copy

package com.sharejoys.mvpdemo.ui.customview;  


import android.content.Context;  

import android.content.res.TypedArray;  

import android.graphics.Canvas;  

import android.graphics.Rect;  

import android.graphics.drawable.Drawable;  

import android.support.annotation.IntDef;  

import android.support.v4.view.ViewCompat;  

import android.support.v7.widget.LinearLayoutManager;  

import android.support.v7.widget.RecyclerView;  

import android.view.View;  


/**

 * Date: 2018/1/14

 *

 * @author 青青-子衿

 * @since 1.0

 */  


public class DividerItemDecoration extends RecyclerView.ItemDecoration {  

@OrientationType  

private int mOrientation = LinearLayoutManager.VERTICAL;  

private Drawable mDivider;  


private int[] attrs = new int[]{  

            android.R.attr.listDivider  

    };  


public DividerItemDecoration(Context context, @OrientationType int orientation) {  

        TypedArray typedArray = context.obtainStyledAttributes(attrs);  

mDivider = typedArray.getDrawable(0);  

        typedArray.recycle();  

        setOrientation(orientation);  

    }  


private void setOrientation(@OrientationType int orientation) {  

if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {  

throw new IllegalArgumentException("传入的布局类型不合法");  

        }  

this.mOrientation = orientation;  

    }  


@Override  

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  

//调用这个绘制方法,RecyclerView会回调该绘制方法,需要我们自己去绘制条目的间隔线  

if (mOrientation == LinearLayoutManager.VERTICAL) {  

//垂直  

            drawVertical(c, parent);  

}else {  

//水平  

            drawHorizontal(c, parent);  

        }  

    }  


private void drawVertical(Canvas c, RecyclerView parent) {  

// 画水平线  

int left = parent.getPaddingLeft();  

int right = parent.getWidth() - parent.getPaddingRight();  

int childCount = parent.getChildCount();  

for (int i = 0; i < childCount; i++) {  

            View child = parent.getChildAt(i);  


            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();  

int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));  

int bottom = top + mDivider.getIntrinsicHeight();  

            mDivider.setBounds(left, top, right, bottom);  

            mDivider.draw(c);  

        }  

    }  


private void drawHorizontal(Canvas c, RecyclerView parent) {  

int top = parent.getPaddingTop();  

int bottom = parent.getHeight() - parent.getPaddingBottom();  

int childCount = parent.getChildCount();  

for (int i = 0; i < childCount; i++) {  

            View child = parent.getChildAt(i);  


            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();  

int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));  

int right = left + mDivider.getIntrinsicHeight();  

            mDivider.setBounds(left, top, right, bottom);  

            mDivider.draw(c);  

        }  

    }  


@Override  

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {  

//获得条目的偏移量(所有的条目都会回调一次该方法)  

if (mOrientation == LinearLayoutManager.VERTICAL) {  

//垂直  

outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());  

}else {  

//水平  

outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);  

        }  

    }  


@IntDef({LinearLayoutManager.VERTICAL, LinearLayoutManager.HORIZONTAL})  

public @interface OrientationType {  

    }  

}  

然后在activity设置水平方向

[java] view plain copy

mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);   

mRecyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));  

竖直方向:

[java] view plain copy

mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONAL, false);   

mRecyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.HORIZONAL))  

这里的分割线是默认的,我们可以在主题中去设置分割线的颜色

[html] view plain copy




@color/colorPrimary  

@color/colorPrimaryDark  

@color/colorAccent  

@drawable/bg_recyclerview_divider  


bg_recyclerview_divider.xml

[html] view plain copy


android:shape="rectangle">  


android:centerColor="#ff00ff00"  

android:endColor="#ff0000ff"  

android:startColor="#ffff0000"  

android:type="linear"/>  


android:width="10dp"  

android:height="10dp"/>  



运行后效果如下

以上的分割线只适用在LinearLayoutManager的相关布局中。

对于GridLayoutManager布局是不适用的。需要我们单独写一个。

以下是对于GridLayoutManager布局的分割线代码

[java] view plain copy

package com.sharejoys.recyclerviewdemo.view;  


import android.content.Context;  

import android.content.res.TypedArray;  

import android.graphics.Canvas;  

import android.graphics.Rect;  

import android.graphics.drawable.Drawable;  

import android.support.v7.widget.GridLayoutManager;  

import android.support.v7.widget.RecyclerView;  

import android.view.View;  


/**

 * Date: 2018/1/14 

 *

 * @author 青青-子衿

 * @since 1.0

 */  


public class DividerGridViewItemDecoration extends RecyclerView.ItemDecoration {  

private Drawable mDivider;  

private int[] attrs = new int[]{  

            android.R.attr.listDivider};  


public DividerGridViewItemDecoration(Context context) {  

        TypedArray typedArray = context.obtainStyledAttributes(attrs);  

mDivider = typedArray.getDrawable(0);  

        typedArray.recycle();  

    }  


@Override  

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  

        drawVertical(c, parent);  

        drawHorizontal(c, parent);  

    }  


private void drawVertical(Canvas c, RecyclerView parent) {  

//绘制垂直间隔线(垂直的矩形)  

int childCount = parent.getChildCount();  

for (int i = 0; i < childCount; i++) {  

            View child = parent.getChildAt(i);  

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();  

int left = child.getRight() + params.rightMargin;  

int right = left + mDivider.getIntrinsicWidth();  

int top = child.getTop() - params.topMargin;  

int bottom = child.getBottom() + params.bottomMargin;  


            mDivider.setBounds(left, top, right, bottom);  

            mDivider.draw(c);  

        }  

    }  


private void drawHorizontal(Canvas c, RecyclerView parent) {  

//绘制水平分割线  

int childCount = parent.getChildCount();  

for (int i = 0; i < childCount; i++) {  

            View child = parent.getChildAt(i);  

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();  

int left = child.getLeft() - params.leftMargin;  

int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth();  

int top = child.getBottom() + params.bottomMargin;  

int bottom = top + mDivider.getIntrinsicHeight();  


            mDivider.setBounds(left, top, right, bottom);  

            mDivider.draw(c);  

        }  

    }  


@Override  

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {  

// 四个方向的偏移值  

int right = mDivider.getIntrinsicWidth();  

int bottom = mDivider.getIntrinsicHeight();  


        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();  

int itemPosition = params.getViewAdapterPosition();  

if (isLastColum(itemPosition, parent)) {  

right =0;  

        }  


if (isLastRow(itemPosition, parent)) {  

bottom =0;  

        }  

outRect.set(0, 0, right, bottom);  

    }  


/**

     * 是否最后一行

     */  

private boolean isLastRow(int itemPosition, RecyclerView parent) {  

int spanCount = getSpanCount(parent);  

if (spanCount != -1) {  

int childCount = parent.getAdapter().getItemCount();  

int lastRowCount = childCount % spanCount;  

//最后一行的数量小于spanCount  

if (lastRowCount == 0 || lastRowCount < spanCount) {  

return true;  

            }  

        }  


return false;  

    }  



/**

     * 根据parent获取到列数

     */  

private int getSpanCount(RecyclerView parent) {  

        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();  

if (layoutManager instanceof GridLayoutManager) {  

            GridLayoutManager lm = (GridLayoutManager) layoutManager;  

int spanCount = lm.getSpanCount();  

return spanCount;  

        }  

return -1;  

    }  


/**

     * 判断是否是最后一列

     */  

private boolean isLastColum(int itemPosition, RecyclerView parent) {  

int spanCount = getSpanCount(parent);  

if (spanCount != -1) {  

if ((itemPosition + 1) % spanCount == 0) {  

return true;  

            }  

        }  

return false;  

    }  

}  

我们在activity中使用该分割线

[java] view plain copy

mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));  

mRecyclerView.addItemDecoration(new DividerGridViewItemDecoration(this));  

点击事件

RecyclerView并没有像ListView的那样可以设置点击事件以及长按点击事件,这个需要我们可以在adapter中去设置回调的方式实现,具体代码如下:

MyRecyclerViewAdapter的代码如下:

[java] view plain copy

package com.sharejoys.recyclerviewdemo.actvity;  


import android.support.v7.widget.RecyclerView;  

import android.view.LayoutInflater;  

import android.view.View;  

import android.view.ViewGroup;  

import android.widget.TextView;  


import com.sharejoys.recyclerviewdemo.R;  


import java.util.List;  


/**

 * Created by 青青-子衿 on 2018/1/15.

 */  



public class MyRecyclerViewAdapter extends RecyclerView.Adapter {  

private List list;  

private OnItemClickListener onItemClickListener;  

private OnItemLongClickListener onItemLongClickListener;  


/**

     * 设置点击事件

     */  

public void setOnItemClickListener(OnItemClickListener onItemClickListener) {  

this.onItemClickListener = onItemClickListener;  

    }  


/**

     * 设置长按点击事件

     */  

public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {  

this.onItemLongClickListener = onItemLongClickListener;  

    }  


public MyRecyclerViewAdapter(List list) {  

this.list = list;  

    }  


@Override  

public MyRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_base_use, parent,false);  

MyRecyclerViewAdapter.ViewHolder viewHolder =new MyRecyclerViewAdapter.ViewHolder(view);  

return viewHolder;  

    }  


@Override  

public void onBindViewHolder(MyRecyclerViewAdapter.ViewHolder holder, int position) {  

        holder.mText.setText(list.get(position));  

int adapterPosition = holder.getAdapterPosition();  

if (onItemClickListener != null) {  

holder.itemView.setOnClickListener(new MyOnClickListener(position, list.get(adapterPosition)));  

        }  

if (onItemLongClickListener != null) {  

holder.itemView.setOnLongClickListener(new MyOnLongClickListener(position, list.get(adapterPosition)));  

        }  

    }  


@Override  

public int getItemCount() {  

return list.size();  

    }  


class ViewHolder extends RecyclerView.ViewHolder {  

        TextView mText;  


        ViewHolder(View itemView) {  

super(itemView);  

            mText = itemView.findViewById(R.id.item_tx);  

        }  

    }  


private class MyOnLongClickListener implements View.OnLongClickListener {  

private int position;  

private String data;  


public MyOnLongClickListener(int position, String data) {  

this.position = position;  

this.data = data;  

        }  


@Override  

public boolean onLongClick(View v) {  

            onItemLongClickListener.onItemLongClick(v, position, data);  

return true;  

        }  

    }  


private class MyOnClickListener implements View.OnClickListener {  

private int position;  

private String data;  


public MyOnClickListener(int position, String data) {  

this.position = position;  

this.data = data;  

        }  


@Override  

public void onClick(View v) {  

            onItemClickListener.onItemClick(v, position, data);  

        }  

    }  



public interface OnItemClickListener {  

void onItemClick(View view, int position, String data);  

    }  


public interface OnItemLongClickListener {  

void onItemLongClick(View view, int position, String data);  

    }  


}  

activity中设置监听:

[java] view plain copy

mAdapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {  

@Override  

public void onItemClick(View view, int position, String data) {  

Toast.makeText(MainActivity.this, "您点击了:  " + data, Toast.LENGTH_SHORT).show();  

        }  

    });  

mAdapter.setOnItemLongClickListener(new MyRecyclerViewAdapter.OnItemLongClickListener() {  

@Override  

public void onItemLongClick(View view, int position, String data) {  

Toast.makeText(MainActivity.this, "您长按点击了:  " + data, Toast.LENGTH_SHORT).show();  

        }  

    });  

运行后效果如下:

ItemAnimator

我们可以为RecyclerView设置增加和删除动画,这里我们可以使用默认动画

[java] view plain copy

//设置添加或删除item时的动画,这里使用默认动画  

mRecyclerView.setItemAnimator(new DefaultItemAnimator());  

然后在Adapter中增加删除和添加数据的方法

[java] view plain copy

/**

  * 插入一条数据

  *

  * @param index 下标

  * @param s     数据

  */  

public void addItem(int index, String s) {  

     list.add(index, s);  

     notifyItemInserted(index);  

 }  


/**

  * 删除一条数据

  *

  * @param index 下标

  */  

public void deleteItem(int index) {  

     list.remove(index);  

     notifyItemRemoved(index);  

 }  

activty调用删除和添加方法后效果如下

RecycleView还有一些其他用法,比如结合ItemTouchHelper实现item的拖拽效果,可以自定义增加header和footer(类似Listview)

最后附上demo地址

本文来自:https://blog.csdn.net/tuike/article/details/79064750

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

推荐阅读更多精彩内容