Android 列表視頻的全屏孽糖、自動小窗口優(yōu)化實(shí)踐

Hello,愛貓的老司機(jī)來埋坑啦<( ̄︶ ̄)>毅贮,鑒于之前的《Android 實(shí)現(xiàn)視屏播放器办悟、邊播邊緩存功能、外加鏟屎(IJKPlayer)》好像還挺多人關(guān)注的滩褥,文中一些地方因?yàn)槠ň褪菓校﹩栴}一筆帶過病蛉,這篇就拓?fù)淞囊涣钠渲辛斜砣粒€有播放中的視頻滑出屏幕用小窗口播放的實(shí)現(xiàn)瑰煎,剛好最近有做了一些調(diào)整铺然。

上例牌 github>>>>>>>> https://github.com/CarGuo 對,就是這個郭老司機(jī)酒甸。

本期就不話嘮了探熔,周一誰有精力說話呢┑( ̄Д  ̄)┍,程序猿的周末是什么烘挫?

列表中播放視頻全屏展示

看過小喵上一篇視頻相關(guān)文章的應(yīng)該知道小喵手賤的用了兩種實(shí)現(xiàn)方式诀艰,一種是基于懶人的系統(tǒng)層模式柬甥;一種是基于單例的UI邏輯播放器的模式的ListVideoUtil。至于為什么是兩種呢其垄?因?yàn)槭仲v啊苛蒲。(ノ?益?)ノ彡┻━┻,本文如有不明之處可結(jié)合前文一起食用:《Android 實(shí)現(xiàn)視屏播放器绿满、邊播邊緩存功能臂外、外加鏟屎(IJKPlayer)》

1喇颁、系統(tǒng)層實(shí)現(xiàn)全屏播放

偉人曾經(jīng)說過漏健,每一個Activity都有一個自己的默認(rèn)布局,這里面又包含有了一個com.android.internal.R.id.content橘霎,而且是一個FrameLayout(請無視上面的廢話)蔫浆,如此看來用來作為我們?nèi)溜@示的父布局妥妥的。此處手賤的加入了動畫效果的支持姐叁,一直覺得5.0的過渡動畫挺高大上的瓦盛,作為一個material design的應(yīng)用必須有這樣的逼格(什么?你說兼容外潜?這里美女太多我聽不到····)原环。

作為一只內(nèi)向的程序猿,語言組織能力有限处窥,我們還是從代碼上來嘱吗,從代碼上去吧,注釋滿滿的滔驾,順序看下去不難理解(前提是你看的下柜与,確實(shí)長♂了點(diǎn))。

1.1 進(jìn)入全屏
  • 獲取到了com.android.internal.R.id.content這個ViewGroup嵌灰。
  • 清除當(dāng)前列表播放器L上的TextureView渲染控件,等待全屏播放器F的渲染控件颅悉。
  • 新創(chuàng)建一個視頻邏輯播放器F沽瞭,為它設(shè)置一個固定id,這樣干掉它的時候通過這個id也能快速找到剩瓶。
  • 保存當(dāng)前的狀態(tài)欄驹溃、標(biāo)題欄信息和列表中在屏幕位置的信息,用于恢復(fù)到原本的狀態(tài)延曙。
  • 創(chuàng)建一個黑色背景的FrameLayout豌鹤,充滿屏幕用來承載全屏播放器F,這樣全屏播放器F可以在其中執(zhí)行動畫效果枝缔。
  • 5.0以下直接加全屏播放器F到ViewGroup居中充滿全屏布疙,5.0以上則執(zhí)行動畫蚊惯。
  • 5.0以上先通過margin讓全屏播放器加入到ViewGroup同列表的位置一致,之后通過過渡動畫平移到屏幕中間灵临,居中充滿全屏截型。

怎么樣,看起來是不是有些混亂儒溉?(ノ?益?)ノ彡┻━┻宦焦,我就說程序猿還是看代碼好溝通是吧,雖然很長就是顿涣。

 
//獲得com.android.internal.R.id.content
private ViewGroup getViewGroup() {    
    return (ViewGroup) (CommonUtil.scanForActivity(getContext())).findViewById(Window.ID_ANDROID_CONTENT);
}

···此處省略無數(shù)只草泥馬

//這兩個是TextureView的回調(diào)波闹,在這remove和onPause還有add的時候基本會進(jìn)入
 @Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
    //更新數(shù)據(jù)到這個surface上渲染
    mSurface = new Surface(surface);
    GSYVideoManager.instance().setDisplay(mSurface);
}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    //告訴數(shù)據(jù)管理器這個渲染控件放棄了
    GSYVideoManager.instance().setDisplay(null);
    surface.release();
    return true;
}

