【Android】造輪子:輪播圖

前言

目前市場(chǎng)上的APP中箩兽,輪播圖可以說(shuō)是很常見的薇溃。一個(gè)好的輪播圖,基本上適用于所有的APP放前。是時(shí)候打造一個(gè)自己的輪播圖了忿磅,不要等到用的時(shí)候才去Google。

本文參考自Android實(shí)現(xiàn)Banner界面廣告圖片循環(huán)輪播(包括實(shí)現(xiàn)手動(dòng)滑動(dòng)循環(huán))凭语,根據(jù)該代碼改編

功能

輪播圖需要實(shí)現(xiàn)一下功能

  • 圖片循環(huán)輪播
  • 可添加文字
  • 最后一張到第一張的切換也要有切換效果
  • 循環(huán)葱她、自動(dòng)播放可控制

還有我們都比較關(guān)注的一點(diǎn):這輪子必須易拆、易裝似扔,可擴(kuò)展性強(qiáng)吨些。每次換個(gè)項(xiàng)目就要拷貝好幾個(gè)文件,改一大堆代碼炒辉,這是很煩的豪墅。

實(shí)現(xiàn)

再多的文字也不如一張圖來(lái)得直觀,先來(lái)個(gè)福利黔寇,回頭再說(shuō)怎實(shí)現(xiàn)的偶器。

效果

思路

這里使用ViewPager來(lái)實(shí)現(xiàn)輪播的效果,但是ViewPager是滑動(dòng)到最后一張時(shí),是不能跳轉(zhuǎn)到第一張的屏轰。于是颊郎,我們可以這樣:

  • 需要顯示的輪播圖有N張
  • ViewPager中添加N個(gè)View,這時(shí)ViewPager中有:
    View(1)霎苗、View(2)姆吭、View(3) ... View(N)
  • 再往ViewPager中添加View(1),這時(shí)ViewPager中有:
    View(1)唁盏、View(2)内狸、View(3) ... View(N)、View(1)

這樣就可以實(shí)現(xiàn)一種視覺(jué)效果:滑動(dòng)到最后一張 View(N)的時(shí)候厘擂,再往后滑動(dòng)就回到了第一張View(1)昆淡。
這也適用于從第一張條轉(zhuǎn)到最后一張的實(shí)現(xiàn)。
文字看著費(fèi)解驴党?那就看圖吧(還好會(huì)那么一點(diǎn)點(diǎn)PS)
例:
需要顯示三張圖:

需要輪播的圖片

經(jīng)過(guò)處理瘪撇,變成這樣

處理后的輪播圖

在界面上看到的是三張圖片,而實(shí)際在ViewPager中的是這樣的5張港庄。

  • 當(dāng)從View4跳轉(zhuǎn)到View5時(shí)倔既,在代碼中立刻將視圖切換到View2,應(yīng)為圖片是一樣的鹏氧,所有在界面上看不到任何效果渤涌。
  • 同理,當(dāng)從View2跳轉(zhuǎn)到View1時(shí)把还,在代碼中將視圖切換到View4实蓬。

自動(dòng)輪播流程:
View2 -->View3 --> View4 --> View5 -->View2(完成一次循環(huán))-->View3 -->View4....
當(dāng)顯示View5的時(shí)候,立刻切換到View2View5View2顯示的內(nèi)容是相同的)吊履,這樣就實(shí)現(xiàn)了圖片輪播安皱。
這里View5 ->View2的切換巧妙利用了ViewPager中的方法:

setCurrentItem(int item, boolean smoothScroll)

參數(shù)smoothScroll為false的時(shí)候,實(shí)現(xiàn)了“看不見”的跳轉(zhuǎn)艇炎。

還是不大清楚酌伊?那就直接看代碼吧

代碼

思路說(shuō)完,上代碼

  • 創(chuàng)建model
    這里創(chuàng)建一個(gè)Info類缀踪,模擬實(shí)際應(yīng)用中的數(shù)據(jù)居砖。里面有titleurl字段。
