一起擼個(gè)朋友圈吧 - 圖片瀏覽(下)【ViewPager優(yōu)化】

項(xiàng)目地址:https://github.com/razerdp/FriendCircle (能弱弱的求個(gè)star或者fork么QAQ)
《一起擼個(gè)朋友圈吧》 這是本文所處文集,所有更新都會(huì)在這個(gè)文集里面哦挂谍,歡迎關(guān)注


上篇鏈接:http://www.reibang.com/p/4c5b5d7dc856
下篇鏈接:http://www.reibang.com/p/42119b89c26f


【ps:評(píng)論功能羽翼君我補(bǔ)全了后臺(tái)交互了喲漩绵,如果您想體驗(yàn)一下不同的用戶而不是一直都是羽翼君匆赃,可以在FriendCircleApp下熟嫩,在onCreate中,將LocalHostInfo.INSTANCE.setHostId(1001);的id改為1001~1115之間任意一個(gè)】

在上一篇夏哭,我們實(shí)現(xiàn)了朋友圈的圖片瀏覽满哪,在文章的最后,留下了幾個(gè)問(wèn)題汛兜,那么這一片我們解決這些巴粪。

本篇需要解決的幾個(gè)問(wèn)題(本篇主要為控件的自定義,但相信我粥谬,不會(huì)很難):

- viewpager如何復(fù)用
- 圖片瀏覽viewpager的指示器

本篇圖片預(yù)覽如下:

preview

Q1:指示器

我們知道肛根,在微信圖片瀏覽的時(shí)候,多張圖下方是有個(gè)指示器的漏策,比如這樣

當(dāng)然派哲,我們可以找?guī)欤@個(gè)如此簡(jiǎn)單的控件為此花時(shí)間去找?guī)煊寸瑁共蝗缥覀冏约簛?lái)定制一番對(duì)吧狮辽。

我們來(lái)分析一下,可以如何實(shí)現(xiàn)這個(gè)指示器功能巢寡。

首先可以確認(rèn)的是喉脖,指示器要跟ViewPager聯(lián)調(diào),就必須要跟ViewPager的滑動(dòng)狀態(tài)進(jìn)行關(guān)聯(lián)抑月。

而對(duì)于ViewPager的滑動(dòng)狀態(tài)树叽,使用的最多的就是ViewPager.OnPageChangeListener這個(gè)接口。

從圖中我們可以看到谦絮,微信下方的指示器滑動(dòng)的時(shí)候题诵,白點(diǎn)并沒(méi)有什么移動(dòng)動(dòng)畫,而是直接就跳到另一個(gè)點(diǎn)上面了层皱,這樣一來(lái)性锭,這個(gè)控件的實(shí)現(xiàn)就更加的容易了。

因此我們可以初步得到思路如下:

  • 首先可以肯定的是叫胖,指示器不應(yīng)該隸屬于ViewPager草冈,否則每次instantiateItem的時(shí)候又inflate出來(lái)是很不合理的,所以我們的indicator必須跟ViewPager同級(jí)瓮增,但可以通過(guò)ViewPager的滑動(dòng)狀態(tài)來(lái)改變怎棱。

  • 第二,小點(diǎn)點(diǎn)的數(shù)量永遠(yuǎn)都是0~9绷跑,因?yàn)槲⑿诺膱D片數(shù)量最多9張拳恋。

  • 第三,小點(diǎn)點(diǎn)都是水平居中砸捏,因此我們的indicator可以繼承LinearLayout來(lái)實(shí)現(xiàn)谬运。

  • 第四隙赁,小點(diǎn)點(diǎn)有兩個(gè)狀態(tài),一個(gè)選中梆暖,一個(gè)非選中鸳谜。所以小點(diǎn)點(diǎn)的定制必須要提供改變選中狀態(tài)的接口。


Q1 - 代碼的編寫:

小點(diǎn)點(diǎn)的自定義

