自定义View,绘制

1.使用绘制方法,画出一个view,然后在xml文件中使用即可

1.创建自定义的view
这里我只画了一个空心圆,canvas是画布,paint是画笔,用画笔可以画出任何图形设置颜色、空心实心、线条宽度,通过RectF设置圆的位置和大小

public class PaintView extends View {

    public PaintView(Context context) {
        super(context);
    }

    public PaintView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        RectF rectF = new RectF(10, 10, 100, 100);
        Paint paint = new Paint();

        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.RED);
        paint.setStrokeWidth(10);

        canvas.drawOval(rectF, paint);
    }
}

2.将画好的view引用到xml中

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.mazhan.view.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.mazhan.view.PaintView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

这样我们绘制的view就可以被加载出来了


Snip20201022_18.png

2.绘制线条时的注意点
1.需要设置stroke
2.二阶的贝塞尔曲线可以设置跟随手势画出任意的图形,这个在线教育中使用的画板就是使用的二阶贝塞尔曲线

public class CanvasPathView extends View {
    public CanvasPathView(Context context) {
        super(context);
    }

    public CanvasPathView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(10);
        // 如果需要绘制path的话,需要设置paint的style为stroke
        paint.setStyle(Paint.Style.STROKE);

        // 线条需要通过path来绘制
        Path path = new Path();
        // 设置起点
        path.moveTo(50,50);
        // 设置连接点
        path.lineTo(100,100);

        //二阶贝塞尔曲线
        path.quadTo(200,200,300,100);

        canvas.drawPath(path, paint);
    }
}
Snip20201022_20.png

3.移动坐标系

默认的坐标系是(0,0),可以通过设置canvas的属性来平移或者是旋转坐标系,然后将坐标系的模式保存下来,这样可以便利的设置一些特殊的坐标系

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.RED);
        paint.setStrokeWidth(10);

        // 设置坐标系起始点为100,100
        canvas.translate(100,100);

        // 保存设置好的坐标系
        canvas.save();

        // 设置坐标系旋转
        canvas.rotate(90);

        // 销毁坐标系,还原上一次保存的坐标系
        canvas.restore();

        canvas.drawLine(0,0,100,0,paint);
    }

4.自定义控件的三大方法执行顺序

public class MyFrameLayout extends FrameLayout {

    public MyFrameLayout(@NonNull Context context) {
        super(context);
    }

    public MyFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Log.d(getClass().getSimpleName(), "onDraw: " + "MyFrameLayout父控件");
    }

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

        Log.d(getClass().getSimpleName(), "onMeasure: " +  "MyFrameLayout父控件");
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        Log.d(getClass().getSimpleName(), "onLayout: " +  "MyFrameLayout父控件");
    }
}


public class MyView extends View {

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setTextSize(20);
        canvas.drawText("这是一个view", 10, 10, paint);

        Log.d(getClass().getSimpleName(), "onDraw: " + "MyView子控件");

    }

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

        Log.d(getClass().getSimpleName(), "onMeasure: " + "MyView子控件");

    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        Log.d(getClass().getSimpleName(), "onLayout: " + "MyView子控件");

    }
}

在xml中使用MyFrameLayout和MyView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.mazhan.customviewmethodorder.MainActivity">

    <com.mazhan.customviewmethodorder.MyFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <com.mazhan.customviewmethodorder.MyView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    </com.mazhan.customviewmethodorder.MyFrameLayout>

</LinearLayout>
10-22 07:20:51.088 6735-6735/com.mazhan.customviewmethodorder D/MyFrameLayout: onMeasure: MyFrameLayout父控件
10-22 07:20:51.150 6735-6735/com.mazhan.customviewmethodorder D/MyFrameLayout: onMeasure: MyFrameLayout父控件
10-22 07:20:51.153 6735-6735/com.mazhan.customviewmethodorder D/MyFrameLayout: onLayout: MyFrameLayout父控件
10-22 07:28:38.713 6928-6928/com.mazhan.customviewmethodorder D/MyFrameLayout: onMeasure: MyFrameLayout父控件
                                                                              
10-22 07:28:38.753 6928-6928/com.mazhan.customviewmethodorder D/MyFrameLayout: onMeasure: MyFrameLayout父控件
10-22 07:28:38.760 6928-6928/com.mazhan.customviewmethodorder D/MyFrameLayout: onLayout: MyFrameLayout父控件
10-22 07:30:32.941 7079-7079/com.mazhan.customviewmethodorder D/MyView: onMeasure: MyView子控件
10-22 07:30:32.943 7079-7079/com.mazhan.customviewmethodorder D/MyFrameLayout: onMeasure: MyFrameLayout父控件
                                                                               
10-22 07:30:32.995 7079-7079/com.mazhan.customviewmethodorder D/MyView: onMeasure: MyView子控件
10-22 07:30:32.995 7079-7079/com.mazhan.customviewmethodorder D/MyFrameLayout: onMeasure: MyFrameLayout父控件
10-22 07:30:32.996 7079-7079/com.mazhan.customviewmethodorder D/MyView: onLayout: MyView子控件
10-22 07:30:32.996 7079-7079/com.mazhan.customviewmethodorder D/MyFrameLayout: onLayout: MyFrameLayout父控件
10-22 07:30:33.188 7079-7079/com.mazhan.customviewmethodorder D/MyView: onDraw: MyView子控件