public class Info {
    private String url;
    private String title;

    public Info(String title, String url) {
        this.url = url;
        this.title = title;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
  • 布局
    為了實(shí)現(xiàn)畫面重疊的效果驴娃,這里用了相對(duì)布局奏候,輪播圖使用ViewPager來(lái)實(shí)現(xiàn)。后面有兩個(gè)LinearLayout唇敞,第一個(gè)LinearLayout用來(lái)放指示器蔗草,在java代碼中動(dòng)態(tài)添加咒彤;第二個(gè)LinearLayout就用來(lái)顯示Title了,當(dāng)然蕉世,如果還需要顯示的其他內(nèi)容蔼紧,可以在這個(gè)布局里面中添加。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical">
    <android.support.v4.view.ViewPager
        android:id="@+id/cycle_view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <LinearLayout
        android:id="@+id/cycle_indicator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        android:gravity="center"
        android:orientation="horizontal" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/cycle_indicator"
        android:orientation="vertical">
        <TextView
            android:id="@+id/cycle_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:gravity="center"
            android:textColor="@android:color/white"
            android:textSize="20sp" />
    </LinearLayout>
</RelativeLayout>
  • CycleViewPager
    重點(diǎn)來(lái)了狠轻,自定義的輪播圖。來(lái)個(gè)重磅炸彈彬犯,別看暈了
public class CycleViewPager extends FrameLayout implements ViewPager.OnPageChangeListener {

    private static final String TAG = "CycleViewPager";

    private Context mContext;

    private ViewPager mViewPager;//實(shí)現(xiàn)輪播圖的ViewPager

    private TextView mTitle;//標(biāo)題

    private LinearLayout mIndicatorLayout; // 指示器

    private Handler handler;//每幾秒后執(zhí)行下一張的切換

    private int WHEEL = 100; // 轉(zhuǎn)動(dòng)

    private int WHEEL_WAIT = 101; // 等待

    private List<View> mViews = new ArrayList<>(); //需要輪播的View向楼,數(shù)量為輪播圖數(shù)量+2

    private ImageView[] mIndicators;    //指示器小圓點(diǎn)

    private boolean isScrolling = false; // 滾動(dòng)框是否滾動(dòng)著

    private boolean isCycle = true; // 是否循環(huán),默認(rèn)為true

    private boolean isWheel = true; // 是否輪播谐区,默認(rèn)為true

    private int delay = 4000; // 默認(rèn)輪播時(shí)間

    private int mCurrentPosition = 0; // 輪播當(dāng)前位置

    private long releaseTime = 0; // 手指松開湖蜕、頁(yè)面不滾動(dòng)時(shí)間,防止手機(jī)松開后短時(shí)間進(jìn)行切換

    private ViewPagerAdapter mAdapter;

    private ImageCycleViewListener mImageCycleViewListener;

    private List<Info> infos;//數(shù)據(jù)集合

    private int mIndicatorSelected;//指示器圖片宋列,被選擇狀態(tài)

    private int mIndicatorUnselected;//指示器圖片昭抒,未被選擇狀態(tài)

    final Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (mContext != null && isWheel) {
                long now = System.currentTimeMillis();
                // 檢測(cè)上一次滑動(dòng)時(shí)間與本次之間是否有觸擊(手滑動(dòng))操作,有的話等待下次輪播
                if (now - releaseTime > delay - 500) {
                    handler.sendEmptyMessage(WHEEL);
                } else {
                    handler.sendEmptyMessage(WHEEL_WAIT);
                }
            }
        }
    };

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

    public CycleViewPager(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CycleViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        initView();
    }