···此處省略無數(shù)只草泥馬

這個開始全屏的頁面邏輯

//將播放的視頻渲染控件移除,進(jìn)入上面的回調(diào)涛碑,讓新的邏輯播放器可以接入
if (mTextureViewContainer.getChildCount() > 0) {
    mTextureViewContainer.removeAllViews();
}

//保存全屏之前的狀態(tài)欄和
saveLocationStatus(context, statusBar, actionBar);

try {
    //生成一個播放器精堕,因?yàn)槔^承關(guān)系,會創(chuàng)建一個當(dāng)前列表item一樣的UI邏輯播放器
    //這些邏輯都是寫在GSYBaseVideoPlayer這個抽象類下
    Constructor<GSYBaseVideoPlayer> constructor = (Constructor<GSYBaseVideoPlayer>) GSYBaseVideoPlayer.this.getClass().getConstructor(Context.class);
    final GSYBaseVideoPlayer gsyVideoPlayer = constructor.newInstance(getContext());
    //給它一個固定的id锌唾,在這樣移除的時候就知道在哪里
    gsyVideoPlayer.setId(FULLSCREEN_ID);
    //獲取屏幕的高度
    WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    final int w = wm.getDefaultDisplay().getWidth();
    final int h = wm.getDefaultDisplay().getHeight();
    //創(chuàng)建一個層用于加入都window層中锄码,設(shè)置為黑色,用于包含著播放器
    FrameLayout.LayoutParams lpParent = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    FrameLayout frameLayout = new FrameLayout(context);
    frameLayout.setBackgroundColor(Color.BLACK);
    //如果5.0的機(jī)器就執(zhí)行動畫晌涕,這里其實(shí)可以用VauleAnimaton兼容5.0以下的
    if (mShowFullAnimation && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        //先把播放器的位置設(shè)置為在列表中一樣位置
        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(getWidth(), getHeight());
        lp.setMargins(mListItemRect[0], mListItemRect[1], 0, 0);
        frameLayout.addView(gsyVideoPlayer, lp);
        vp.addView(frameLayout, lpParent);
        //稍微延時執(zhí)行動畫
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //開啟5.0動畫
                TransitionManager.beginDelayedTransition(vp);
                //將播放器跳轉(zhuǎn)為充滿居中滋捶,系統(tǒng)自動過渡
                resolveFullVideoShow(context, gsyVideoPlayer, h, w);
            }
        }, 300);
    } else {
        //非5.0的直接將播放器的布局加入到布局下
        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(getWidth(), getHeight());
        frameLayout.addView(gsyVideoPlayer, lp);
        vp.addView(frameLayout, lpParent);
        //將播放器跳轉(zhuǎn)為充滿居中
        resolveFullVideoShow(context, gsyVideoPlayer, h, w);
    }
    //設(shè)置全屏邏輯播放器和當(dāng)前列表的邏輯狀態(tài)一致
    gsyVideoPlayer.setUp(mUrl, mCache, mObjects);
    gsyVideoPlayer.setStateAndUi(mCurrentState);
    //添加上渲染控件,通知數(shù)據(jù)加載管理器是用這個渲染
    gsyVideoPlayer.addTextureView();
    //配置對應(yīng)UI
    gsyVideoPlayer.getFullscreenButton().setImageResource(R.drawable.video_shrink);
    gsyVideoPlayer.getFullscreenButton().setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            clearFullscreenLayout();
        }
    });

    gsyVideoPlayer.getBackButton().setVisibility(VISIBLE);
    gsyVideoPlayer.getBackButton().setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            clearFullscreenLayout();
        }
    });
    //將數(shù)據(jù)加載管理器的接口回到配置到全屏播放器里面
    GSYVideoManager.instance().setLastListener(this);
    GSYVideoManager.instance().setListener(gsyVideoPlayer);

} catch (Exception e) {
    e.printStackTrace();
}

···此處省略無數(shù)只草泥馬

/**
 * 全屏
 */
private void resolveFullVideoShow(Context context, GSYBaseVideoPlayer gsyVideoPlayer) {
    //清除動畫的margin
    FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) gsyVideoPlayer.getLayoutParams();
    lp.setMargins(0, 0, 0, 0);
    //居中充滿
    lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
    lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
    lp.gravity = Gravity.CENTER;
    gsyVideoPlayer.setLayoutParams(lp);
    gsyVideoPlayer.setIfCurrentIsFullscreen(true);
    //加入旋轉(zhuǎn)工具類
    mOrientationUtils = new OrientationUtils((Activity) context, gsyVideoPlayer);
    mOrientationUtils.setEnable(mRotateViewAuto);
}

