Activity手动设置横竖屏展示之后继续保持横竖屏自动切换

今天项目中遇到一个问题,因为我们的项目有几个视频播放的界面,所以避不开与全屏/半屏按钮、锁屏/解屏按钮、方向传感横竖屏自动变化打交道,我就被分到了这些任务。
先上一下大致的界面:

横屏

竖屏

一般来说,涉及到能播放视频的界面都大同小异(优酷、爱奇艺等),抛开弹幕、摄像头、倍速、截屏、截Gif等功能不谈,几乎都会有全屏/半屏播放、锁屏/解屏、方向传感这三个东西,而这三个东西都会牵涉到横竖屏问题。

一开始的时候,我认为很好做,也没多想,觉得思路就是这样:
⑴.全屏/半屏按钮点击逻辑:
监测点击全屏/半屏按钮时,用户屏幕所处的横竖位置,然后根据横竖屏,反向设置锁定死用户的屏幕:

/**
 * 横竖屏切换
 */
private void changeScreenOrientation() {
    //获取用户当前屏幕的横竖位置
    int currentOrientation = getResources().getConfiguration().orientation;
    //判断并设置用户点击全屏/半屏按钮的显示逻辑
    if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
        //如果屏幕当前是横屏显示,则设置屏幕锁死为竖屏显示
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
        //如果屏幕当前是竖屏显示,则设置屏幕锁死为横屏显示
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

⑵.锁屏按钮点击逻辑:
当点击锁屏按钮时,设置手机忽略方向传感;当点击解屏按钮时,设置手机恢复方向传感。

/**
 * 锁定/解锁屏幕点击事件
 */
private void lockScreen(){
    if(mLockBtn.isChecked()){
        //锁定屏幕
        //忽略物理方向传感器,这样就不会随着用户旋转设备而横竖屏切换了
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
    } else {
        //解锁屏幕
        //由设备的物理方向传感器决定,如果用户旋转设备,这屏幕就会横竖屏切换
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    }
}

⑶.方向传感横竖屏自动变化逻辑
直接把这个界面在清单文件下设计一下即可:

<!-- 测试横竖屏视频播放界面 -->
<activity
    android:name=".modules.course.VodActivity"
    android:configChanges="orientation|screenSize|layoutDirection"
    android:screenOrientation="unspecified" />

但是谁知道里面的坑很深,全然不是这么回事,写完之后测试就找上门了,说:我没锁死屏幕,点击全屏播放了,为啥我又竖着拿手机屏幕不自动切换回来了?
我擦,当然不能自动切换回来了,点击全屏播放,我锁死为手机横屏了!

当时觉得产品这个需求很不合理,又要全屏按钮控制横竖屏,又要小锁按钮控制横竖屏,还有手机方向感应控制横竖屏,一旦我在代码中强制设置屏幕的横竖变化,不论是设置为ActivityInfo的哪个控制横竖屏的值:

SCREEN_ORIENTATION_LANDSCAPE、
SCREEN_ORIENTATION_PORTRAIT、
SCREEN_ORIENTATION_SENSOR_LANDSCAPE、
SCREEN_ORIENTATION_SENSOR_PORTRAIT、
SCREEN_ORIENTATION_REVERSE_LANDSCAPE、
SCREEN_ORIENTATION_REVERSE_PORTRAIT、
SCREEN_ORIENTATION_USER_LANDSCAPE、
SCREEN_ORIENTATION_USER_PORTRAIT

手机的方向感应基本上算是都GG了。那点击全屏/竖屏按钮,强制设置了上面的值,还怎么再让手机方向感应自动变化呢。
而且还有一个不合理的场景,如果用户竖着拿手机,点击了界面的全屏播放,我设置界面为横屏了,但此处如果方向传感器还起作用的话,界面又立马变回竖屏了,那用户觉得全屏按钮还有啥作用呀。

:只能这么实现,没法做到点击全屏按钮之后,手机的方向传感器还在继续生效,就算继续生效,也会立马变回竖屏播放,相当于全屏按钮不好使。

:优酷做出来了

:....

:爱奇艺也做出来了

:...那啥,我再看看吧。

下了个爱奇艺和优酷,发现还真是做到了这个功能,他们的功能逻辑实现了方向感应和全屏/半屏按钮手动设置的兼容。对于上面的类似于功能冲突的点,他们的做法是,如果用户竖着拿手机,点击了界面的全屏播放,就会设置界面为横屏显示,方向传感器此时失效,但是当用户拿着手机变化了一下位置,比如我竖着拿手机,点击了全屏,屏幕此时向左横屏显示,但是我拿着手机往右横屏侧过来,此时方向传感器又起作用,把屏幕向右横屏显示。
好吧,用了一下午的时间在研究这个东西,发现不论怎么变换关键字,BD搜索到东西和这个功能没一点关联性,全是在说怎么设置横竖屏的问题,想念谷歌呀!

到后来自己摸索了一套方法,较为简单的解决了这个问题!


首先必须得先了解一下ActivityInfo类的各个属性值代表啥意思,不能乱用:

源码:
@IntDef({
        SCREEN_ORIENTATION_UNSET,
        SCREEN_ORIENTATION_UNSPECIFIED,
        SCREEN_ORIENTATION_LANDSCAPE,
        SCREEN_ORIENTATION_PORTRAIT,
        SCREEN_ORIENTATION_USER,
        SCREEN_ORIENTATION_BEHIND,
        SCREEN_ORIENTATION_SENSOR,
        SCREEN_ORIENTATION_NOSENSOR,
        SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
        SCREEN_ORIENTATION_SENSOR_PORTRAIT,
        SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
        SCREEN_ORIENTATION_REVERSE_PORTRAIT,
        SCREEN_ORIENTATION_FULL_SENSOR,
        SCREEN_ORIENTATION_USER_LANDSCAPE,
        SCREEN_ORIENTATION_USER_PORTRAIT,
        SCREEN_ORIENTATION_FULL_USER,
        SCREEN_ORIENTATION_LOCKED
})

挨个解释一下(先找了这几个,剩下的有空搜到再一个个补充):

ActivityInfo属性值 含义
SCREEN_ORIENTATION_UNSET
SCREEN_ORIENTATION_UNSPECIFIED 默认值,系统根据方向感应自动选择屏幕方向
SCREEN_ORIENTATION_LANDSCAPE 正向横屏,显示的宽比高长(锁死为横屏方向,不再让方向感应起作用)
SCREEN_ORIENTATION_PORTRAIT 正向竖屏,显示的高比宽长(锁死为竖屏方向,不再让方向感应起作用)
SCREEN_ORIENTATION_USER 用户当前首选的方向
SCREEN_ORIENTATION_BEHIND 这个有点奇葩,它跟Activity堆栈中的下面一个Activity的方向一致
SCREEN_ORIENTATION_SENSOR 由设备的方向传感器决定,如果用户旋转设备,这屏幕就会横竖屏切换(这里要注意了:这个属性有些强悍。大家知道安卓手机上都有一个“屏幕旋转”按钮,有的也叫“锁定屏幕”随便什么名字不管了,这个设置里面的开关和Activity有密切关系。关闭它之后Activity界面就不能响应方向传感器了,打开它才会恢复正常,挺合理的一个功能,让决定权放在用户手中。可一旦你设置了这个属性,无论用户怎么设置自己的手机上的“屏幕旋转”按钮,打开也好,关闭也好,Activity界面都会响应方向传感器的,会随着用户手持手机的方向自动变化,这就让用户有点奇怪。)
SCREEN_ORIENTATION_NOSENSOR 忽略物理方向传感器,这样就不会随着用户旋转设备而横竖屏切换了(这里有个坑:如果用户横屏拿着手机进行播放,界面也是横屏的,一旦设置了这个属性之后,手机界面会先变换到竖屏,然后才会锁死方向传感器)
SCREEN_ORIENTATION_SENSOR_LANDSCAPE 横屏,和上面它“爸爸”SENSOR一样强悍,无视用户手机设置的“屏幕旋转”按钮开关,直接根据方向传感器来切换正反向横屏,但是不会切换到竖屏
SCREEN_ORIENTATION_SENSOR_PORTRAIT 竖屏,和上面它“爸爸”SENSOR一样强悍,无视用户手机设置的“屏幕旋转”按钮开关,直接根据方向传感器来切换正反向竖屏,不会切换到横屏
SCREEN_ORIENTATION_REVERSE_LANDSCAPE 反向横屏,横屏分正向横屏(靠左手方向横屏)和反向横屏(靠右手方向横屏)
SCREEN_ORIENTATION_REVERSE_PORTRAIT 反向竖屏,就是和正常竖着拿手机相反,竖着掉了个个
SCREEN_ORIENTATION_FULL_SENSOR
SCREEN_ORIENTATION_USER_LANDSCAPE
SCREEN_ORIENTATION_USER_PORTRAIT
SCREEN_ORIENTATION_FULL_USER
SCREEN_ORIENTATION_LOCKED 锁死用户当前屏幕,方向传感器不生效(这里也有一个坑,低版本不生效,如vivo4.1,你如果使用这个属性来锁定屏幕,它会直接变回到竖屏再锁死)

⑴首先先来分析全屏/半屏按钮,可以这么做:
还是顺着之前的思路来走:

/**
 * 横竖屏切换
 */
private void changeScreenOrientation() {
    //获取用户当前屏幕的横竖位置
    int currentOrientation = getResources().getConfiguration().orientation;
    //判断并设置用户点击全屏/半屏按钮的显示逻辑
    if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
        //如果屏幕当前是横屏显示,则设置屏幕锁死为竖屏显示
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
        //如果屏幕当前是竖屏显示,则设置屏幕锁死为横屏显示
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

设置完之后呢,发现手机的方向感应器失效了。那全屏半屏问题是解决了,
但是,最重要的事情也来了,我们需要在一个正确的“点”上恢复手机的方向感应器!

⑵怎么来找这个点呢?
我们来想,按照优酷的那个实现方法,竖屏拿着手机,点击全屏按钮之后,切换到横屏,此时如果用户不移动手机或者移动的幅度不大,屏幕还是横屏,一旦动作过大(比如我把手机横过来了),此时你会发现,方向感应器又好使了!
就这么来实现它!
在这里介绍一个监听器OrientationEventListener,可以用它来监听用户的手机位置变化情况:

OrientationEventListener orientationListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {

    @Override
    public void onOrientationChanged(int orientation) {
        if(orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
            //手机平放时,检测不到有效的角度
            return;
        }

        /**
         * 只检测是否有四个角度的改变
         */
        if(orientation > 350 || orientation< 10) {
            //0度,用户竖直拿着手机

        } else if(orientation > 80 && orientation < 100) {
            //90度,用户右侧(正向)横屏拿着手机

        } else if(orientation > 170 && orientation < 190) {
            //180度,用户反向竖直拿着手机

        } else if(orientation > 260 && orientation < 280) {
            //270度,用户左侧(反向)横屏拿着手机
        }
    }
};

对应的具体方位图:


0度,用户竖直拿着手机
90度,用户右侧横屏拿着手机
180度,用户反向竖直拿着手机
270度,用户左侧横屏拿着手机

有了这个监听器,就变得很简单了。
我们可以这样,在onOrientationChanged(int orientation)实时记录用户的位置,看是否与记录的用户手机上一次手机所处的位置发生了改变,如果改变了,则用户手机发生了很大的位置偏移,就需要恢复用户手机的方向传感器。

@Override
public void onOrientationChanged(int orientation) {
        //判null
        if(mActivity == null || mActivity.isFinishing()){
            return;
        }
        //记录用户手机上一次放置的位置
        int mLastOrientation = mOrientation;

        if(orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
            //手机平放时,检测不到有效的角度

            //重置为原始位置 -1
            mOrientation = -1;
            return;
        }

        /**
         * 只检测是否有四个角度的改变
         */
        if(orientation > 350 || orientation< 10) {
            //0度,用户竖直拿着手机
            mOrientation = 0;

        } else if(orientation > 80 && orientation < 100) {
            //90度,用户右侧横屏拿着手机
            mOrientation = 90;

        } else if(orientation > 170 && orientation < 190) {
            //180度,用户反向竖直拿着手机
            mOrientation = 180;

        } else if(orientation > 260 && orientation < 280) {
            //270度,用户左侧横屏拿着手机
            mOrientation = 270;
        }

        //如果用户锁定了屏幕,不再开启代码自动旋转了,直接return
        if(mIsLock){
            return;
        }

        //如果用户关闭了手机的屏幕旋转功能,不再开启代码自动旋转了,直接return
        try {
            /**
             * 1 手机已开启屏幕旋转功能
             * 0 手机未开启屏幕旋转功能
             */
            if(Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0){
                return;
            }
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }

        //当检测到用户手机位置距离上一次记录的手机位置发生了改变,开启屏幕自动旋转
        if(mLastOrientation != mOrientation){
            mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        }
    }

大头搞定,剩下的就简单了,完善其他小逻辑。
⑶手机本身的方向传感器
这个简单,可以直接在AndroidManifest.xml中设置SCREEN_ORIENTATION_UNSPECIFIED属性就可以了,剩下的,交给OrientationEventListener小锁的逻辑重新对其赋值即可

<activity
    android:name=".modules.course.DemoActivity"
    android:configChanges="orientation|screenSize|layoutDirection"
    android:screenOrientation="unspecified" />

⑷小锁的逻辑
检测下小锁的开关是否打开,如果打开,就放开手机方向感应器(前提是用户打开了自己手机上的自动旋转);如果关闭,就是锁死手机方向感应器:

/**
 * 锁定/解锁屏幕点击事件
 */
private void lockScreen(){
    if(mLockBtn.isChecked()){
        //锁定屏幕
        //获取用户当前屏幕的横竖位置
        int currentOrientation = getResources().getConfiguration().orientation;
        //判断并设置用户点击锁定屏幕按钮的显示逻辑
        if(currentOrientation == Configuration.ORIENTATION_LANDSCAPE){
            //如果屏幕当前是横屏显示,则设置屏幕锁死为横屏显示
            
            if(mMyOrientationDetector.getDisplayRotation() == 90){
                //正向横屏
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
             } else if(mMyOrientationDetector.getDisplayRotation() == 270){
                //反向横屏
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
             }
        } else if(currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
            //如果屏幕当前是竖屏显示,则设置屏幕锁死为竖屏显示
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    } else {
        //解锁屏幕
        try {
            /**
             * 1 手机已开启屏幕旋转功能
             * 0 手机未开启屏幕旋转功能
             */
            if(Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1){
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
            }
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
    }
}

其中,getDisplayRotation() 是一个检测手机正反向横竖屏的方法:

/**
     * 获取当前屏幕旋转角度
     *
     * @return
     *
     * 0 - 表示是竖屏  90 - 表示是左横屏(正向)  180 - 表示是反向竖屏  270表示是右横屏(反向)
     */
    public int getDisplayRotation() {

        int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
        switch (rotation) {
            case Surface.ROTATION_0:
                return 0;
            case Surface.ROTATION_90:
                return 90;
            case Surface.ROTATION_180:
                return 180;
            case Surface.ROTATION_270:
                return 270;
        }
        return 0;
    }

这里在赘述一点,当时我想的是:
①锁定屏幕,直接设置SCREEN_ORIENTATION_NOSENSOR,不再这么麻烦的先去判断屏幕正反向横竖屏,再去分别锁死,但是这里面具体实现起来发现了个坑,如果用户横屏拿着手机进行播放,界面也是横屏的,一旦设置了这个属性之后,手机界面会先变换到竖屏,然后才会锁死方向传感器。
②锁定屏幕,直接设置SCREEN_ORIENTATION_LOCKED,不再这么麻烦的先去判断屏幕正反向横竖屏,再去分别锁死,但是这里面也发现了个坑,这个属性在低版本手机上不生效,它也会直接变回到竖屏再锁死
③锁定屏幕,判断横竖屏再进行锁死:

if(mLockBtn.isChecked()){
    //锁定屏幕
    //获取用户当前屏幕的横竖位置
    int currentOrientation = getResources().getConfiguration().orientation;
    //判断并设置用户点击锁定屏幕按钮的显示逻辑
    if(currentOrientation == Configuration.ORIENTATION_LANDSCAPE){
        //如果屏幕当前是横屏显示,则设置屏幕锁死为横屏显示
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    } else if(currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
        //如果屏幕当前是竖屏显示,则设置屏幕锁死为竖屏显示
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
}

但是这样的话,也有一个bug:
我在上面介绍各个属性的时候,说过横屏分为正向横屏和反向横屏,竖屏同理。
此时如果用户是反向横屏拿着手机的,代码这么写的话,直接设置SCREEN_ORIENTATION_LANDSCAPE,手机屏幕会直接翻转到正向横屏再锁死,让用户感到奇怪。
以上就是我做锁定屏幕的时候,经历的种种探索,感觉好麻烦,但是做出来还是挺开心的。


OK,到了这里,就把三个逻辑融合到一起了。最后再优化优化逻辑(大体思路就是上面的这些东西)、封装成一个工具类:

/**
 * 自定义工具类
 *
 * 实时的检测用户屏幕的位置改变,做到 重力感应 与 全屏/半屏按钮 逻辑的互容
 */
public class CLOrientationDetector extends OrientationEventListener {

    /**
     * 横竖屏BaseActivity
     */
    private BaseActivity mActivity;
    /**
     * 用户是否锁定屏幕
     */
    private boolean mIsLock = false;
    /**
     * 实时记录用户手机屏幕的位置
     */
    private int mOrientation = -1;

    /**
     * 构造方法
     * @param activity
     */
    public CLOrientationDetector(BaseActivity activity) {
        super(activity);
        mActivity = activity;
    }

    /**
     * 设置用户屏幕是否被锁定
     * @param isLock
     */
    public void setIsLock(boolean isLock){
        mIsLock = isLock;
    }

    @Override
    public void onOrientationChanged(int orientation) {
        //判null
        if(mActivity == null || mActivity.isFinishing()){
            return;
        }
        //记录用户手机上一次放置的位置
        int mLastOrientation = mOrientation;

        if(orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
            //手机平放时,检测不到有效的角度

            //重置为原始位置 -1
            mOrientation = -1;
            return;
        }

        /**
         * 只检测是否有四个角度的改变
         */
        if(orientation > 350 || orientation< 10) {
            //0度,用户竖直拿着手机
            mOrientation = 0;

        } else if(orientation > 80 && orientation < 100) {
            //90度,用户右侧横屏拿着手机
            mOrientation = 90;

        } else if(orientation > 170 && orientation < 190) {
            //180度,用户反向竖直拿着手机
            mOrientation = 180;

        } else if(orientation > 260 && orientation < 280) {
            //270度,用户左侧横屏拿着手机
            mOrientation = 270;
        }

        //如果用户锁定了屏幕,不再开启代码自动旋转了,直接return
        if(mIsLock){
            return;
        }

        //如果用户关闭了手机的屏幕旋转功能,不再开启代码自动旋转了,直接return
        try {
            /**
             * 1 手机已开启屏幕旋转功能
             * 0 手机未开启屏幕旋转功能
             */
            if(Settings.System.getInt(mActivity.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0){
                return;
            }
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }

        //当检测到用户手机位置距离上一次记录的手机位置发生了改变,开启屏幕自动旋转
        if(mLastOrientation != mOrientation){
            mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        }
    }

    /**
     * 获取当前屏幕旋转角度
     *
     * @return
     *
     * 0 - 表示是竖屏  90 - 表示是左横屏(正向)  180 - 表示是反向竖屏  270表示是右横屏(反向)
     */
    public int getDisplayRotation() {

        int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
        switch (rotation) {
            case Surface.ROTATION_0:
                return 0;
            case Surface.ROTATION_90:
                return 90;
            case Surface.ROTATION_180:
                return 180;
            case Surface.ROTATION_270:
                return 270;
        }
        return 0;
    }
}

这篇文章说的比较简单,主要想表明的就是这个思路,思路有了,就上手代码就容易了。小伙伴们如果有更好的思路的话,欢迎指正。

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

推荐阅读更多精彩内容