    /**
     * 初始化View
     */
    private void initView() {
      LayoutInflater.from(mContext).inflate(R.layout.layout_cycle_view, this, true);
        mViewPager = (ViewPager) findViewById(R.id.cycle_view_pager);
        mTitle = (TextView) findViewById(R.id.cycle_title);
        mIndicatorLayout = (LinearLayout) findViewById(R.id.cycle_indicator);
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == WHEEL && mViews.size() > 0) {
                    if (!isScrolling) {
                        //當(dāng)前為非滾動(dòng)狀態(tài)炼杖,切換到下一頁(yè)
                        int posttion = (mCurrentPosition + 1) % mViews.size();
                        mViewPager.setCurrentItem(posttion, true);
                    }
                    releaseTime = System.currentTimeMillis();
                    handler.removeCallbacks(runnable);
                    handler.postDelayed(runnable, delay);
                    return;
                }
                if (msg.what == WHEEL_WAIT && mViews.size() > 0) {
                    handler.removeCallbacks(runnable);
                    handler.postDelayed(runnable, delay);
                }
            }
        };
    }

    /**
     * 設(shè)置指示器圖片灭返,在setData之前調(diào)用
     *
     * @param select   選中時(shí)的圖片
     * @param unselect 未選中時(shí)的圖片
     */
    public void setIndicators(int select, int unselect) {
        mIndicatorSelected = select;
        mIndicatorUnselected = unselect;
    }
    public void setData(List<Info> list, ImageCycleViewListener listener) {
        setData(list, listener, 0);
    }

    /**
     * 初始化viewpager
     *
     * @param list         要顯示的數(shù)據(jù)
     * @param showPosition 默認(rèn)顯示位置
     */
    public void setData(List<Info> list, ImageCycleViewListener listener, 
        int showPosition) {
        if (list == null || list.size() == 0) {
            //沒(méi)有數(shù)據(jù)時(shí)隱藏整個(gè)布局
            this.setVisibility(View.GONE);
            return;
        }
        mViews.clear();
        infos = list;
        if (isCycle) {
            //添加輪播圖View,數(shù)量為集合數(shù)+2
            // 將最后一個(gè)View添加進(jìn)來(lái)
            mViews.add(getImageView(mContext, infos.get(infos.size() - 1).getUrl()));
            for (int i = 0; i < infos.size(); i++) {
                mViews.add(getImageView(mContext, infos.get(i).getUrl()));
            }
            // 將第一個(gè)View添加進(jìn)來(lái)
            mViews.add(getImageView(mContext, infos.get(0).getUrl()));
        } else {
            //只添加對(duì)應(yīng)數(shù)量的View
            for (int i = 0; i < infos.size(); i++) {
                mViews.add(getImageView(mContext, infos.get(i).getUrl()));
            }
        }
        if (mViews == null || mViews.size() == 0) {
            //沒(méi)有View時(shí)隱藏整個(gè)布局
            this.setVisibility(View.GONE);
            return;
        }
        mImageCycleViewListener = listener;
        int ivSize = mViews.size();
        // 設(shè)置指示器
        mIndicators = new ImageView[ivSize];
        if (isCycle)
            mIndicators = new ImageView[ivSize - 2];
        mIndicatorLayout.removeAllViews();
        for (int i = 0; i < mIndicators.length; i++) {
            mIndicators[i] = new ImageView(mContext);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT, 
                    LinearLayout.LayoutParams.WRAP_CONTENT);
            lp.setMargins(10, 0, 10, 0);
            mIndicators[i].setLayoutParams(lp);
            mIndicatorLayout.addView(mIndicators[i]);
        }
        mAdapter = new ViewPagerAdapter();
        // 默認(rèn)指向第一項(xiàng)坤邪,下方viewPager.setCurrentItem將觸發(fā)重新計(jì)算指示器指向
        setIndicator(0);
        mViewPager.setOffscreenPageLimit(3);
        mViewPager.setOnPageChangeListener(this);
        mViewPager.setAdapter(mAdapter);
        if (showPosition < 0 || showPosition >= mViews.size())
            showPosition = 0;
        if (isCycle) {
            showPosition = showPosition + 1;
        }
        mViewPager.setCurrentItem(showPosition);
        setWheel(true);//設(shè)置輪播
    }

    /**
     * 獲取輪播圖View
     *
     * @param context
     * @param url
     */
    private View getImageView(Context context, String url) {
        return MainActivity.getImageView(context, url);
    }

    /**
     * 設(shè)置指示器
     *
     * @param selectedPosition 默認(rèn)指示器位置
     */
    private void setIndicator(int selectedPosition) {
        setText(mTitle, infos.get(selectedPosition).getTitle());
        try {
            for (int i = 0; i < mIndicators.length; i++) {
                mIndicators[i]
                        .setBackgroundResource(mIndicatorUnselected);
            }
            if (mIndicators.length > selectedPosition)
                mIndicators[selectedPosition]
                        .setBackgroundResource(mIndicatorSelected);
        } catch (Exception e) {
            Log.i(TAG, "指示器路徑不正確");
        }
    }

    /**
     * 頁(yè)面適配器 返回對(duì)應(yīng)的view
     *
     * @author Yuedong Li
     */
    private class ViewPagerAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return mViews.size();
        }
        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
        @Override
        public View instantiateItem(ViewGroup container, final int position) {
            View v = mViews.get(position);
            if (mImageCycleViewListener != null) {
                v.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                     mImageCycleViewListener.onImageClick(
                        infos.get(mCurrentPosition - 1), mCurrentPosition, v);
                    }
                });
            }
            container.addView(v);
            return v;
        }
        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }
    @Override
    public void onPageScrolled(
          int position, float positionOffset, int positionOffsetPixels) {
    }
    @Override
    public void onPageSelected(int arg0) {
        int max = mViews.size() - 1;
        int position = arg0;
        mCurrentPosition = arg0;
        if (isCycle) {
            if (arg0 == 0) {
                //滾動(dòng)到mView的1個(gè)(界面上的最后一個(gè))熙含,將mCurrentPosition設(shè)置為max - 1
                mCurrentPosition = max - 1;
            } else if (arg0 == max) {
                //滾動(dòng)到mView的最后一個(gè)(界面上的第一個(gè)),將mCurrentPosition設(shè)置為1
                mCurrentPosition = 1;
            }
            position = mCurrentPosition - 1;
        }
        setIndicator(position);
    }
    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == 1) { // viewPager在滾動(dòng)
            isScrolling = true;
            return;
        } else if (state == 0) { // viewPager滾動(dòng)結(jié)束

            releaseTime = System.currentTimeMillis();
            //跳轉(zhuǎn)到第mCurrentPosition個(gè)頁(yè)面(沒(méi)有動(dòng)畫效果艇纺,實(shí)際效果頁(yè)面上沒(méi)變化)
            mViewPager.setCurrentItem(mCurrentPosition, false);
        }
        isScrolling = false;
    }

    /**
     * 為textview設(shè)置文字
     * @param textView
     * @param text
     */
    public static void setText(TextView textView, String text) {
        if (text != null && textView != null) textView.setText(text);
    }

    /**
     * 為textview設(shè)置文字
     *
     * @param textView
     * @param text
     */
    public static void setText(TextView textView, int text) {
        if (textView != null) setText(textView, text + "");
    }

    /**
     * 是否循環(huán)怎静,默認(rèn)開啟。必須在setData前調(diào)用
     *
     * @param isCycle 是否循環(huán)
     */
    public void setCycle(boolean isCycle) {
        this.isCycle = isCycle;
    }

    /**
     * 是否處于循環(huán)狀態(tài)
     *
     * @return
     */
    public boolean isCycle() {
        return isCycle;
    }

    /**
     * 設(shè)置是否輪播黔衡,默認(rèn)輪播,輪播一定是循環(huán)的
     *
     * @param isWheel
     */
    public void setWheel(boolean isWheel) {
        this.isWheel = isWheel;
        isCycle = true;
        if (isWheel) {
            handler.postDelayed(runnable, delay);
        }
    }

    /**
     * 刷新數(shù)據(jù)蚓聘,當(dāng)外部視圖更新后,通知刷新數(shù)據(jù)
     */
    public void refreshData() {
        if (mAdapter != null)
            mAdapter.notifyDataSetChanged();
    }

    /**
     * 是否處于輪播狀態(tài)
     *
     * @return
     */
    public boolean isWheel() {
        return isWheel;
    }

    /**
     * 設(shè)置輪播暫停時(shí)間,單位毫秒(默認(rèn)4000毫秒)
     * @param delay
     */
    public void setDelay(int delay) {
        this.delay = delay;
    }

    /**
     * 輪播控件的監(jiān)聽事件
     *
     * @author minking
     */
    public static interface ImageCycleViewListener {

        /**
         * 單擊圖片事件
         *
         * @param info
         * @param position
         * @param imageView
         */
        public void onImageClick(Info info, int position, View imageView);
    }
}

