Android Design Support Library系列之一:TabLayout的使用

原文章地址

Google官方在14年 I/O大会上推出了全新的设计语言——Material Design,

Material Design让Android界面在体验上更加鲜艳和简洁,正在逐步成为APP设计的趋势.

而与Material Design相关的是一系列实现Material Design效果的控件库Android Design Support Library,从今天开始将一一介绍他们的用法.

这一系列控件库在使用时都需要在gradle中添加依赖:

compile 'com.android.support:design:25.3.1'

一、TabLayout介绍

官方地址:TabLayout

需要翻墙

TabLayout1

TabLayout2

像上面这种选项卡切换的效果,几乎所有应用中都有涉及到,这种效果实现方式很多,TabHost实现、RadioGroup+RadioButton实现、ViewPager+PagerTabStrip或者种种第三方库(Viewpageindicator…)来实现、HorizontalScrollView+LinearLayout动态实现……

而在Android Design Support Library中就有这样一个控件:TabLayout,继承自HorizontalScrollView,通过TabLayout我们可以很轻松的实现这种效果.

二、TabLayout简单使用

布局文件:


    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


        android:id="@+id/tablayout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">


Activity中:

package com.my;

import android.support.design.widget.TabLayout;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private TabLayout mTablayout;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mTablayout = (TabLayout) findViewById(R.id.tablayout);

        mTablayout.addTab(mTablayout.newTab().setText("A"));

        mTablayout.addTab(mTablayout.newTab().setText("B"));

        mTablayout.addTab(mTablayout.newTab().setText("C"));

    }

}

效果图:

简单的选项卡效果就实现了,当然,你也可以在布局文件中写死,像下面这样:


    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


        android:id="@+id/tablayout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">


            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="A" />


            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="B" />


            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="C" />


效果和上面是一样的,不过一般没人这么使用.

三、TabLayout的常用属性

app:tabIndicatorColor=""  指示器颜色

app:tabIndicatorHeight=""  指示器高度,设置为0就是没有指示器

app:tabTextColor=""    Tab文本默认颜色

app:tabSelectedTextColor=""    Tab文本被选中后的颜色

app:tabTextAppearance=""      为Tab文本设置样式,一般是需要为Tab加图标时使用

app:tabMode=""  只有两个值:fixed、scrollable

    fixed用于标题栏少的情况,每个Tab可以平分屏幕宽度

    scrollable用于标题栏多出屏幕的情况,如果标题栏少的时候用很难看,占不满屏幕

app:tabBackground=""    TabLayout背景,和android:background=""效果一样

app:tabGravity=""    对齐方式:  居中显示center、fill填满

app:tabGravity=”center”

app:tabGravity=”fill”

还有一些很少使用的:

从左边开始偏移距离,tabMode值必须为scrollable才会生效

app:tabContentStart="150dp"

app:tabContentStart

选项卡宽度限制

app:tabMaxWidth=""  最大宽度

app:tabMinWidth=""  最小宽度

Tab内边距

app:tabPaddingStart=""

app:tabPaddingBottom=""

app:tabPaddingEnd=""

app:tabPaddingTop=""

app:tabPadding=""

三、TabLayout方法

Tablayout.newTab()        创建标签

Tablayout.addTab()        添加标签

Tablayout.removeTab()      删除标签

Tablayout.removeTabAt()    通过索引删除标签

Tablayout.removeAllTabs()  删除全部标签

因为TabLayout继承自HorizontalScrollView,所以可以直接添加View

addView ()

添加监听器,取消监听器,清楚所有的监听器

Tablayout.addOnTabSelectedListener()

Tablayout.removeOnTabSelectedListener()

Tablayout.clearOnTabSelectedListeners()

Tablayout.getSelectedTabPosition()    获取当前选中的Tab位置

Tablayout.getTabAt()      根据索引获取Tab

Tablayout.getTabCount()    获取Tab总数

对应tabGravity属性

Tablayout.getTabGravity()

Tablayout.setTabGravity()

对应tabMode属性

Tablayout.getTabMode()

Tablayout.setTabMode()

对应tabTextColor属性

Tablayout.setTabTextColors()

Tablayout.getTabTextColors()

和ViewPager关联,随着ViewPager滑动而滑动

TabLayout和ViewPager配合使用是最常见的运用方式

两者关联后:

1)TabLayout之前创建的Tab并不能正常显示,但可以在关联后通过 getTabAt() 得到标签之后进行修改

但其实没有必要,我们一般由2)和3)决定Tab的数量和内容

2)TabLayout的Tab数量由ViewPager分页数量决定