既然思路有了式廷,那么剩下來(lái)的也僅僅是用代碼將我們的思路實(shí)現(xiàn)而已咐扭。

首先我們來(lái)弄小點(diǎn)點(diǎn)。

由于我懶得打開(kāi)AE滑废,所以我選擇直接采用Drawable的方式來(lái)寫蝗肪。

來(lái)到drawable文件下,新建一個(gè)drawable

首先來(lái)定制一個(gè)未選中狀態(tài)的drawable

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <size android:width="25dp" android:height="25dp"/>
    <stroke android:color="@color/white" android:width="1dp"/>
</shape>

代碼非常簡(jiǎn)單蠕趁,效果也僅僅是一個(gè)圓環(huán)薛闪。

未選中的drawable

而選中的實(shí)心圓只是把上述代碼的stroke換成solid而已,這里就略過(guò)了俺陋。

然后我們新建一個(gè)類繼承View豁延,叫做“DotView”

或許看到繼承View你就會(huì)覺(jué)得,難道又要重寫onMeasure,onLayout什么的腊状?煩死了诱咏。。缴挖。袋狞。

其實(shí)不用,畢竟咱們用的是drawable映屋。苟鸯。。

我們的代碼整體結(jié)構(gòu)如下:

public class DotView extends View {
    private static final String TAG = "DotView";

    //正常狀態(tài)下的dot
    Drawable mDotNormal;
    //選中狀態(tài)下的dot
    Drawable mDotSelected;

    private boolean isSelected;

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

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

    public DotView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mDotNormal = context.getResources().getDrawable(R.drawable.ic_viewpager_dot_indicator_normal);
        mDotSelected = context.getResources().getDrawable(R.drawable.ic_viewpager_dot_indicator_selected);
    }

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

    }

    public void setSelected(boolean selected) {
        this.isSelected = selected;
        invalidate();
    }

    public boolean getSelected() {
        return isSelected;
    }
}

可以看到棚点,我們只需要實(shí)現(xiàn)onDraw方法和提供是否選中的方法而已早处。其他的都不需要。

在onDraw里面瘫析,我們編寫以下代碼:

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

        int width=getWidth();
        int height=getHeight();



        if (isSelected) {
            mDotSelected.setBounds(0,0,width,height);
            mDotSelected.draw(canvas);
        }
        else {
            mDotNormal.setBounds(0,0,width,height);
            mDotNormal.draw(canvas);
        }
    }

這里僅僅為了確定drawable的大小并根據(jù)不同的狀態(tài)進(jìn)行不同的drawable繪制砌梆。非常簡(jiǎn)單。

indicator的自定義

在上面的思路里颁股,我們可以通過(guò)繼承LinearLayout來(lái)實(shí)現(xiàn)指示器么库。

因此我們新建一個(gè)類繼承LinearLayout傻丝,取名“DotIndicator”

在這個(gè)指示器中甘有,我們需要確定他擁有的功能:

  • 包含0~9個(gè)DotView
  • 通過(guò)公有方法來(lái)設(shè)置當(dāng)前選中的DotView
  • 通過(guò)公有方法來(lái)設(shè)置當(dāng)前顯示的DotView的數(shù)量

因此我們可以初步設(shè)計(jì)以下代碼結(jié)構(gòu):

package razerdp.friendcircle.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
import razerdp.friendcircle.utils.UIHelper;

/**
 * Created by 大燈泡 on 2016/4/21.
 * viewpager圖片瀏覽器底部的小點(diǎn)點(diǎn)指示器
 */
public class DotIndicator extends LinearLayout {
    private static final String TAG = "DotIndicator";

    List<DotView> mDotViews;

    private int currentSelection = 0;

    private int mDotsNum = 9;

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

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

    public DotIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        setOrientation(HORIZONTAL);
        setGravity(Gravity.CENTER);