從里面挑了幾個(gè)變量和方法說(shuō)明一下:
變量
handler盟劫、runnable:實(shí)現(xiàn)定時(shí)輪播
mCurrentPosition:表示當(dāng)前位置
方法
setIndicators():設(shè)置指示器的圖片(必須在setData前調(diào)用)
setData():根據(jù)數(shù)據(jù)夜牡,生成對(duì)應(yīng)的輪播圖
setIndicator():設(shè)置指示器和文字內(nèi)容
onPageSelected()onPageScrollStateChanged():利用ViewPager的滾動(dòng)監(jiān)聽捞高,實(shí)現(xiàn)了上面的思路氯材。onPageSelected()中根據(jù)ViewPager中顯示的位置,改變mCurrentPosition的值硝岗,然后在onPageScrollStateChanged()中根據(jù)mCurrentPosition重新設(shè)置頁(yè)面(這里的setCurrentItem沒(méi)有動(dòng)畫效果)氢哮。
getImageView():根據(jù)URL生成Viewpager中對(duì)應(yīng)的各個(gè)View根據(jù)實(shí)際的圖片加載框架來(lái)生成,這里使用了Picasso實(shí)現(xiàn)了網(wǎng)絡(luò)圖片的加載)型檀,看看getImageView()中調(diào)用的代碼

    /**
     * 得到輪播圖的View
     * @param context
     * @param url
     * @return
     */
    public static View getImageView(Context context, String url) {
        RelativeLayout rl = new RelativeLayout(context);
        //添加一個(gè)ImageView冗尤,并加載圖片
        ImageView imageView = new ImageView(context);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.MATCH_PARENT);
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setLayoutParams(layoutParams);
        //使用Picasso來(lái)加載圖片
        Picasso.with(context).load(url).into(imageView);
        //在Imageview前添加一個(gè)半透明的黑色背景,防止文字和圖片混在一起
        ImageView backGround = new ImageView(context);
        backGround.setLayoutParams(layoutParams);
        backGround.setBackgroundResource(R.color.cycle_image_bg);
        rl.addView(imageView);
        rl.addView(backGround);
        return rl;
    }