3)TabLayout的Tab内容由ViewPager的Adapter中 getPagerTitle() 方法返回的内容决定

Tablayout.setupWithViewPager()

TabLayout中的内部类:Tab,表示TabLayout中的每一个标签

Tab的方法

boolean is Selected()  Tab是否被选中

void setSelected()  设置Tab为被选中状态

setText ()    设置Tab文本内容

getText ()    获取Tab文本内容

getIcon ()  获取Tab的图标

setIcon ()  为Tab添加图标

setCustomView()    设置用户自定义的Tab,参数为资源id或者View对象

getPosition() 获取当前位置

四、TabLayout搭配ViewPager使用

1、MainActivity布局文件的两种方式


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

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


        android:id="@+id/viewpager"

        android:layout_width="match_parent"

        android:layout_height="match_parent">


            android:id="@+id/tablayout"

            app:tabMode="scrollable"

            app:tabBackground="@android:color/holo_blue_dark"

            app:tabIndicatorColor="@android:color/white"

            app:tabTextColor="@android:color/black"

            app:tabSelectedTextColor="@android:color/white"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"/>



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

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


        android:id="@+id/tablayout"

        app:tabMode="scrollable"

        app:tabBackground="@android:color/holo_blue_dark"

        app:tabIndicatorColor="@android:color/white"

        app:tabTextColor="@android:color/black"

        app:tabSelectedTextColor="@android:color/white"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"/>


        android:id="@+id/viewpager"

        android:layout_width="match_parent"

        android:layout_height="match_parent">


2、MainActivity.java

package com.my;

import android.os.Bundle;

import android.support.design.widget.TabLayout;

import android.support.v4.app.Fragment;

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

import java.util.ArrayList;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    private TabLayout mTablayout;

    private ViewPager mViewPager;

    private List mDatas;

    private List fragments;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        initData();

        initFragments();

        mTablayout = (TabLayout) findViewById(R.id.tablayout);

        mViewPager = (ViewPager) findViewById(R.id.viewpager);

      mViewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(), mDatas, fragments));

//        mTablayout.setupWithViewPager(mViewPager);

//注意:我的布局文件中ViewPager和TabLayout 是嵌套的,所以不需要这一步

//          如果没有嵌套,则需要在ViewPager设置Adapter之后加上这一步

//另外,只能是ViewPager嵌套Tablayout,反了会报错的,因为Tablayout中只能嵌套TabItem

    }

    private void initData() {

        mDatas = new ArrayList<>();

        for (int i = 'A'; i < 'I'; i++) {

            mDatas.add("" + (char) i);

        }

    }

    private void initFragments() {

        fragments = new ArrayList<>();

        for (int i = 0; i < mDatas.size(); i++) {

            MyFragment fragment = MyFragment.newInstance(mDatas.get(i));

            fragments.add(fragment);

        }

    }

}

3、MyPagerAdapter.java

package com.my;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentStatePagerAdapter;

import java.util.List;

/**

* Created by fgq on 2017/5/9.

*/

public class MyPagerAdapter extends FragmentStatePagerAdapter {

    private List mDatas;

    private List mFragments;

    public MyPagerAdapter(FragmentManager fm, List mDatas, List fragments) {

        super(fm);

        this.mDatas = mDatas;

        this.mFragments = fragments;

    }

    @Override

    public Fragment getItem(int position) {

        return mFragments.get(position);

    }

    @Override

    public int getCount() {

        return mDatas.size()==mFragments.size()?mFragments.size():0;

    }

    /**

    * 重写此方法,返回TabLayout的内容

    */

    @Override

    public CharSequence getPageTitle(int position) {

        return mDatas.get(position);

    }

}

4、MyFragment.java

package com.my;

import android.os.Bundle;

import android.support.v4.app.Fragment;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.TextView;

/**

* Created by fgq on 2017/5/9.

*/

public class MyFragment extends Fragment {

    public static MyFragment newInstance(String data) {

        Bundle args = new Bundle();

        args.putString("key", data);

        MyFragment fragment = new MyFragment();

        fragment.setArguments(args);

        return fragment;

    }

    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment, container, false);

        TextView tv = (TextView) view.findViewById(R.id.tv);

        tv.setText("Fragment------" + getArguments().getString("key"));

        return view;

    }

}

5、Fragment布局文件


    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent">


        android:id="@+id/tv"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_centerInParent="true"

        tools:text="别看了,我就是一个TextView" />

5、效果图

五、TabLayout之自定义Tab布局

我们的Tab上有时候不仅仅只有文字,还会有图标,那么这时候我们的getPageTitle()方法就不应该仅仅返回一个文本了.