1.2 退出全屏

既然都進(jìn)去了♂余黎,出來還難嗎重窟?所以我們只需要反著來就行了,下面直接長代碼惧财,有注釋巡扇。(男人長一點(diǎn)有什么錯┑( ̄Д  ̄)┍)

  • 是否橫屏,是的話先轉(zhuǎn)為豎屏
  • 恢復(fù)狀態(tài)欄和標(biāo)題欄
  • 5.0以下直接清除當(dāng)前列全屏播放器F垮衷,恢復(fù)視頻狀態(tài)
  • 5.0以上顯示讓全屏播放器F過渡到原本的位置厅翔,再清除恢復(fù)視頻狀態(tài)
/**
 * 退出系統(tǒng)層播放全屏效果
 */
public void clearFullscreenLayout() {

    //需要判斷當(dāng)前是否橫屏,是的話要轉(zhuǎn)為界面之后稍等一會在退回搀突,這樣才不會界面抖動
    int delay = mOrientationUtils.backToProtVideo();
    //關(guān)閉旋轉(zhuǎn)
    mOrientationUtils.setEnable(false);
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            backToNormal();
        }
    }, delay);
}

/**
 * 回到正常效果
 */
private void backToNormal() {
    //恢復(fù)狀態(tài)
    showSupportActionBar(mContext, mActionBar, mStatusBar);
    final ViewGroup vp = getViewGroup();
    //拿到content和播放器
    final View oldF = vp.findViewById(FULLSCREEN_ID);
    final GSYVideoPlayer gsyVideoPlayer;
    if (oldF != null) {
        gsyVideoPlayer = (GSYVideoPlayer) oldF;
        if (mShowFullAnimation && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            TransitionManager.beginDelayedTransition(vp);
            //執(zhí)行動畫回到原本的列表中的位置
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) gsyVideoPlayer.getLayoutParams();
            lp.setMargins(mListItemRect[0], mListItemRect[1], 0, 0);
            lp.width = mListItemSize[0];
            lp.height = mListItemSize[1];
            //注意配置回來刀闷,不然動畫效果會不對
            lp.gravity = Gravity.NO_GRAVITY;
            gsyVideoPlayer.setLayoutParams(lp);

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    resolveNormalVideoShow(oldF, vp, gsyVideoPlayer);
                }
            }, 400);
        } else {
            //直接移除
            resolveNormalVideoShow(oldF, vp, gsyVideoPlayer);
        }

    } else {
        //直接移除
        resolveNormalVideoShow(null, vp, null);
    }
}


/**
 * 恢復(fù)
 */
private void resolveNormalVideoShow(View oldF, ViewGroup vp, GSYVideoPlayer gsyVideoPlayer) {
    //移除全屏播放器
    if (oldF.getParent() != null) {
        ViewGroup viewGroup = (ViewGroup) oldF.getParent();
        vp.removeView(viewGroup);
    }
    //拿回狀態(tài)
    mCurrentState = GSYVideoManager.instance().getLastState();
    if (gsyVideoPlayer != null) {
        mCurrentState = gsyVideoPlayer.getCurrentState();
    }
    //重新設(shè)置回調(diào)
    GSYVideoManager.instance().setListener(GSYVideoManager.instance().lastListener());
    GSYVideoManager.instance().setLastListener(null);
    //播放器恢復(fù)
    setStateAndUi(mCurrentState);
    //通知數(shù)據(jù)加載播放器用回列表的渲染
    addTextureView();
    CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
}

2、ListVideoUtil實(shí)現(xiàn)全屏播放

總體上邏輯和上文是一致的仰迁,只是這種實(shí)現(xiàn)在列表中是不包含邏輯播放器甸昏,邏輯播放器和全屏邏輯播放器都是一個單例,需要你手動在list列表的最外層加多一個布局做全屏播放徐许,在每個item那里預(yù)留一個位置用于包容列表的播放器施蜜,還有一個播放按鈕用于播放。

感覺很麻煩是吧雌隅,耦合度又高翻默,但是它可以在視頻滑出界面的時候不被釋放缸沃,一直保持在原來的位置。

2.1 全屏