<color name="cycle_image_bg">#44222222</color>

代碼很簡(jiǎn)單,創(chuàng)建了一個(gè)顯示圖片的布局裂七,先在布局中添加了需要顯示的圖片皆看,然后加了個(gè)半透明的圖,防止顯示時(shí)文字和圖片中白色的部分重疊在一起背零,導(dǎo)致看不清文字腰吟。

  • 在Acitivty中使用
    輪子打造好了,不拿出來(lái)溜一溜徙瓶?
public class MainActivity extends AppCompatActivity {

    /**
     * 模擬請(qǐng)求后得到的數(shù)據(jù)
     */
    List<Info> mList = new ArrayList<>();

    /**
     * 輪播圖
     */
    CycleViewPager mCycleViewPager;

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

    /**
     * 初始化數(shù)據(jù)
     */
    private void initData() {
        mList.add(new Info("標(biāo)題1", 
              "http://img2.3lian.com/2014/c7/25/d/40.jpg"));
        mList.add(new Info("標(biāo)題2", 
              "http://img2.3lian.com/2014/c7/25/d/41.jpg"));
        mList.add(new Info("標(biāo)題3", 
             "http://imgsrc.baidu.com/forum/pic/item/b64543a98226cffc8872e00cb9014a90f603ea30.jpg"));
        mList.add(new Info("標(biāo)題4", 
             "http://imgsrc.baidu.com/forum/pic/item/261bee0a19d8bc3e6db92913828ba61eaad345d4.jpg"));
    }