方式1:通过SpannableString为Tab添加图标

SpannableString基本上与String差不多,也是用来存储字符串,但它们俩的特殊就在于SpannableString有一个SetSpan()方法,能给这些存储的String添加各种格式或者称样式(Span),将原来的String以不同的样式显示出来,比如在原来String上加下划线、加背景色、改变字体颜色、用图片把指定的文字给替换掉,等等.

MainActivity中的修改

private int[] imageRes = {

            R.mipmap.a,R.mipmap.b, R.mipmap.c,R.mipmap.d,

            R.mipmap.e, R.mipmap.f,R.mipmap.g,R.mipmap.h

};

mViewPager.setAdapter(new MyPagerAdapter(MainActivity.this,getSupportFragmentManager(), mDatas, fragments,imageRes));

添加了一个装有图片资源的数组,然后通过构造传给MyPagerAdapter,当然,其实标题mDatas和图标资源imageRes你直接声明在MyPagerAdapter中也是可以的.

MyPagerAdapter中的修改

    private int[] imageRes;

    private Context mContext;

    public MyPagerAdapter(Context context, FragmentManager fm, List mDatas, List fragments, int[] imageRes) {

        super(fm);

        this.mContext = context;

        this.mDatas = mDatas;

        this.mFragments = fragments;

        this.imageRes = imageRes;

    }

    /**

    * 通过SpannableString 为Tab添加各种样式,这里就添加了一个图标

    */

    @Override

    public CharSequence getPageTitle(int position) {

        SpannableString sb = new SpannableString("  "+mDatas.get(position));

        Drawable image = mContext.getResources().getDrawable(imageRes[position]);

      image.setBounds(0,0,image.getIntrinsicWidth(), image.getIntrinsicHeight());

        ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);

        sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        return sb;

    }

运行之后你会发现效果没变,这是因为TabLayout创建的tab默认样式textAllCaps属性为true,这阻止了ImageSpan被渲染出来,可以通过下面的样式文件定义来改变:

在res/values/styles中定义我们自己的样式,把textAllCaps属性设为false

   

        false



TabLayout中Tab的文字大小无法在布局文件中更改,也是在这里更改的

在布局文件中为TabLayout引用我们自己的样式

  app:tabTextAppearance="@style/MyTabTextAppearance"

效果图

方式2:通过Tab的setCustomView()方法自定义Tab布局

上面已经介绍了,Tab有一个方法,setCustomView(),参数为一个资源id或者一个View对象,我们通过这个方法来自定义Tab的布局.

1)MainActivity布局文件


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

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


        android:id="@+id/tablayout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:tabBackground="@android:color/holo_blue_dark"

        app:tabIndicatorColor="@android:color/white"

        app:tabMode="scrollable"

        app:tabSelectedTextColor="@android:color/white"

        app:tabTextAppearance="@style/MyTabTextAppearance"

        app:tabTextColor="@android:color/black" />


        android:id="@+id/viewpager"

        android:layout_width="match_parent"

        android:layout_height="match_parent">


2)MainActivity.java

package com.my;

import android.os.Bundle;

import android.support.design.widget.TabLayout;

import android.support.v4.app.Fragment;

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

import java.util.ArrayList;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    private TabLayout mTablayout;

    private ViewPager mViewPager;

    private List mDatas;

    private List fragments;

    private MyPagerAdapter mAdapter;

    private int[] imageRes = {

            R.mipmap.a,R.mipmap.b, R.mipmap.c,R.mipmap.d,

            R.mipmap.e, R.mipmap.f,R.mipmap.g,R.mipmap.h

    };

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        initData();

        initFragments();

        mTablayout = (TabLayout) findViewById(R.id.tablayout);

        mViewPager = (ViewPager) findViewById(R.id.viewpager);

        mAdapter = new MyPagerAdapter(MainActivity.this,getSupportFragmentManager(), mDatas, fragments,imageRes);

        mViewPager.setAdapter(mAdapter);

        mTablayout.setupWithViewPager(mViewPager);

        /**

        * 为每一个Tab设置自定义布局

        */

        for (int i = 0; i

            TabLayout.Tab tab = mTablayout.getTabAt(i);

            tab.setCustomView(mAdapter.getTabView(i));

        }

    }

    private void initData() {

        mDatas = new ArrayList<>();

        for (int i = 'A'; i < 'I'; i++) {

            mDatas.add("" + (char) i);

        }

    }

    private void initFragments() {

        fragments = new ArrayList<>();

        for (int i = 0; i < mDatas.size(); i++) {

            MyFragment fragment = MyFragment.newInstance(mDatas.get(i));

            fragments.add(fragment);

        }

    }

}