5.VierPager的使用

1.在MainActivity的xml中添加ViewPager

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" tools:context="com.mazhan.viewpagerdemo.MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPagerId"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_purple">


    </android.support.v4.view.ViewPager>


</LinearLayout>

2.给ViewPager设置PagerAdapter

public class MainActivity extends AppCompatActivity {

    private ArrayList<TextView> mDatas;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initData();
        initViews();
    }

    private void initViews() {
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewPagerId);

        viewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return mDatas.size();
            }

            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {

                TextView textView =  mDatas.get(position);
                container.addView(textView);
                return textView;
            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {

                container.removeView((View) object);
            }
        });
    }

    private void initData() {
        mDatas = new ArrayList<>();
        for (int i = 0; i < 10; i++) {

            TextView textView = new TextView(getApplicationContext());
            textView.setTextSize(20);
            textView.setText("这是第" + i + "个页面");
            mDatas.add(textView);
        }
    }
}

6.ViewFliper的使用
使用viewFlipper完成文字向上滚动的效果(只要设置滚动的动画即可)

在xml中直接使用系统的ViewFlipper即可

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" tools:context="com.mazhan.viewfliperdemo.MainActivity">

    <ViewFlipper
        android:id="@+id/ViewFlipperId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/myColorRed">
    </ViewFlipper>

</android.support.constraint.ConstraintLayout>
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

    }

    private void initView() {
        ViewFlipper viewFlipper = (ViewFlipper) findViewById(R.id.ViewFlipperId);
        viewFlipper.startFlipping();

        //设置viewFlipper的一些属性
        viewFlipper.setFlipInterval(5000);

        // 设置viewFlipper的的入场动画和离场动画
        // 组合动画   透明度  位移
        // 离场动画
        AnimationSet inAnimationSet = new AnimationSet(false);
        AnimationSet outAnimationSet = new AnimationSet(false);

        AlphaAnimation inAlphaAnimation = new AlphaAnimation(0, 1);
        TranslateAnimation inTranslateAnimation = new TranslateAnimation(
                TranslateAnimation.RELATIVE_TO_SELF, 0,
                TranslateAnimation.RELATIVE_TO_SELF, 0,
                TranslateAnimation.RELATIVE_TO_SELF, 1,
                TranslateAnimation.RELATIVE_TO_SELF, 0);
        inAnimationSet.addAnimation(inAlphaAnimation);
        inAnimationSet.addAnimation(inTranslateAnimation);
        inAnimationSet.setDuration(3000);


        AlphaAnimation outAlphaAnimation = new AlphaAnimation(1, 0);
        TranslateAnimation outTranslateAnimation = new TranslateAnimation(
                TranslateAnimation.RELATIVE_TO_SELF, 0,
                TranslateAnimation.RELATIVE_TO_SELF, 0,
                TranslateAnimation.RELATIVE_TO_SELF, 0,
                TranslateAnimation.RELATIVE_TO_SELF, -1);
        outAnimationSet.addAnimation(outAlphaAnimation);
        outAnimationSet.addAnimation(outTranslateAnimation);
        outAnimationSet.setDuration(2000);

        viewFlipper.setInAnimation(inAnimationSet);
        viewFlipper.setOutAnimation(outAnimationSet);

        //向ViewFlipper中添加要滚动的view
        for (int i = 0; i < 10; i++) {
            TextView textView = new TextView(getApplicationContext());
            textView.setText("这是第" + i + "个textView");
            viewFlipper.addView(textView);
        }
    }
}

7.自定义控件自定义属性

1.比如说自定义一个只滚动text的ViewFlipper,叫做textViewFlipper。如果要给这个控件添加自定义属性,那么需要新建一个文件


image.png

2.那么如何在xml中使用自定义的属性呢


image.png

3.这样在自定义的控件类被加载的时候,就会调用构造方法,那么就可以得到自定义的属性名和属性值


image.png

4.将自定义的属性设置给textView
这里自定义属性的获取方式并不是这样遍历的,是直接通过字段获取的,R.styleable,R.styleable.TextViewFlipper_fontColor,R.styleable.TextViewFlipper_fontSize,这些都是系统根据自定义属性的文件生成的。

注意点:这里获取属性的时机是要注意的,只能在构造方法里进行获取,只有在构造方法被调用的时候,attrs的值才是正确的,当构造方法执行完成之后,attrs的值会发生变化,也就得不到自定义的属性了。


public class TextViewFlipper extends ViewFlipper {

    private AttributeSet mAttrs;
    private Context mContext;
    private float mTextSize;
    private int mTextColor;

    public TextViewFlipper(Context context) {
        super(context);
    }

