Android 帶動(dòng)畫的多選方案

先上圖理疙,看看今天開什么車从媚,坐穩(wěn)咯痹扇。拖拉機(jī)即將超速行使悯舟,請(qǐng)系好安全帶担租!

MultiSelector.gif

MultiSelecter

先來(lái)分析一下android中會(huì)遇到哪些選擇方面的需求:

  1. 單選--這個(gè)就不啰嗦了
  2. 多選:
    1. 全部數(shù)據(jù)都可以被選擇,這個(gè)比較簡(jiǎn)單
    2. 過(guò)濾掉一部分?jǐn)?shù)據(jù)抵怎,不讓顯示出來(lái)
    3. 過(guò)濾掉一部分?jǐn)?shù)據(jù)奋救,能顯示,但用戶不能選擇
    4. 默認(rèn)選擇一部分?jǐn)?shù)據(jù)反惕,用戶可以取消選擇
    5. 默認(rèn)選擇一部分?jǐn)?shù)據(jù)尝艘,用戶不可以取消選擇

原諒我還只遇到過(guò)這些,那這里都有哪些功能呢姿染?

  1. 多選時(shí)會(huì)有選擇過(guò)渡動(dòng)畫(如GIF里所見(jiàn)背亥,但肯定不能肯的這樣掉渣的)
  2. 點(diǎn)擊上面的頭像可以取消選擇
  3. 選中的數(shù)據(jù)條數(shù)提示
  4. 根據(jù)選擇的條目會(huì)將搜索欄向右移動(dòng),搜索樣最少占屏幕寬度的1/3
  5. 當(dāng)然還有模糊搜索功能啦
  6. 全選

啰啰嗦嗦講了一堆悬赏,看一下Gif圖就什么都知道了好么狡汉?
好吧,遇到像你們這些高智商的闽颇,還是直接開車好了

一盾戴、緣起:

早上9點(diǎn),程序猿小猿同學(xué)一如往常準(zhǔn)時(shí)的坐在自己的位置上进萄,又是燥熱的一天捻脖。擠了一個(gè)小時(shí)的地鐵,原本瘦消的身體越發(fā)覺(jué)得扁平了中鼠。小猿心想:我要再擠個(gè)一年,也會(huì)成A4腰哦沿癞,不是像A4紙那么寬援雇,而是像它那么扁。開機(jī)-洗水杯-吃早餐椎扬,小猿開啟了程式化的一天惫搏。

小猿剛叼起一個(gè)小籠包,還沒(méi)來(lái)得及體會(huì)里面的美味蚕涤,產(chǎn)品經(jīng)理輕輕拍了下他的肩膀筐赔。直勾勾的看著小猿眼睛說(shuō):“昨天那個(gè)選擇頁(yè)面要做一個(gè)已經(jīng)選擇條目頭像展示的功能∫就”小猿剛想說(shuō)我cao,產(chǎn)品經(jīng)理連忙說(shuō)茴丰,中午下班前看下效果。小猿差點(diǎn)沒(méi)把小籠包整個(gè)咽下去,早TM干嗎去了贿肩,昨天晚上加班趕出來(lái)的峦椰,又得改,操蛋玩意兒汰规,小猿心理罵道汤功。

快速解決了小籠包,迅速進(jìn)入到戰(zhàn)斗狀態(tài)溜哮。好在這個(gè)不是太難實(shí)現(xiàn)滔金,只是在數(shù)據(jù)傳遞方面要下點(diǎn)功夫。在飯點(diǎn)前總算一切搞掂茂嗓,翹著二郎腿對(duì)產(chǎn)品說(shuō)餐茵,你要的頭像展示功能OK了。產(chǎn)品聽(tīng)完悠悠的轉(zhuǎn)過(guò)身在抛,肯定道:嗯嗯钟病,不錯(cuò),是我想要的刚梭。不過(guò)感覺(jué)好像還少了點(diǎn)什么肠阱,哦,對(duì)了朴读,這個(gè)頁(yè)面條目太多屹徘,用戶可能看不過(guò)來(lái),需要一個(gè)搜索功能衅金。放在這些頭像同一排就好了噪伊,就微信那樣。說(shuō)完拍拍小猿的肩膀氮唯,跟其它同事出去吃飯去了鉴吹,留下小猿在風(fēng)中凌亂。