        buildDotView(context);
    }

    /**
     * 初始化dotview
     * @param context
     */
    private void buildDotView(Context context) {

    }

    /**
     * 當(dāng)前選中的dotview
     * @param selection
     */
    public void setCurrentSelection(int selection) {
      
    }

    public int getCurrentSelection() {
        return currentSelection;
    }

    /**
     * 當(dāng)前需要展示的dotview數(shù)量
     * @param num
     */
    public void setDotViewNum(int num) {
        
    }

    public int getDotViewNum() {
        return mDotsNum;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mDotViews.clear();
        mDotViews=null;
        Log.d(TAG, "清除dotview引用");
    }
}

在這里說(shuō)明一下,由于我們操作不同位置的dotview葡缰,所以我們需要有一個(gè)列表來(lái)存下這些dotview亏掀。

另外忱反,我們?cè)O(shè)置指示器必須是水平的同時(shí)Gravity=CENTER

另外注意記得在onDetachedFromWindow清除所有引用哦。否則無(wú)法回收就內(nèi)存泄漏了滤愕。

接下來(lái)我們補(bǔ)全代碼温算。

首先是

buildDotView

在這里我們將會(huì)進(jìn)行indicator的初始化,也就是將9個(gè)dotView添加進(jìn)來(lái)

/**
     * 初始化dotview
     * @param context
     */
    private void buildDotView(Context context) {
        mDotViews = new ArrayList<>();
        for (int i = 0; i < 9; i++) {
            DotView dotView = new DotView(context);
            dotView.setSelected(false);
            LinearLayout.LayoutParams params = new LayoutParams(UIHelper.dipToPx(context, 10f),
                    UIHelper.dipToPx(context, 10f));
            if (i == 0) {
                params.leftMargin = 0;
            }
            else {
                params.leftMargin = UIHelper.dipToPx(context, 6f);
            }
            addView(dotView,params);
            mDotViews.add(dotView);
        }
    }

這里有一個(gè)需要注意的是第0個(gè)dotview是不需要marginleft的间影。

接下來(lái)補(bǔ)全

setCurrentSelection

這個(gè)方法我們的思路也很簡(jiǎn)單注竿,首先將所有的DotView設(shè)置為未選中狀態(tài),然后再設(shè)置對(duì)應(yīng)num的DotView為選中狀態(tài)魂贬。雖然是遍歷了兩次數(shù)組巩割,但因?yàn)楹苌贃|西,而且CPU的處理速度完全可以在肉眼無(wú)法觀察的速度下完成付燥,所以這里無(wú)需過(guò)度考慮宣谈。

/**
     * 當(dāng)前選中的dotview
     * @param selection
     */
    public void setCurrentSelection(int selection) {
        this.currentSelection = selection;
        for (DotView dotView : mDotViews) {
            dotView.setSelected(false);
        }
        if (selection >= 0 && selection < mDotViews.size()) {
            mDotViews.get(selection).setSelected(true);
        }
        else {
            Log.e(TAG, "the selection can not over dotViews size");
        }
    }

值得注意的是,我們需要留意邊界問(wèn)題

最后我們補(bǔ)全setDotViewNum

這里的思路跟上面的差不多键科,首先我們將所有的dotview設(shè)置為可見(jiàn)闻丑,然后將指定數(shù)量之后的dotview設(shè)置為GONE,這時(shí)候由于LinearLayout的Gravity是CENTER勋颖,所以剩余的dotView會(huì)水平居中嗦嗡。

 /**
     * 當(dāng)前需要展示的dotview數(shù)量
     * @param num
     */
    public void setDotViewNum(int num) {
        if (num > 9 || num <= 0) {
            Log.e(TAG, "num必須在1~9之間哦");
            return;
        }

        for (DotView dotView : mDotViews) {
            dotView.setVisibility(VISIBLE);
        }
        this.mDotsNum = num;
        for (int i = num; i < mDotViews.size(); i++) {
            DotView dotView = mDotViews.get(i);
            if (dotView != null) {
                dotView.setSelected(false);
                dotView.setVisibility(GONE);
            }
        }
    }

同樣需要注意邊界問(wèn)題。

