帶你一步一步實現(xiàn)listview上拉加載下拉刷新

帶你一步一步實現(xiàn)listview上拉加載下拉刷新

思路:

  • 要是實現(xiàn)這個效果我們需要尉尾,有一個view能在頭部和底部存在(通過查找的只listview有addheard,和addfoot的方法可以將一個view添加到頭部的底部)
  • 如何進來的時候不顯示頭部的view呢隅居?(我門可以設(shè)置View的初始高度為0梧宫,或者設(shè)置setPadding設(shè)置他距離上面的距離為-的高度就可以隱藏了莺琳,我們使用setPadding方法)
  • 如何隱藏底部的view蛉幸?(同上)
  • 如何能讓view跟著我們的手勢移動呢赏酥?(第一種我們可以使用OverScroller這個類,第二種我們可以通過動態(tài)的改變頭部view和底部view的高度來實現(xiàn)移動的的效果医增,我們使用后者)
  • 如何實現(xiàn)view的自動回彈呢?(我們可以使用OverScroller這個類的startScroll方法老虫,然后實現(xiàn)computeScroll方法在這個里面去動態(tài)的改變view的高度)

第一步我們創(chuàng)建HeaderView這個類當(dāng)頂部的刷新的view


public class HeaderView extends LinearLayout {
    /** 刷新狀態(tài) */
    private LoadState mState = LoadState.NORMAL;

    private View mHeader = null;
    private ImageView mArrow = null;
    private ProgressBar mProgressBar = null;
    private TextView mRefreshTips = null;
    private TextView mRefreshLastTime = null;
    private RotateAnimation mRotateUp = null;
    private RotateAnimation mRotateDown = null;
    private final static int ROTATE_DURATION = 250;

    /** 一分鐘的毫秒值叶骨,用于判斷上次的更新時間. */
    private final long ONE_MINUTE = 60 * 1000;
    /** 一小時的毫秒值,用于判斷上次的更新時間. */
    private final long ONE_HOUR = 60 * ONE_MINUTE;
    /** 一天的毫秒值祈匙,用于判斷上次的更新時間. */
    private final long ONE_DAY = 24 * ONE_HOUR;
    /** 一月的毫秒值忽刽,用于判斷上次的更新時間. */
    private final long ONE_MONTH = 30 * ONE_DAY;
    /** 一年的毫秒值,用于判斷上次的更新時間. */
    private final long ONE_YEAR = 12 * ONE_MONTH;

    public HeaderView(Context context) {
        this(context, null);
    }

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