和上面的邏輯基本一致冰蘑,就不廢話了(可以偷懶了)和泌,只需要注意用的時候操作方式不一樣,總結(jié)起來就是有些麻煩祠肥。


//配置好全屏布局
listVideoUtil.setFullViewContainer(videoFullContainer);
listVideoUtil.setHideStatusBar(true);

···此處省略無數(shù)只草泥馬

//增加封面
ImageView imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(R.mipmap.xxx1);
//將列表的位置武氓,封面,列表的TAG仇箱,列表是的父布局县恕,播放按鍵傳入進(jìn)去
listVideoUtil.addVideoPlayer(position, imageView, TAG, holder.videoContainer, holder.playerBtn);

holder.playerBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //更新其他item
        notifyDataSetChanged();
        //設(shè)置播放器的標(biāo)志位,防止錯位
        listVideoUtil.setPlayPositionAndTag(position, TAG);
        //url開始播放
        final String url = "http://baobab.wdjcdn.com/14564977406580.mp4";
        listVideoUtil.startPlay(url);
    }
});

列表中播放視頻小窗口播放

有時候我們會想要視頻滑出屏幕的時候有個小窗口在右下角剂桥,最好還是可以關(guān)閉和拖動的(看視頻的時候可以快速最小化收起來忠烛,不停止,避免尷尬對吧)权逗。邏輯和實(shí)現(xiàn)全屏一樣美尸,用系統(tǒng)的content層來承載,不同的是利用margin讓視頻出現(xiàn)在右下角斟薇,這樣我們拖動的時候只要改變視頻的margin师坎,就可以讓視頻小窗體在它的父布局內(nèi)移動啦。

小窗口
/**
 * 顯示小窗口
 */
public void showSmallVideo(Point size, final boolean actionBar, final boolean statusBar) {
    //利用content實(shí)現(xiàn)堪滨,和全屏一樣胯陋,只是大小和背景色不一樣
    final ViewGroup vp = getViewGroup();

    removeVideo(vp, SMALL_ID);

    if (mTextureViewContainer.getChildCount() > 0) {
        mTextureViewContainer.removeAllViews();
    }

    try {
        Constructor<GSYBaseVideoPlayer> constructor = (Constructor<GSYBaseVideoPlayer>) GSYBaseVideoPlayer.this.getClass().getConstructor(Context.class);
        GSYBaseVideoPlayer gsyVideoPlayer = constructor.newInstance(getContext());
        gsyVideoPlayer.setId(SMALL_ID);

        FrameLayout.LayoutParams lpParent = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        FrameLayout frameLayout = new FrameLayout(mContext);

        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(size.x, size.y);
        int marginLeft = CommonUtil.getScreenWidth(mContext) - size.x;
        int marginTop = CommonUtil.getScreenHeight(mContext) - size.y;

        if (actionBar) {
            marginTop = marginTop - getActionBarHeight((Activity) mContext);
        }

        if (statusBar) {
            marginTop = marginTop - getStatusBarHeight(mContext);
        }
        //利用margin讓視頻出現(xiàn)在右下角,這樣我們拖動的時候只要改變margin就好啦
        lp.setMargins(marginLeft, marginTop, 0, 0);
        frameLayout.addView(gsyVideoPlayer, lp);

        vp.addView(frameLayout, lpParent);
        //繼續(xù)播放
        gsyVideoPlayer.setUp(mUrl, mCache, mObjects);
        gsyVideoPlayer.setStateAndUi(mCurrentState);
        gsyVideoPlayer.addTextureView();
        gsyVideoPlayer.onClickUiToggle();
        gsyVideoPlayer.setSmallVideoTextureView(new SmallVideoTouch(gsyVideoPlayer, marginLeft, marginTop));

        GSYVideoManager.instance().setLastListener(this);
        GSYVideoManager.instance().setListener(gsyVideoPlayer);

    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

/**
 * 隱藏小窗口
 */
public void hideSmallVideo() {
    final ViewGroup vp = getViewGroup();
    GSYVideoPlayer gsyVideoPlayer = (GSYVideoPlayer) vp.findViewById(SMALL_ID);
    removeVideo(vp, SMALL_ID);
    mCurrentState = GSYVideoManager.instance().getLastState();
    if (gsyVideoPlayer != null) {
        mCurrentState = gsyVideoPlayer.getCurrentState();
    }
    GSYVideoManager.instance().setListener(GSYVideoManager.instance().lastListener());
    GSYVideoManager.instance().setLastListener(null);
    setStateAndUi(mCurrentState);
    addTextureView();
    CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
}

這是觸摸邏輯袱箱,這拖動的視頻窗體的時候遏乔,通過改變margin來實(shí)現(xiàn)窗體的移動,注意不要跑飛了就要发笔,加個閾值盟萨。多說無益,看代碼(又省下了好多字):

public class SmallVideoTouch implements View.OnTouchListener {

    private int mDownX, mDownY;
    private int mMarginLeft, mMarginTop;
    private int _xDelta, _yDelta;
    private GSYBaseVideoPlayer mGsyBaseVideoPlayer;


    public SmallVideoTouch(GSYBaseVideoPlayer gsyBaseVideoPlayer, int marginLeft,  int marginTop) {
        super();
        mMarginLeft = marginLeft;
        mMarginTop = marginTop;
        mGsyBaseVideoPlayer = gsyBaseVideoPlayer;
    }

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        final int X = (int) event.getRawX();
        final int Y = (int) event.getRawY();
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                mDownX = X;
                mDownY = Y;

                FrameLayout.LayoutParams lParams = (FrameLayout.LayoutParams) mGsyBaseVideoPlayer
                        .getLayoutParams();
                _xDelta = X - lParams.leftMargin;
                _yDelta = Y - lParams.topMargin;

                break;
            case MotionEvent.ACTION_UP:
                if (Math.abs(mDownY - Y) < 5 && Math.abs(mDownX - X) < 5) {
                    return false;
                } else {
                    return true;
                }
            case MotionEvent.ACTION_MOVE:
                FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mGsyBaseVideoPlayer
                        .getLayoutParams();

                layoutParams.leftMargin = X - _xDelta;
                layoutParams.topMargin = Y - _yDelta;
                
                //不能超過屏幕上下左右的位置
                if (layoutParams.leftMargin >= mMarginLeft) {
                    layoutParams.leftMargin = mMarginLeft;
                }

                if (layoutParams.topMargin >= mMarginTop) {
                    layoutParams.topMargin = mMarginTop;
                }

                if (layoutParams.leftMargin <= 0) {
                    layoutParams.leftMargin = 0;
                }

                if (layoutParams.topMargin <= 0) {
                    layoutParams.topMargin = 0;
                }

                mGsyBaseVideoPlayer.setLayoutParams(layoutParams);

        }
        return false;
    }

}
最后