3)MyPagerAdapter.java

package com.my;

import android.content.Context;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentStatePagerAdapter;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.ImageView;

import android.widget.TextView;

import java.util.List;

/**

* Created by fgq on 2017/5/9.

*/

public class MyPagerAdapter extends FragmentStatePagerAdapter {

    private List mDatas;

    private List mFragments;

    private int[] imageRes;

    private Context mContext;

    public MyPagerAdapter(Context context, FragmentManager fm, List mDatas, List fragments, int[] imageRes) {

        super(fm);

        this.mContext = context;

        this.mDatas = mDatas;

        this.mFragments = fragments;

        this.imageRes = imageRes;

    }

    @Override

    public Fragment getItem(int position) {

        return mFragments.get(position);

    }

    @Override

    public int getCount() {

        return mDatas.size()==mFragments.size()?mFragments.size():0;

    }

    /**

    * 要使用我们自定义的布局,这里返回null

    */

    @Override

    public CharSequence getPageTitle(int position) {

        return null;

    }

    /**

    * 定义一个方法,来返回Tab的内容

    */

    public View getTabView(int position){

      View view = LayoutInflater.from(mContext).inflate(R.layout.tab_layout, null);

        TextView tv= (TextView) view.findViewById(R.id.tv);

        ImageView iv = (ImageView) view.findViewById(R.id.iv);

        tv.setText(mDatas.get(position));

        iv.setImageResource(imageRes[position]);

        return view;

    }

}

4)每一个Tab的布局文件


    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:orientation="vertical">


        android:id="@+id/iv"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_gravity="center"

        tools:src="@mipmap/a" />


        android:id="@+id/tv"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_gravity="center"

        android:layout_marginTop="5dp"

        tools:text="别看了,我就是一个TextView" />

其它的文件没有发生改变

5)效果图

ok, 效果还好,但是文字颜色的选择器效果没了,这种情况我们可以在每一个Tab的布局文件为TextView的textColor设置一个选择器就行了

android:textColor="@drawable/seletor_tab_textcolor"

在drawable目录下新建一个选择器seletor_tab_textcolor.xml


   

   

但是图片要实现选择器的效果就不好办了,Tab数量太多,针对每一个tab的图片都需要一个seletor….

另外我们也注意到:setCustomView()为Tab设置自定义布局的参数不仅仅可以是View对象,也可以是资源Id.像下面这样:

        int[] tabs = {R.layout.tab_one,

                    R.layout.tab_two,

                    R.layout.tab_three,

                    R.layout.tab_four};//有多少tab,就添加多少tab的布局文件

        for (int i = 0; i < mTablayout.getTabCount(); i++) {

            mTabLayout.getTabAt(i).setCustomView(tabs[i]);

        }

这种做法适合选项卡比较少而且固定的情况.

六、关于TabLayout指示器长度的更改

TabLayout的指示器(Indicator)可以更改颜色、高度,但是你会发现没有更改长度的属性或者方法,这时我们查看源码,发现被private 了,所以只能通过反射来做了.

private final SlidingTabStrip mTabStrip;

    public  void setIndicator(TabLayout tabs, int leftDip, int rightDip) {

        Class tabLayout = tabs.getClass();

        Field tabStrip = null;

        try {

            tabStrip = tabLayout.getDeclaredField("mTabStrip");

        } catch (NoSuchFieldException e) {

            e.printStackTrace();

        }

        tabStrip.setAccessible(true);

        LinearLayout ll_tab = null;

        try {

            ll_tab = (LinearLayout) tabStrip.get(tabs);

        } catch (IllegalAccessException e) {

            e.printStackTrace();

        }

        int left = (int) (Resources.getSystem().getDisplayMetrics().density * leftDip);

        int right = (int) (Resources.getSystem().getDisplayMetrics().density * rightDip);

        for (int i = 0; i < ll_tab.getChildCount(); i++) {

            View child = ll_tab.getChildAt(i);

            child.setPadding(0, 0, 0, 0);

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);

            params.leftMargin = left;

            params.rightMargin = right;

            child.setLayoutParams(params);

            child.invalidate();

        }

    }

注意:tabMode必须是fixed

1)调用setIndicator(mTabLayout, 20, 20);方法即可,这两个20根据实际需求来定.

2)关于背景不正常问题,不要使用TabLayout自带的app:tabBackground=””;

使用android:background=” “就可以了

ok,TabLayout的使用就写到这里,如果你的项目中有类似效果要实现,不妨试试TabLayout.

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

推荐阅读更多精彩内容