    private void initHeaderView(Context context) {
        LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
        mHeader = LayoutInflater.from(context).inflate(R.layout.g_refresh_header, null);
        addView(mHeader, lp);
        setGravity(Gravity.BOTTOM);
        mArrow = (ImageView) mHeader.findViewById(R.id.ivArrow);
        mProgressBar = (ProgressBar) mHeader.findViewById(R.id.pbWaiting);
        mRefreshTips = (TextView) mHeader.findViewById(R.id.refresh_tips);
        mRefreshLastTime = (TextView) mHeader.findViewById(R.id.refresh_last_time);
        //初始化旋轉(zhuǎn)的動畫需要反轉(zhuǎn)箭頭
        mRotateUp = new RotateAnimation(0.0f, -180.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateUp.setDuration(ROTATE_DURATION);
        mRotateUp.setFillAfter(true);

        mRotateDown = new RotateAnimation(-180.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateDown.setDuration(ROTATE_DURATION);
        mRotateDown.setFillAfter(true);
        Log.e("HeaderView","HeaderView初始化了");
    }

    public void setHeaderState(LoadState state) {
        if (mState == state) {
            return;
        }
        mArrow.clearAnimation();
        if (state == LoadState.LOADING) {
            mArrow.setVisibility(View.GONE);
            mProgressBar.setVisibility(View.VISIBLE);
        } else {
            mProgressBar.setVisibility(View.GONE);
            mArrow.setVisibility(View.VISIBLE);
        }

        switch (state) {
        case NORMAL:
            mArrow.startAnimation(mRotateDown);
            mRefreshTips.setText(R.string.g_pull_down_for_refresh);
            break;

        case WILL_RELEASE:
            //旋轉(zhuǎn)當(dāng)前的箭頭的狀態(tài)
            mArrow.startAnimation(mRotateUp);
            mRefreshTips.setText(R.string.g_release_for_refresh);
            break;

        case LOADING:
            mRefreshTips.setText(R.string.g_refreshing);
            break;

        default:
            break;
        }

        mState = state;
    }

    public LoadState getCurrentState() {
        return mState;
    }

    public void setHeaderHeight(int height) {
        if (height <= 0) {
            height = 0;
        }
        LayoutParams lp = (LayoutParams) mHeader.getLayoutParams();
        lp.height = height;
        mHeader.setLayoutParams(lp);
    }

    public int getHeaderHeight() {
        return mHeader.getHeight();
    }



我們可以看到HeaderView這個類很簡單夺欲,就是初始化一個view,然后提供了設(shè)置高度跪帝,和不同狀態(tài)的判斷顯示的不同字體的邏輯

我們創(chuàng)建FooterView這個類其實和heardview一樣

        
/**
 * 底部
 */
public class FooterView extends LinearLayout {
    /** 加載更多. */
    private LoadState mState = LoadState.NORMAL;

    private View mFooter = null;
    private ImageView mArrow = null;
    private ProgressBar mProgressBar = null;
    private TextView mLoaderTips = null;

    private RotateAnimation mRotateUp = null;
    private RotateAnimation mRotateDown = null;
    private final static int ROTATE_DURATION = 250;

    public FooterView(Context context) {
        this(context, null);
    }

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

    private void initFooterView(Context context) {
        LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
        mFooter = LayoutInflater.from(context).inflate(R.layout.g_loader_footer, null);
        addView(mFooter, lp);

        mArrow = (ImageView) mFooter.findViewById(R.id.ivLoaderArrow);
        mProgressBar = (ProgressBar) mFooter.findViewById(R.id.pbLoaderWaiting);
        mLoaderTips = (TextView) mFooter.findViewById(R.id.loader_tips);

        mRotateDown = new RotateAnimation(0.0f, 180.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateDown.setDuration(ROTATE_DURATION);
        mRotateDown.setFillAfter(true);

        mRotateUp = new RotateAnimation(180.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateUp.setDuration(ROTATE_DURATION);
        mRotateUp.setFillAfter(true);

        show();
    }

    public void setFooterState(LoadState state) {
        if (mState == state) {
            return;
        }

        mArrow.clearAnimation();
        if (state == LoadState.LOADING) {
            mProgressBar.setVisibility(View.VISIBLE);
            mArrow.setVisibility(View.GONE);
        } else if (state == LoadState.NODATA) {
            mProgressBar.setVisibility(View.GONE);
            mArrow.setVisibility(View.GONE);
        } else {
            mProgressBar.setVisibility(View.GONE);
            mArrow.setVisibility(View.VISIBLE);
        }

        switch (state) {
        case NORMAL:
            mArrow.startAnimation(mRotateUp);
            mLoaderTips.setText(R.string.g_pull_up_for_more);
            break;

        case WILL_RELEASE:
            mArrow.startAnimation(mRotateDown);
            mLoaderTips.setText(R.string.g_release_for_more);
            break;

        case LOADING:
            mLoaderTips.setText(R.string.g_loading);
            break;

        case NODATA:
            mLoaderTips.setText(R.string.g_nodata);
            break;

        default:
            break;
        }
        mState = state;
    }

    public LoadState getCurrentState() {
        return mState;
    }

    public void setFooterHeight(int height) {
        if (height <= 0) {
            height = 0;
        }

        LayoutParams lp = (LayoutParams) mFooter.getLayoutParams();
        lp.height = height;
        mFooter.setLayoutParams(lp);
    }

    public int getFooterHeight() {
        return mFooter.getHeight();
    }

}


邏輯也是一樣,設(shè)置高度些阅,提供不同狀態(tài)的判斷伞剑,顯示不同的內(nèi)容

接下來上我們的主要類XrefershListview



/**
 * 作者:liujingyuan on 2015/12/21 13:14
 * 郵箱:906514731@qq.com
 * 自定義的下拉刷新上拉加載的Listview
 */
public class XrefershListview extends ListView implements AbsListView.OnScrollListener {
    private final static String TAG = "[XrefershListview]";
    private final static float OFFSET_Y = 0.7f;
    private OverScroller mScroller;
    private final static int SCROLL_HEADER = 0;
    private final static int SCROLL_FOOTER = 1;
    //刷新的監(jiān)聽
    public XrefershListviewListener mListViewListener;
    /** 滑動項. */
    private int iScrollWhich = SCROLL_HEADER;
    //是否顯示footview
    public boolean isShowLoadeFooterView=false;
    HeaderView mHeaderView;
    FooterView mFooterView;
    int   iHeaderHeight;
    int iFooterHeight;
    float EndRawy;
    float mStartY;
    float dy;
    private float mLastY;

    public XrefershListview(Context context) {
        super(context);
        initHeardView(context);
    }

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

    public XrefershListview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initHeardView(context);
    }
    //初始化頭部的view
    private void initHeardView(Context context) {
        //初始化scmScroller
        mScroller = new OverScroller(context,new DecelerateInterpolator());
        mHeaderView = new HeaderView(context);
        mFooterView = new FooterView(context);
        //初始化hearview的高度
        mHeaderView.setHeaderHeight(200);
        //初始化footview
        initFooterView(context);
        final RelativeLayout header_content = (RelativeLayout) mHeaderView.findViewById(R.id.header_content);
        addHeaderView(mHeaderView);
        this.setOnScrollListener(this);
        //監(jiān)聽到view加載完畢獲取view的高度
        mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                iHeaderHeight =mHeaderView.getMeasuredHeight();
                Log.d(TAG, "iHeaderHeight = " + iHeaderHeight);
                //剛進來的時候我們隱藏heardview
                mHeaderView.setPadding(0,-iHeaderHeight,0,0);
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //按下的時候我們需要記住起始點的Y軸的坐標(biāo)
                mLastY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                //移動的時候獲取當(dāng)前的y軸的坐標(biāo)
                mStartY = ev.getY();
                //計算滑動的距離
                dy=mStartY-mLastY;
                //再次獲取一次,因為我們是增量增加寬度的市埋,每次獲取的是相對于上一點的位移
                mLastY = ev.getY();
                if (getFirstVisiblePosition()==0&& (mHeaderView.getMeasuredHeight() > 0 || dy > 0)){
                    //通過改變heardview的高度
                    upDataHeardView(dy*0.7f);
                }else if (getLastVisiblePosition() == getCount() - 1 && (mFooterView.getFooterHeight() > 0 || dy < 0)){
                    //通過改變footview的高度
                    updateFooterState(-dy);
                }
                Log.e(TAG,"dy============"+dy);
               break;
            case MotionEvent.ACTION_UP:
                EndRawy = ev.getRawY();
                //如果當(dāng)前的可見的第一個條目是0黎泣,并且當(dāng)前的hreadview的高度不為0,滑動的距離大于0就證明是在下拉刷新
                if (getFirstVisiblePosition()==0&& (mHeaderView.getMeasuredHeight() > 0 || dy > 0)){
                    //判斷當(dāng)前的狀態(tài)不是正在刷新的狀態(tài)就設(shè)置為刷新的狀態(tài)
                    if (mHeaderView.getCurrentState() != LoadState.LOADING) {
                        if (mHeaderView.getHeaderHeight() > iHeaderHeight) {
                            mHeaderView.setHeaderState(LoadState.LOADING);
                            //調(diào)用是界面的刷新,延時1秒
                            mListViewListener.onRefresh();
                            new Handler().postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    resetHeaderHeight();
                                }
                            },1000);
                        }
                    }
                 //如果當(dāng)前已經(jīng)顯示到最后一個條目了就是上拉加載缤谎,并且當(dāng)前footview的高度大于0聘裁,移動的距離也大于0
                }else if(getLastVisiblePosition() == getCount() - 1 && (mFooterView.getFooterHeight() > 0 || dy < 0)){
                    //判斷當(dāng)前的狀態(tài)不是正在刷新的狀態(tài)就設(shè)置為刷新的狀態(tài)
                    if (mFooterView.getCurrentState() != LoadState.LOADING) {
                        if (mFooterView.getFooterHeight() > iFooterHeight) {
                            mFooterView.setFooterState(LoadState.LOADING);
                            new Handler().postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    //調(diào)用是界面的刷新,延時1秒
                                    mListViewListener.onLoadMore();
                                    resetFooter();
                                }
                            },3000);
                        }
                    }
                }
                break;
            default:
                break;
        }
        return super.onTouchEvent(ev);
    }
    /**
     * 更新底部footview的狀態(tài)
     *
     * @param delta
     */
    private void updateFooterState(float delta) {
        if (null == mFooterView) {
            return;
        }
        //設(shè)置footview的高度移動的時候,這個高度是增加每次移動的點相當(dāng)于上一個點的位置的距離
        mFooterView.setFooterHeight((int) (delta + mFooterView.getFooterHeight()));
        //當(dāng)前的狀態(tài)不是在刷新的狀態(tài)弓千!
        if (mFooterView.getCurrentState() != LoadState.LOADING) {
            if (mFooterView.getFooterHeight() > iFooterHeight) {
                //設(shè)置當(dāng)前的顯示的內(nèi)容為松開加載更多
                mFooterView.setFooterState(LoadState.WILL_RELEASE);
            } else {
                mFooterView.setFooterState(LoadState.NORMAL);
            }
        }
    }
    /**
     * 初始化底部footview
     */
    private void initFooterView(Context context) {
        mFooterView = new FooterView(context);
        mFooterView.setFooterHeight(200);
        //隱藏footview
        mFooterView.setPadding(0,0,0,-200);
        addFooterView(mFooterView);
        mFooterView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //獲取測量的footview的高度
                iFooterHeight = mFooterView.getMeasuredHeight();
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }
    /**
     * 重置footview
     */
    private void resetFooter() {
        //重置刷新狀態(tài)
        mFooterView.setFooterState(LoadState.NORMAL);
        if (null == mFooterView) {
            return;
        }
        int height = mFooterView.getMeasuredHeight();
        if (height == 0) {
            return;
        }
        int finalHeight = 0;
        if (height > iFooterHeight && mFooterView.getCurrentState() != LoadState.NORMAL) {
            finalHeight = iFooterHeight;
        } else if (mFooterView.getCurrentState() == LoadState.LOADING) {
            return;
        }
        iScrollWhich = SCROLL_FOOTER;
        mScroller.startScroll(0, height, 0, finalHeight - height, 300);
        invalidate();
    }
    /**
     * 重置heardview的狀態(tài)
     */
    private void resetHeaderHeight() {
        //重置刷新的狀態(tài)
        mHeaderView.setHeaderState(LoadState.NORMAL);
        //獲取測量得到的heardview的高度
        int height = mHeaderView.getMeasuredHeight();
        //如果獲取當(dāng)前的View的高度等于0代表是沒有移動就不做處理
        if (height == 0) // not visible.
            return;
        int finalHeight = 0;
        //如果超過HeaderView高度,則回滾到HeaderView高度即可
        if (height > iHeaderHeight && mHeaderView.getCurrentState() != LoadState.NORMAL) {
            finalHeight = iHeaderHeight;
        }
        //標(biāo)記當(dāng)前是heardview在移動
        iScrollWhich = SCROLL_HEADER;
        //inalHeight - height献起, finalHeight代表heardview抬起的時候高度-heardview初始化的高度=heardview在y軸上移動的距離洋访,280毫秒內(nèi)移動完畢
        //int startX,開始的位置
        // int mLastY,y位置開始的位置
        // int dx, x滑動的距離
        // int dy, y滑動的距離
        // int duration執(zhí)行完畢需要的時間
        mScroller.startScroll(0, height, 0, finalHeight - height, 300);
        //手動調(diào)用刷新移動
        invalidate();
    }
    /**
     * 設(shè)置頭部的view的高度,來達(dá)到下移的效果
     */
    private void upDataHeardView(float dy) {
        //如果當(dāng)前的狀態(tài)不是正在加載中谴餐,就改變狀態(tài)
        if (mHeaderView.getCurrentState() != LoadState.LOADING) {
            //如果當(dāng)前的heardview的高度大于原始的高度就代表用戶下拉刷新了要該表狀態(tài)姻政,變成下拉刷新的狀態(tài)
            if (mHeaderView.getHeaderHeight() > iHeaderHeight) {
                mHeaderView.setHeaderState(LoadState.WILL_RELEASE);
            } else {
                mHeaderView.setHeaderState(LoadState.NORMAL);
            }
        }
        //移動距離等于move的距離加上heardview的高度
        mHeaderView.setHeaderHeight((int) (dy + mHeaderView.getHeaderHeight()));
    }

    /**
     * 設(shè)置刷新的監(jiān)聽
     */
    public void setXrefershListviewListener(XrefershListviewListener l) {
        mListViewListener = l;
    }
    //每次移動都會調(diào)用computeScroll
    @Override
    public void computeScroll() {
        //判斷是否滑動結(jié)束
        if (mScroller.computeScrollOffset()) {
            //代表是下拉刷新
            if (iScrollWhich == SCROLL_HEADER) {
                //獲取到當(dāng)前滾動的位置,來動態(tài)的設(shè)置mHeaderView的高度
                mHeaderView.setHeaderHeight(mScroller.getCurrY());
                //代表是上拉加載改變footview
            } else if (iScrollWhich == SCROLL_FOOTER) {
                //不斷去改變footview的高度
                mFooterView.setFooterHeight(mScroller.getCurrY());
            }
            invalidate();
        }
    }
    //監(jiān)聽listview的滑動監(jiān)聽
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }
    //監(jiān)聽listview的滑動監(jiān)聽
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    }
}