    /**
     * 初始化View
     */
    private void initView() {
        mCycleViewPager = (CycleViewPager) findViewById(R.id.cycle_view);
        //設(shè)置選中和未選中時(shí)的圖片
        mCycleViewPager.setIndicators(R.mipmap.ad_select, R.mipmap.ad_unselect);
        //設(shè)置輪播間隔時(shí)間
        mCycleViewPager.setDelay(2000);
        mCycleViewPager.setData(mList, mAdCycleViewListener);
    }

    /**
     * 輪播圖點(diǎn)擊監(jiān)聽
     */
    private CycleViewPager.ImageCycleViewListener mAdCycleViewListener = 
                  new CycleViewPager.ImageCycleViewListener() {

        @Override
        public void onImageClick(Info info, int position, View imageView) {

            if (mCycleViewPager.isCycle()) {
                position = position - 1;
            }
            Toast.makeText(MainActivity.this, info.getTitle() +
                 "選擇了--" + position, Toast.LENGTH_LONG).show();
        }
    };
}

使用起來(lái)也是很簡(jiǎn)單的毛雇,只要設(shè)置下圖片、數(shù)據(jù)侦镇、點(diǎn)擊監(jiān)聽就可以了灵疮。(之前貼過(guò)MainActivity.getImageView()方法了,這里就不貼了)
放到自己的項(xiàng)目中壳繁?
只需要調(diào)下布局震捣,根據(jù)自己的圖片加載框架改下getImageView(或者也可以直接用我的),然后把CycleViewPager中的Info改成自己的Model就可以了闹炉。

源碼地址:Github

以上有錯(cuò)誤之處蒿赢,感謝指出

投稿給鴻洋大神后,大神幫我測(cè)了下剩胁,發(fā)現(xiàn)這輪播圖在MOTO nexus 6上诉植,快速滑動(dòng)會(huì)卡住,然后跳躍昵观,類似應(yīng)該在小米5上也會(huì)復(fù)現(xiàn)晾腔。
大神的建議:無(wú)限循環(huán)banner,不如使用MAX頁(yè)啊犬,然后currentItem=MAX/2來(lái)做灼擂。

(這段時(shí)間忙著找工作,就先擱下了觉至,有興趣的同學(xué)可以先嘗試下剔应。)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市语御,隨后出現(xiàn)的幾起案子峻贮,更是在濱河造成了極大的恐慌,老刑警劉巖应闯,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纤控,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡碉纺,警方通過(guò)查閱死者的電腦和手機(jī)船万,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門刻撒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人耿导,你說(shuō)我怎么就攤上這事声怔。” “怎么了舱呻?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵醋火,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我箱吕,道長(zhǎng)胎撇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任殖氏,我火速辦了婚禮,結(jié)果婚禮上姻采,老公的妹妹穿的比我還像新娘雅采。我一直安慰自己,他們只是感情好慨亲,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布婚瓜。 她就那樣靜靜地躺著,像睡著了一般刑棵。 火紅的嫁衣襯著肌膚如雪巴刻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天蛉签,我揣著相機(jī)與錄音胡陪,去河邊找鬼。 笑死碍舍,一個(gè)胖子當(dāng)著我的面吹牛柠座,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播片橡,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼妈经,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了捧书?” 一聲冷哼從身側(cè)響起吹泡,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎经瓷,沒(méi)想到半個(gè)月后爆哑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡了嚎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年泪漂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了廊营。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萝勤,死狀恐怖露筒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情敌卓,我是刑警寧澤慎式,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站趟径,受9級(jí)特大地震影響瘪吏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜗巧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一掌眠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幕屹,春花似錦蓝丙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至说敏,卻和暖如春鸥跟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盔沫。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工医咨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迅诬。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓腋逆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親侈贷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惩歉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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