完成之后饭玲,我們回到圖片瀏覽的布局酸钦,將我們的自定義dotindicator添加到布局,并對(duì)其父布局底部咱枉。

xml

最后在我們封裝好的PhotoPagerManager引入DotIndicator

在調(diào)用showPhoto的時(shí)候卑硫,先設(shè)置dotindicator展示的dotview數(shù)量,然后再設(shè)置選中的dotview

showphoto

最后在viewpager的pagechangerlistener監(jiān)聽(tīng)中設(shè)置dotindicator的對(duì)應(yīng)方法就好了

設(shè)置當(dāng)前展示的dotview

【DotIndicator完】


Q2:viewpager復(fù)用

在上一篇文章蚕断,我們看到當(dāng)某個(gè)動(dòng)態(tài)的圖片數(shù)量超過(guò)3張欢伏,我們點(diǎn)擊第四張圖片的時(shí)候,會(huì)發(fā)現(xiàn)放大動(dòng)畫并不明顯亿乳。

這是因?yàn)閂iewPager的機(jī)制硝拧,ViewPager默認(rèn)會(huì)緩存當(dāng)前item左右共三個(gè)view,當(dāng)劃到第四個(gè)葛假,則會(huì)重新執(zhí)行initItem障陶,對(duì)應(yīng)我們的adapter,就是重新new了一個(gè)PhotoView聊训,由于這個(gè)PhotoView并沒(méi)有圖片抱究,所以放大動(dòng)畫無(wú)法展示。

而我們選擇解決方案就是带斑,在adapter初始化的時(shí)候鼓寺,就直接把9個(gè)photoview給new出來(lái)放到一個(gè)對(duì)象池里面勋拟,每次執(zhí)行到instantiateItem就從池里面拿出來(lái),這樣就可以防止每次都new妈候,保證放大動(dòng)畫敢靡。

因此我們的改動(dòng)如下:


/**
 * Created by 大燈泡 on 2016/4/12.
 * 圖片瀏覽窗口的adapter
 */
public class PhotoBoswerPagerAdapter extends PagerAdapter {
    private static final String TAG = "PhotoBoswerPagerAdapter";

    private static ArrayList<MPhotoView> sMPhotoViewPool;
    private static final int sMPhotoViewPoolSize = 10;
    ...跟上次一樣

    public PhotoBoswerPagerAdapter(Context context) {
    ...不變
        sMPhotoViewPool = new ArrayList<>();
        //buildProgressTV(context);
        buildMPhotoViewPool(context);
    }

    private void buildMPhotoViewPool(Context context) {
        for (int i = 0; i < sMPhotoViewPoolSize; i++) {
            MPhotoView sPhotoView = new MPhotoView(context);
            sPhotoView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            sMPhotoViewPool.add(sPhotoView);
        }
    }

    ...resetDatas()方法不變

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        MPhotoView mPhotoView = sMPhotoViewPool.get(position);
        if (mPhotoView == null) {
            mPhotoView = new MPhotoView(mContext);
            mPhotoView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
        }
        Glide.with(mContext).load(photoAddress.get(position)).into(mPhotoView);
        container.addView(mPhotoView);
        return mPhotoView;
    }
    ...setPrimaryItem()方法不變

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

        container.removeView((View) object);
    }

    ...其余方法不變
    //=============================================================destroy
    public void destroy(){
        for (MPhotoView photoView : sMPhotoViewPool) {
            photoView.destroy();
        }
        sMPhotoViewPool.clear();
        sMPhotoViewPool=null;
    }
}

在adapter初始化的時(shí)候,我們將對(duì)象池new出來(lái)苦银,并new出10個(gè)photoview添加到池里面啸胧。

在instantiateItem我們直接從池里面拿出來(lái),如果沒(méi)有幔虏,才創(chuàng)建吓揪。然后跟以前一樣,glide載入所计。

在destroyItem我們把view給remove掉柠辞,這樣可以防止在instantiateItem的時(shí)候在池里拿出的view擁有parent導(dǎo)致了異常的拋出。