    public TextViewFlipper(Context context, AttributeSet attrs) {
        super(context, attrs);

        mContext = context;
        mAttrs = attrs;

        int attributeCount = attrs.getAttributeCount();
        for (int i = 0; i < attributeCount; i++) {
            String attributeName = attrs.getAttributeName(i);
            String attributeValue = attrs.getAttributeValue(i);

            Log.d(getClass().getSimpleName(), "TextFlipperView: attributeName: " + attributeName
                    +" attributeValue: "+attributeValue);
        }

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TextViewFlipper);
        mTextColor = typedArray.getColor(R.styleable.TextViewFlipper_fontColor, Color.BLACK);
        mTextSize = typedArray.getDimension(R.styleable.TextViewFlipper_fontSize, 100);
        //销毁typedArray 
        typedArray.recycle();
    }


    void setViews (ArrayList<TextView> textViews) {

        for (int i = 0; i < textViews.size(); i++) {
            TextView textView = textViews.get(i);
            textView.setTextColor(mTextColor);
            textView.setTextSize(mTextSize);
            addView(textView);
        }
    }

}

8.制作垂直滑动的滑块demo
自定义VerticalSlideView,里面放一个ImageView,让imageView跟随手指拖动而滑动


public class VerticalSlideView extends ViewGroup {

    private View mChildView;
    private float mStartY;
    private float mStartX;


    public VerticalSlideView(Context context) {
        super(context);
    }

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


    // 确定控件的大小
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mChildView = getChildAt(0);

        //1. 获得mode和size
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int withSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        // 测量自控件的宽度
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        // 2.判断mode,根据mode来设置size
        int childWidth = mChildView.getMeasuredWidth();

        // 设置自身控件的大小
        setMeasuredDimension(childWidth, heightSize - dip2px(10));
    }


    // 对子控件进行布局
    int mTop = 0;
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 位置:左上右下
        mChildView.layout(0, mTop, mChildView.getMeasuredWidth(), mTop+mChildView.getMeasuredHeight());
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        // 这里没有判断action的类型,是点击还是滑动还是抬起
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                // do sth
                break;

            case MotionEvent.ACTION_MOVE:
                // do sth
                break;
            case MotionEvent.ACTION_UP:
                // do sth
                break;
            default:
                break;
        }

        // 直接设置滑块的y值跟随触摸的y值变化
        float y = event.getY();
        mTop = (int) y;
        requestLayout();

        if (y < 0) {
            mTop = 0;
        }

        if (y > getMeasuredHeight() - mChildView.getMeasuredHeight()) {
            mTop =  getMeasuredHeight() - mChildView.getMeasuredHeight();
        }

        requestLayout();
        return true;
    }



    public int px2dip(float pxValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    // 将do转化为像素尺寸
    public int dip2px( float dpValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

在xml中使用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" tools:context="com.mazhan.verticalslideview.MainActivity">

    <com.mazhan.verticalslideview.VerticalSlideView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="20dp"
        android:background="#f00">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/tabicon"/>
    </com.mazhan.verticalslideview.VerticalSlideView>

</LinearLayout>

9.无限滚动的背景View
通过绘制背景图片来实现

1.创建自定义的属性,来设置图片滚动的参数,创建attrs属性文件,设置参数

  <?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ScrollingView" >
        <attr name="speed" format="integer"/>
        <attr name="src" format="reference"/>
    </declare-styleable>
</resources>

2.在xml中使用自定义的属性

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:mazhan="http://schemas.android.com/apk/res-auto"
    tools:context="com.mazhan.scrollingview.MainActivity">


    <com.mazhan.scrollingview.ScrollingView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        mazhan:src="@drawable/scrolling_background"
        mazhan:speed="3"/>


</LinearLayout>

3.创建自定义的ScrollingView,在里面绘制bitmap,通过刷新bitmap的绘制来提现出动画效果


public class ScrollingView extends View {
    private int mSpeed;
    private Paint mPaint;
    private Bitmap mBitmap;

    public ScrollingView(Context context) {
        super(context);
    }

    public ScrollingView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        // 获取自定义的属性值
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScrollingView);

        mSpeed = typedArray.getInteger(R.styleable.ScrollingView_speed, 1);
        int resourceId = typedArray.getResourceId(R.styleable.ScrollingView_src, 0);
        mBitmap = BitmapFactory.decodeResource(getResources(), resourceId);
        typedArray.recycle();

        mPaint = new Paint();
    }


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

        int widthSize =  MeasureSpec.getSize(widthMeasureSpec);
        setMeasuredDimension(widthSize, mBitmap.getHeight());
    }

    int mOffset = 0;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //1 画图片

        //节约效率,避免控件在看不见的地方疯狂绘制,对偏移量需要控制
        //负数到了一定的范围,就重置,范围设置为bitmap的宽度
        if(mOffset<-mBitmap.getWidth()){
            mOffset = 0;
        }

        //2 填充控件剩下的宽度,多绘制几个bitmap上去
        int left = (int) mOffset;
        while (left<getMeasuredWidth()){
//            一直往右边去绘制,填充
            canvas.drawBitmap(mBitmap,left,0,mPaint);
            left+=mBitmap.getWidth();
        }

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