小猿點(diǎn)了個(gè)外賣惩琉,然后想著剛剛這個(gè)需求要怎么實(shí)現(xiàn)豆励。突然小猿用力的拍了一下桌子,這樣下去不是辦法瞒渠,以后還哪里敢吃小籠包良蒸,只能喝粥度日了。我得趕在那貨之前弄個(gè)比較全面的解決方案伍玖,小猿對(duì)自己斬釘截鐵的說(shuō)到嫩痰。

小猿在想著他的對(duì)策,首先不能跟某一塊耦合了窍箍,萬(wàn)一其它地方也要用到呢串纺,那不是尷尬了丽旅?功能得盡可能的全面些,多選造垛,數(shù)據(jù)過(guò)濾魔招,單選....甚至還可以來(lái)得動(dòng)畫。小猿仿佛看到了自己對(duì)于需求應(yīng)對(duì)自如的樣子....一絲冷風(fēng)吹過(guò)五辽,吹醒了正在做白日夢(mèng)的小猿办斑。

二、 抽象:

說(shuō)干就干杆逗,首先得解決的是如何解耦乡翅,得用接口,接口是對(duì)現(xiàn)實(shí)的抽象罪郊。有了思路剩下的就是手速了蠕蚜,像小猿這種單身20多年的,手速當(dāng)然快如閃電悔橄,要不能上磚石靶累?

  1. 先造一個(gè)能判斷數(shù)據(jù)是何種選擇類型的接口,返回不同條目類型(可選癣疟、不可選 ....)挣柬,像這樣:
public interface Filter {

    //專為標(biāo)題而生,因?yàn)橄到y(tǒng)默認(rèn)給的是0睛挚,這樣title Bean類里面都不用做過(guò)多的修改了
    int TITLE_NO_CHOICE = 0;

    //默認(rèn)不選中邪蛔,可以選中
    int NORMAL = 1;

    //默認(rèn)選中,不可以取消選中
    int SELECTED_NOCANCEL = 2;

    //默認(rèn)不選中,不能被選中
    int NO_CHOICE = 3;

    //不顯示在列表
    int NOT_SHOW = 4;

    //本地圖片地址
    int getImageResource();

    //網(wǎng)絡(luò)圖片url
    String getImageUrl();

    //返回當(dāng)前條目的狀態(tài),就是上面定義的那些個(gè)常量扎狱,返回值會(huì)在BaseViewHolder里面用到
    int filter();

    //是否是選中狀態(tài)
    boolean isSelected();

    void setSelected(boolean isSelected);

    //是否匹配搜索關(guān)鍵字侧到,用來(lái)處理搜索的,如果不要搜索功能淤击,可以不用處理
    boolean isMatch(String condition);
}

這樣只要每個(gè)具體bean 類去實(shí)現(xiàn)
在filter方法里去根據(jù)不同的條件返回上面定義的常量
isMatch方法是針對(duì)模糊搜索設(shè)計(jì)的
機(jī)智如我匠抗,看你還怎么改需求,小猿暗自竊喜...

  1. 圖片加載框架現(xiàn)在有好幾個(gè)污抬,搞不好哪個(gè)以后就不維護(hù)了戈咳,我可不能在一棵樹上吊死,小猿警惕起來(lái)壕吹,順手?jǐn)]了個(gè)圖片加載框架的接口:
public interface IImageLoader {
    void showImage(Context context, String url, ImageView imageView);
}

以后項(xiàng)目想用哪個(gè)圖片框架只需要根據(jù)當(dāng)前項(xiàng)目使用的圖片加載框架實(shí)現(xiàn)對(duì)應(yīng)的ImageLoader就可以了,就是這么任性

三删铃、實(shí)施:

大致思路是有了耳贬,具體要怎么實(shí)現(xiàn)這些功能呢?小猿摸著日益上揚(yáng)的發(fā)跡線猎唁,沉思良久....

  1. 不需要展示給用戶的數(shù)據(jù)過(guò)濾倒是好做,可以像下面這樣的呀:
protected List<T> getFilterItems(List<T> items) {
        mSelectionList.clear();
        if (items != null) {
            List<T> data = new ArrayList<>();
            for (T item : items) {
                int type = item.filter();
                if (type != Filter.NOT_SHOW) {
                    data.add(item);
                    if (type != Filter.NO_CHOICE&&type!=Filter.TITLE_NO_CHOICE) {
                        mSelectionList.add(item);
                    }
                }
            }
            return data;
        } else {
            return null;
        }
    }
  1. 如果是正常的數(shù)據(jù)咒劲,既要支持多選又能支持單選,這個(gè)要怎么處理比較好呢?毫無(wú)頭緒腐魂,一不小心干掉幾根本來(lái)就屈指可數(shù)的頭發(fā)帐偎,抱著試試的心態(tài)寫了下面的代碼:
  public void setData(T data) {
        normalBackgroundResource = getNormalBackgroundResource();
        noChoiceBackgroundResource = getNoChoiceBackgroundResource();
        int type = data.filter();
        if (mCheckBox != null) {
            mCheckBox.setChecked(data.isSelected());
        }
        if (type == Filter.NORMAL) {
            onNormal(data);
        } else if (type == Filter.NO_CHOICE) {
            onNoChoice();
        }
    }

  private void setClickListener(final Filter data) {
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (selectType == SelectionFragment.MULTI_SELECT) {
                    multiSelect(data);
                } else {
                    singleSelect(data);
                }
            }
        });
    }

   private void singleSelect(Filter data) {
        if (mListener == null) {
            throw new IllegalStateException("沒(méi)有設(shè)置點(diǎn)擊事件監(jiān)聽(tīng)");
        }
        if (mCurrentCheckBox != null) {
            mCurrentCheckBox.setChecked(false);
            mCurrentItem.setSelected(false);
            mListener.onItemClick(itemView, mCurrentItem, false);
        }
        data.setSelected(true);
        mCheckBox.setChecked(true);
        mListener.onItemClick(itemView, data, true);
        mCurrentCheckBox = mCheckBox;
        mCurrentItem = data;
    }

寫完心理在打鼓,不知道好不好使蛔屹,反正試下又不要錢削樊。經(jīng)過(guò)漫長(zhǎng)的等待,程序總算部署完畢兔毒,這么個(gè)小項(xiàng)目編譯居然還兩分鐘漫贞,還天天嫌我效率低,小猿抱怨道育叁。試了下單選功能迅脐,Prefect!簡(jiǎn)直不要太如我意豪嗽,哈哈谴蔑。嘗到甜頭的小猿準(zhǔn)備再試試多選功能,我草龟梦,還是那么完美隐锭。機(jī)智如我,啦啦啦....差點(diǎn)唱起了歌

3 . 那如果是需要展示变秦,但是不能操作的呢成榜?這個(gè)就簡(jiǎn)單了,隨手就擼了一個(gè)出來(lái):

   public void onNoChoice() {
        if (mCheckBox != null) {
            mCheckBox.setBackgroundResource(noChoiceBackgroundResource);
            itemView.setOnClickListener(null);
        }
    }

機(jī)智如我蹦玫,啦啦啦....對(duì)于小猿大神我來(lái)說(shuō)赎婚,都是小菜一碟。小猿得意的哼起了歌樱溉,得意得有點(diǎn)欠揍

是時(shí)候解決產(chǎn)品提的那兩個(gè)需求了:

展示頭像倒是沒(méi)難度的挣输,關(guān)鍵是如何讓搜索根據(jù)選擇條目的數(shù)量動(dòng)態(tài)改變寬度?能不能計(jì)算出當(dāng)前RecyclerView占用的寬度呢福贞?如果能知道的話事情不就解決了嗎撩嚼?嗯嗯,擼串代碼測(cè)試一下:

private void refreshLayout(boolean isSelected) {
        mIvSelectAll.setSelected(isSelected);

        if (mAdapter.getSelectionList().size() == mIconListRvAdapter.getItemCount()) {
            mIvSelectAll.setSelected(true);
        }

        int size = mSelectList.size();
        mTvConfirm.setText(size == 0 ? "確定" : "確定(" + size + ")");
        if (size == 0) {
            mTvConfirm.setEnabled(false);
        } else {
            mTvConfirm.setEnabled(true);
        }

        int width = mItemWidth * size;
        if (width > mMaxWidth) {
            width = mMaxWidth;
        }
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, LinearLayout.LayoutParams.WRAP_CONTENT);
        mIconRecyclerView.setLayoutParams(params);
        mContainer.requestLayout();
    }

完美挖帘、完美完丽、完美、簡(jiǎn)直不要太完美拇舀。這里主要做三件事:
如果手動(dòng)選擇時(shí)逻族,所有的條目都被選中,全選按鈕也會(huì)變成選中狀態(tài);
設(shè)置確定按鈕的選中條目的數(shù)量骄崩,并根據(jù)數(shù)量設(shè)置確定按鈕是否可點(diǎn)擊;
動(dòng)態(tài)改變搜索欄的寬度
mItemWidth是怎么計(jì)算的聘鳞?

  private void initData() {
        int screenWidth = ScreenUtils.getScreenWidth(mContext);
        mMaxWidth = screenWidth * 2 / 3;
        mItemWidth = SizeUtils.dp2px(mContext, 45);
        mWidth5 = SizeUtils.dp2px(mContext, 5);
    }

你沒(méi)看錯(cuò)薄辅,寫死了,可惜不能插入捂臉的表情抠璃。RecyclerView一個(gè)item占用45dp站楚,這個(gè)在寫布局的時(shí)候就已經(jīng)知道了。當(dāng)然這種硬編碼可不是個(gè)好習(xí)慣哦搏嗡,不要學(xué)習(xí)窿春。

四、進(jìn)化:

嘗到甜頭的小猿現(xiàn)在感覺(jué)自己無(wú)所不能彻况,哎呀谁尸,這個(gè)效果我還是很不滿意呀,為了展示逼格得加個(gè)動(dòng)畫不可纽甘。經(jīng)過(guò)千辛萬(wàn)苦良蛮,各種嘗試,總算有了能用的代碼:

public void translationView(final View itemView, final Filter item) {
        getParentPoint();
        itemView.setClickable(false);
        final FloatImgBean floatImg = getFloatImg();
        floatImg.mImageView.setVisibility(View.VISIBLE);
        mPlaceHolder.setVisibility(View.VISIBLE);
        floatImg.mImageView.setImageResource(item.getImageResource());
        MultiSelecter.mImageLoader.showImage(mContext, item.getImageUrl(), floatImg.mImageView);
        floatImg.mIsAnimator = true;

        int[] sourceLocation = new int[2];
        mSourceView.getLocationOnScreen(sourceLocation);
        int startX = sourceLocation[0];
        int startY = sourceLocation[1];

        int[] tagetLocation = new int[2];
        mIconRecyclerView.getLocationOnScreen(tagetLocation);
        int endX = tagetLocation[0] + mIconRecyclerView.getWidth() + mWidth5;

        int endY = tagetLocation[1] + mWidth5 * 2;

        animator(itemView, item, floatImg, startX, startY, endX, endY);
    }

    private void animator(final View itemView, final Filter item, final FloatImgBean floatImg, int startX, int startY, int endX, int endY) {
        ObjectAnimator animatorX = ObjectAnimator.ofFloat(floatImg.mImageView, "translationX", startX - mStartX, endX - mStartX);
        ObjectAnimator animatorY = ObjectAnimator.ofFloat(floatImg.mImageView, "translationY", startY - mStartY, endY - mStartY);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(animatorX, animatorY);
        animatorSet.setDuration(calcDuration(startX - endX, startY - endY));
        animatorSet.setInterpolator(new OvershootInterpolator(1.1f));
        animatorSet.start();
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                floatImg.mImageView.setVisibility(View.GONE);
                floatImg.mIsAnimator = false;
                mIconListRvAdapter.add(item);
                mIconRecyclerView.smoothScrollToPosition(mIconListRvAdapter.getItemCount());
                mPlaceHolder.setVisibility(View.GONE);
                refreshLayout(false);
                itemView.setClickable(true);
            }
        });
    }