最后記得提供destroy方法來(lái)清掉池的引用哦主胧。


Q2 - 關(guān)于PhotoView在ViewPager里面爆出的"ImageView no longer exists. You should not use this PhotoViewAttacher any more."錯(cuò)誤

如果您細(xì)心叭首,會(huì)發(fā)現(xiàn)我的代碼里寫的是MPhotoView而不是PhotoView

原因就是如小標(biāo)題。

在viewpager中踪栋,如果采用對(duì)象池的方式結(jié)合PhotoView來(lái)實(shí)現(xiàn)復(fù)用焙格,就會(huì)因?yàn)檫@個(gè)錯(cuò)誤而導(dǎo)致PhotoView的點(diǎn)擊事件無(wú)法相應(yīng)。

要解決這個(gè)問(wèn)題夷都,就必須得查看PhotoView的源碼眷唉。

首先我們找到這個(gè)錯(cuò)誤的提示位置

錯(cuò)誤位置

首先PhotoView的實(shí)現(xiàn)跟我們PhotoPagerMananger的實(shí)現(xiàn)思路差不多,都是將事件的處理委托給另一個(gè)對(duì)象囤官,這樣的好處是可以降低耦合度冬阳,其他的控件想實(shí)現(xiàn)類似功能會(huì)更簡(jiǎn)單。

在getImageView中党饮,如果imageview==null肝陪,就會(huì)log出這個(gè)錯(cuò)誤。

我們看看imageview的引用刑顺,在PhotoViewAttacher中氯窍,imageview是屬于弱引用,這樣可以更快的被回收蹲堂。

而imageview的清理則是在cleanup中

/**
     * Clean-up the resources attached to this object. This needs to be called when the ImageView is
     * no longer used. A good example is from {@link android.view.View#onDetachedFromWindow()} or
     * from {@link android.app.Activity#onDestroy()}. This is automatically called if you are using
     * {@link uk.co.senab.photoview.PhotoView}.
     */
    @SuppressWarnings("deprecation")
    public void cleanup() {
        if (null == mImageView) {
            return; // cleanup already done
        }

        final ImageView imageView = mImageView.get();

        if (null != imageView) {
            // Remove this as a global layout listener
            ViewTreeObserver observer = imageView.getViewTreeObserver();
            if (null != observer && observer.isAlive()) {
                observer.removeGlobalOnLayoutListener(this);
            }

            // Remove the ImageView's reference to this
            imageView.setOnTouchListener(null);

            // make sure a pending fling runnable won't be run
            cancelFling();
        }

        if (null != mGestureDetector) {
            mGestureDetector.setOnDoubleTapListener(null);
        }

        // Clear listeners too
        mMatrixChangeListener = null;
        mPhotoTapListener = null;
        mViewTapListener = null;

        // Finally, clear ImageView
        mImageView = null;
    }

那么現(xiàn)在問(wèn)題的出現(xiàn)就很明顯了狼讨,爆出這個(gè)錯(cuò)誤是因?yàn)閕mageview==null,也就是說(shuō)兩個(gè)可能:

  • 要么被執(zhí)行了cleanup
  • 要么就是引用的對(duì)象被銷毀了

第二點(diǎn)我們可以排除柒竞,因?yàn)槲覀冇袀€(gè)list來(lái)引用著photoview政供,所以只可能是第一個(gè)問(wèn)題。

最終,我們?cè)赑hotoView的onDetachedFromWindow找到了cleanup方法的調(diào)用

cleanup

還記得在ViewPager中我們的destroyItem嗎鲫骗,那里我們執(zhí)行的是container.remove(View),一個(gè)View在被remove的時(shí)候會(huì)回調(diào)onDetachedFromWindow踩晶。

而在PhotoView中执泰,回調(diào)的時(shí)候就會(huì)執(zhí)行attacher.cleanup,也就是說(shuō)attacher已經(jīng)沒(méi)有了imageview的引用渡蜻,然而我們的photoview卻是在我們的池里面术吝。