上面的注釋也非常的清楚岂嗓,大體思路:

  • 首先我們直接初始化HeaderView和FooterView然后設(shè)置她們的默認(rèn)高度為200dp
  • addHeaderView然后我們添加頭部的view
  • 設(shè)置addOnGlobalLayoutListener的監(jiān)聽mHeaderView.getMeasuredHeight();在回調(diào)的方法中獲取測量的heardview的高度
  • mHeaderView.setPadding(0,-iHeaderHeight,0,0);這步我們就隱藏了heardview,設(shè)置他距離上面的距離為-iHeaderHeight
  • 然后我們重寫onTouchEvent來實現(xiàn)具體的移動的邏輯汁展,首先我們在ACTION_DOWN里面獲取當(dāng)前的坐標(biāo),然后在ACTION_MOVE中我們?nèi)ビ嬎慊瑒拥木嚯x厌殉,詳情看代碼的注釋
  • 通過 upDataHeardView(dy*0.7f);這個方法我們實現(xiàn)頭部view下拉的效果
 /**
     * 設(shè)置頭部的view的高度食绿,來達(dá)到下移的效果
     */
    private void upDataHeardView(float dy) {
        //如果當(dāng)前的狀態(tài)不是正在加載中,就改變狀態(tài)
        if (mHeaderView.getCurrentState() != LoadState.LOADING) {
            //如果當(dāng)前的heardview的高度大于原始的高度就代表用戶下拉刷新了要該表狀態(tài)公罕,變成下拉刷新的狀態(tài)
            if (mHeaderView.getHeaderHeight() > iHeaderHeight) {
                mHeaderView.setHeaderState(LoadState.WILL_RELEASE);
            } else {
                mHeaderView.setHeaderState(LoadState.NORMAL);
            }
        }
        //移動距離等于move的距離加上heardview的高度
        mHeaderView.setHeaderHeight((int) (dy + mHeaderView.getHeaderHeight()));
    }

  • 然后我們在看ACTION_UP器紧,抬起的時候我們?nèi)ヅ袛喈?dāng)前的是否是下拉刷新,如果是就直接調(diào)用onRefresh是刷新界面的數(shù)據(jù)在resetHeaderHeight我們重置頭部view的狀態(tài)
 /**
     * 重置heardview的狀態(tài)
     */
    private void resetHeaderHeight() {
        //重置刷新的狀態(tài)
        mHeaderView.setHeaderState(LoadState.NORMAL);
        //獲取測量得到的heardview的高度
        int height = mHeaderView.getMeasuredHeight();
        //如果獲取當(dāng)前的View的高度等于0代表是沒有移動就不做處理
        if (height == 0) // not visible.
            return;
        int finalHeight = 0;
        //如果超過HeaderView高度楼眷,則回滾到HeaderView高度即可
        if (height > iHeaderHeight && mHeaderView.getCurrentState() != LoadState.NORMAL) {
            finalHeight = iHeaderHeight;
        }
        //標(biāo)記當(dāng)前是heardview在移動
        iScrollWhich = SCROLL_HEADER;
        //inalHeight - height铲汪, finalHeight代表heardview抬起的時候高度-heardview初始化的高度=heardview在y軸上移動的距離熊尉,280毫秒內(nèi)移動完畢
        //int startX,開始的位置
        // int mLastY,y位置開始的位置
        // int dx, x滑動的距離
        // int dy, y滑動的距離
        // int duration執(zhí)行完畢需要的時間
        mScroller.startScroll(0, height, 0, finalHeight - height, 300);
        //手動調(diào)用刷新移動
        invalidate();
    }

  • 我們需要重寫computeScroll這個方法來實現(xiàn)阻尼的效果
     @Override
    public void computeScroll() {
        //判斷是否滑動結(jié)束
        if (mScroller.computeScrollOffset()) {
            //代表是下拉刷新
            if (iScrollWhich == SCROLL_HEADER) {
                //獲取到當(dāng)前滾動的位置,來動態(tài)的設(shè)置mHeaderView的高度
                mHeaderView.setHeaderHeight(mScroller.getCurrY());
                //代表是上拉加載改變footview
            } else if (iScrollWhich == SCROLL_FOOTER) {
                //不斷去改變footview的高度
                mFooterView.setFooterHeight(mScroller.getCurrY());
            }
            invalidate();
        }
    }