如果你看到這里了讨,恭喜你看完了<( ̄︶ ̄)>捻激!那么,下面還有沙發(fā)量蕊,請問您要坐一坐嗎?d=====( ̄▽ ̄*)b不坐也沒關(guān)系艇挨,還有g(shù)ithub可以去呢:https://github.com/CarGuo 残炮。

來一下嘛
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缩滨,隨后出現(xiàn)的幾起案子势就,更是在濱河造成了極大的恐慌泉瞻,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苞冯,死亡現(xiàn)場離奇詭異袖牙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)舅锄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門鞭达,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人皇忿,你說我怎么就攤上這事畴蹭。” “怎么了鳍烁?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵叨襟,是天一觀的道長。 經(jīng)常有香客問我幔荒,道長糊闽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任爹梁,我火速辦了婚禮右犹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卫键。我一直安慰自己傀履,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布莉炉。 她就那樣靜靜地躺著钓账,像睡著了一般。 火紅的嫁衣襯著肌膚如雪絮宁。 梳的紋絲不亂的頭發(fā)上梆暮,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音绍昂,去河邊找鬼啦粹。 笑死,一個胖子當(dāng)著我的面吹牛窘游,可吹牛的內(nèi)容都是我干的唠椭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼忍饰,長吁一口氣:“原來是場噩夢啊……” “哼贪嫂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起艾蓝,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤力崇,失蹤者是張志新(化名)和其女友劉穎斗塘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亮靴,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡馍盟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了茧吊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贞岭。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饱狂,靈堂內(nèi)的尸體忽然破棺而出曹步,到底是詐尸還是另有隱情,我是刑警寧澤休讳,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布讲婚,位于F島的核電站,受9級特大地震影響俊柔,放射性物質(zhì)發(fā)生泄漏筹麸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一雏婶、第九天 我趴在偏房一處隱蔽的房頂上張望物赶。 院中可真熱鬧,春花似錦留晚、人聲如沸酵紫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奖地。三九已至,卻和暖如春赋焕,著一層夾襖步出監(jiān)牢的瞬間参歹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工隆判, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留犬庇,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓侨嘀,卻偏偏與公主長得像臭挽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子咬腕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

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