這樣導(dǎo)致的結(jié)果就是在下一次instantiateItem時(shí),從池里拿出的photoview里面的attacher根本就沒(méi)有imageview的引用茸苇,所以就會(huì)log出那個(gè)錯(cuò)誤排苍。

所以我們的解決方法就很明了了:

把photoview的代碼copy,注釋掉onDetachedFromWindow中的mattacher.cleanup学密,然后提供cleanup方法來(lái)手動(dòng)進(jìn)行attacher.cleanup淘衙,這樣就可以避免這個(gè)錯(cuò)誤了。

大概代碼如下:

/**
 * Created by 大燈泡 on 2016/4/14.
 *
 * 針對(duì)onDetachedFromWindow
 *
 * 因?yàn)镻hotoView在這里會(huì)導(dǎo)致attacher.cleanup腻暮,從而導(dǎo)致attacher的imageview=null
 * 最終無(wú)法在viewpager響應(yīng)onPhotoViewClick
 *
 * 這里將cleanup注釋掉彤守,把cleanup移到手動(dòng)調(diào)用方法中
 */
public class MPhotoView extends ImageView implements IPhotoView {
    private PhotoViewAttacher mAttacher;

    private ScaleType mPendingScaleType;

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

    public MPhotoView(Context context, AttributeSet attr) {
        this(context, attr, 0);
    }

    public MPhotoView(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
        super.setScaleType(ScaleType.MATRIX);
        init();
    }

    protected void init() {
        if (null == mAttacher || null == mAttacher.getImageView()) {
            mAttacher = new PhotoViewAttacher(this);
        }

        if (null != mPendingScaleType) {
            setScaleType(mPendingScaleType);
            mPendingScaleType = null;
        }
    }

...copy from photoview

    @Override
    protected void onDetachedFromWindow() {
        //mAttacher.cleanup();
        super.onDetachedFromWindow();
    }

    @Override
    protected void onAttachedToWindow() {
        init();
        super.onAttachedToWindow();
    }

    public void destroy(){
        setImageBitmap(null);
        mAttacher.cleanup();
        onDetachedFromWindow();
    }

}

至此,我們上一篇留下來(lái)的問(wèn)題全部解決哭靖。

下一篇具垫。。试幽。暫時(shí)沒(méi)想到做什么好筝蚕,大家有沒(méi)有什么提議的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铺坞,隨后出現(xiàn)的幾起案子起宽,更是在濱河造成了極大的恐慌,老刑警劉巖济榨,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燎含,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡腿短,警方通過(guò)查閱死者的電腦和手機(jī)屏箍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)橘忱,“玉大人赴魁,你說(shuō)我怎么就攤上這事《鄢希” “怎么了颖御?”我有些...
    開(kāi)封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我潘拱,道長(zhǎng)疹鳄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任芦岂,我火速辦了婚禮瘪弓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘禽最。我一直安慰自己腺怯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布川无。 她就那樣靜靜地躺著呛占,像睡著了一般。 火紅的嫁衣襯著肌膚如雪懦趋。 梳的紋絲不亂的頭發(fā)上晾虑,一...
    開(kāi)封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音仅叫,去河邊找鬼走贪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛惑芭,可吹牛的內(nèi)容都是我干的坠狡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼遂跟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼逃沿!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起幻锁,我...
    開(kāi)封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凯亮,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后哄尔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體假消,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年岭接,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了富拗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸣戴,死狀恐怖啃沪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情窄锅,我是刑警寧澤创千,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響追驴,放射性物質(zhì)發(fā)生泄漏械哟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一殿雪、第九天 我趴在偏房一處隱蔽的房頂上張望暇咆。 院中可真熱鬧,春花似錦冠摄、人聲如沸糯崎。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至年栓,卻和暖如春拆挥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背某抓。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工纸兔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人否副。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓汉矿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親备禀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洲拇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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