底部的刷新邏輯和頭部的都一樣掌腰,這樣我們就實現(xiàn)了上拉刷新下拉加載的效果了狰住!
代碼地址點擊這

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市齿梁,隨后出現(xiàn)的幾起案子催植,更是在濱河造成了極大的恐慌,老刑警劉巖士飒,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件查邢,死亡現(xiàn)場離奇詭異,居然都是意外死亡酵幕,警方通過查閱死者的電腦和手機扰藕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芳撒,“玉大人邓深,你說我怎么就攤上這事”噬玻” “怎么了芥备?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舌菜。 經(jīng)常有香客問我萌壳,道長,這世上最難降的妖魔是什么日月? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任袱瓮,我火速辦了婚禮,結(jié)果婚禮上爱咬,老公的妹妹穿的比我還像新娘尺借。我一直安慰自己,他們只是感情好精拟,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布燎斩。 她就那樣靜靜地躺著,像睡著了一般蜂绎。 火紅的嫁衣襯著肌膚如雪栅表。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天师枣,我揣著相機與錄音谨读,去河邊找鬼。 笑死坛吁,一個胖子當(dāng)著我的面吹牛劳殖,可吹牛的內(nèi)容都是我干的铐尚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼哆姻,長吁一口氣:“原來是場噩夢啊……” “哼宣增!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起矛缨,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤爹脾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后箕昭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灵妨,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年落竹,在試婚紗的時候發(fā)現(xiàn)自己被綠了泌霍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡述召,死狀恐怖朱转,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情积暖,我是刑警寧澤藤为,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站夺刑,受9級特大地震影響缅疟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜遍愿,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一存淫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧错览,春花似錦、人聲如沸煌往。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刽脖。三九已至羞海,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曲管,已是汗流浹背却邓。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留院水,地道東北人腊徙。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓简十,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撬腾。 傳聞我的和親對象是個殘疾皇子螟蝙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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