這里小猿可是踩了無(wú)數(shù)坑,這里可以詳細(xì)說(shuō)下。敲黑板固逗,這里可以高潮部分,就不要打瞌睡啦皮胡!

首先是getLocationOnScreen 這個(gè)操蛋的方法,網(wǎng)上一致說(shuō)這個(gè)獲得的是當(dāng)前view相當(dāng)于整個(gè)屏的坐標(biāo)位置赏迟,根據(jù)android坐標(biāo)系的尿性屡贺,那屏幕最左上角就是原點(diǎn)咯,那我通過(guò)這個(gè)方法就是能獲得頂部頭像欄內(nèi)條目的絕對(duì)坐標(biāo)了咯锌杀,簡(jiǎn)直不要太爽甩栈。
然并卵,根本不是那么回事好嗎糕再?直到現(xiàn)在為止量没,小猿仍然沒(méi)有搞懂這個(gè)方法獲取的坐標(biāo)會(huì)受到哪些因素的影響。但是可以肯定的是如果獲取Item的坐標(biāo)會(huì)出現(xiàn)偏移突想,貌似跟padding有關(guān)殴蹄,有知道的可以在評(píng)論區(qū)解答。
但是獲取mIconRecyclerView的坐標(biāo)是沒(méi)有問(wèn)題的猾担,這樣我只要計(jì)算mIconRecyclerView的寬度就可以知道X坐標(biāo)了袭灯。

android的屬性動(dòng)畫執(zhí)行過(guò)程中,如果執(zhí)行了另外的屬性動(dòng)畫绑嘹,會(huì)中斷之前的執(zhí)行妓蛮,導(dǎo)致動(dòng)畫監(jiān)聽(tīng)發(fā)生錯(cuò)亂。
整個(gè)邏輯全都亂套了圾叼,為此小猿想出了一個(gè)奇淫巧技蛤克,java不是有線程池么?為什么我不能弄一個(gè)ImageView的Pool,裝上幾個(gè)ImageView夷蚊,沒(méi)有在執(zhí)行動(dòng)畫的取出來(lái)用构挤,執(zhí)行動(dòng)畫的讓它自己玩去。于是有了下面這個(gè):

private void initFloatPool() {
        FloatImgBean bean1 = new FloatImgBean();
        bean1.mImageView = mFloatImg_1;
        FloatImgBean bean2 = new FloatImgBean();
        bean2.mImageView = mFloatImg_2;
        FloatImgBean bean3 = new FloatImgBean();
        bean3.mImageView = mFloatImg_3;
        mImagePool.add(bean1);
        mImagePool.add(bean2);
        mImagePool.add(bean3);
    }

    private FloatImgBean getFloatImg() {
        for (FloatImgBean bean : mImagePool) {
            if (!bean.mIsAnimator) {
                return bean;
            }
        }
        return null;
    }

當(dāng)然這個(gè)用FloatImgBean 包裝了一下惕鼓,記錄了當(dāng)前ImageView是否有在執(zhí)行動(dòng)畫筋现。
為了讓動(dòng)畫的執(zhí)行更自然作出了一個(gè)犧牲,在mIconRecyclerView和搜索欄中間加了一個(gè)和mIconRecyclerView 的Item等寬的一個(gè)view,在動(dòng)畫執(zhí)行的過(guò)程中設(shè)置成VISIBLE或者GONE來(lái)迎合動(dòng)畫的執(zhí)行箱歧。

五矾飞、示例:

完成了所有的功能,小猿癱坐在電腦椅上洒沦,臉上露出滿意的微笑价淌。
忽然小猿虎軀一震蝉衣,不行病毡,我還得寫個(gè)示例啦膜,不然怎么在人前裝逼呢功戚?
先實(shí)現(xiàn)一個(gè)Bean 類:

public class UserBean implements Filter {
    public String userName;
    public int icon;
    public int age;
    public boolean isSelected;
    public String iconUrl;

    @Override
    public boolean isSelected() {
        return isSelected;
    }

    @Override
    public void setSelected(boolean isSelected) {
        this.isSelected = isSelected;
    }

    @Override
    public int getImageResource() {
        return icon;
    }

    @Override
    public String getImageUrl() {
        return iconUrl;
    }

    @Override
    public int filter() {
        if (age<3){
            return Filter.NO_CHOICE;
        }else if (age>=3&&age<100){
            return Filter.NORMAL;
        }
        return 0;
    }

    @Override
    public boolean isMatch(String condition) {
        if (MatchUtils.isMatch(userName,condition)){
            return true;
        }
        return false;
    }
}

如何調(diào)用那封裝好的東西呢啸臀?

MultiSelectView selectView = new MultiSelecter.Builder(this, container)
               .setImageLoader(new GlideImageLoader())
               .setMultiAdapter(new UserAdapter())
               .setSelectType(MultiSelecter.MULTI_SELECT)
               .register(UserBean.class, R.layout.item_user)
               .register(TitleBean.class, R.layout.item_title)
               .build();

當(dāng)然還得來(lái)一個(gè)ImageLoader的示例:

public class GlideImageLoader implements IImageLoader {
    @Override
    public void showImage(Context context, String url, ImageView imageView) {
        Glide.with(context)
                .load(url)
                .into(imageView);
    }
}

哦了豌注,好累灯萍,小猿來(lái)了個(gè)葛優(yōu)躺....

用到的開源項(xiàng)目:
AutoRecycleView:自動(dòng)維護(hù)下拉刷新和上拉加載更多
SimpleMutiTypeAdapter :使用起來(lái)很簡(jiǎn)單的RecyclerView多條目
沒(méi)錯(cuò)齿风,都是小猿之前為了應(yīng)付需求改動(dòng)寫的。

源碼地址:MultiSelecter

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市穷娱,隨后出現(xiàn)的幾起案子泵额,更是在濱河造成了極大的恐慌嫁盲,老刑警劉巖亡资,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異瘦黑,居然都是意外死亡幸斥,警方通過(guò)查閱死者的電腦和手機(jī)甲葬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門经窖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)画侣,“玉大人配乱,你說(shuō)我怎么就攤上這事搬泥。” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)兽掰。 經(jīng)常有香客問(wèn)我孽尽,道長(zhǎng)杉女,這世上最難降的妖魔是什么熏挎? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮哼勇,結(jié)果婚禮上积担,老公的妹妹穿的比我還像新娘帝璧。我一直安慰自己聋溜,他們只是感情好撮躁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布杨帽。 她就那樣靜靜地躺著注盈,像睡著了一般老客。 火紅的嫁衣襯著肌膚如雪胧砰。 梳的紋絲不亂的頭發(fā)上尉间,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音眠副,去河邊找鬼。 笑死光涂,一個(gè)胖子當(dāng)著我的面吹牛忘闻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炼吴,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼童芹!你這毒婦竟也來(lái)了署咽?” 一聲冷哼從身側(cè)響起宁否,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瑟由,失蹤者是張志新(化名)和其女友劉穎歹苦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚪腋,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眼溶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年灌旧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枢泰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谋右,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辈挂,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響债朵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芝加,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一蝌麸、第九天 我趴在偏房一處隱蔽的房頂上張望来吩。 院中可真熱鬧戚长,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蹲缠。三九已至,卻和暖如春确买,著一層夾襖步出監(jiān)牢的瞬間斤讥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工湾趾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芭商,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓搀缠,卻偏偏與公主長(zhǎng)得像铛楣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艺普,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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